diff --git a/.gitignore b/.gitignore index 37913175b56b..b28d3d6e7964 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,7 @@ ObjectStore # Profiler and heap dumps *.jps *.hprof + +# Maven Enhance Plugin +tooling/hibernate-enhance-maven-plugin/src/main/resources/pom.xml +tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/plugin.xml diff --git a/build.gradle b/build.gradle index 777f41157f51..6843e139740c 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ buildscript { ext { expectedGradleVersion = '1.9' - hibernateTargetVersion = '4.3.0-SNAPSHOT' + hibernateTargetVersion = '5.0.0-SNAPSHOT' javaLanguageLevel = '1.6' osgiExportVersion = hibernateTargetVersion.replaceAll( "-SNAPSHOT", ".SNAPSHOT" ) @@ -137,6 +137,7 @@ subprojects { subProject -> dependencies { compile( libraries.logging ) compile( libraries.logging_annotations ) + compile( libraries.logging_processor ) testCompile( libraries.junit ) testCompile( libraries.byteman ) @@ -152,8 +153,11 @@ subprojects { subProject -> jaxb( libraries.jaxb ){ exclude group: "javax.xml.stream" } + jaxb( libraries.jaxb ) jaxb( libraries.jaxb2_basics ) jaxb( libraries.jaxb2_ant ) + jaxb( libraries.jaxb2_jaxb ) + jaxb( libraries.jaxb2_jaxb_xjc ) animalSniffer ( libraries.animal_sniffer ) javaApiSignature ( libraries.java16_signature ) diff --git a/documentation/src/main/asciidoc/topical/accesstype/AccessType.adoc b/documentation/src/main/asciidoc/topical/accesstype/AccessType.adoc new file mode 100644 index 000000000000..e0c658a8585b --- /dev/null +++ b/documentation/src/main/asciidoc/topical/accesstype/AccessType.adoc @@ -0,0 +1,307 @@ += AccessType +:toc: + +The JPA `javax.persistence.AccessType` enum actually represents 3 related concepts: + +. Determining which fields/methods constitute a persistent attribute. +. Indicating where to look for mapping annotations for each persistent attribute. +. How the attribute (its value) is accessed at runtime + +Unfortunately the JPA specification is not overly clear about how the AccessType value defines the +answers to these 3 questions in all cases. Often that is left up to each provider to decide. So here we will +discuss how Hibernate answers the 3 AccessType-related questions in different situations. By default, Hibernate +tries to keep the explanation for how it answers these questions simple. AccessType defines 2 possible values: FIELD +and PROPERTY. + +For Hibernate, PROPERTY access means that: + +. A persistent attribute is identified by its JavaBeans-style getter and setter on a Class +. The mapping annotations for the persistent attribute are located on the Class getter method +. At runtime we access the persistent attribute's value via the getter/setter methods. + +IMPORTANT: Placing annotations on setters is NEVER appropriate. + + +FIELD access means that: + +. A persistent attribute is identified by its Class field +. The mapping annotations for the persistent attribute are located on the Class field +. At runtime we access the persistent attribute's value directly via the field. + + +== Implicit (hierarchy) access type + +The implicit access type for an entity hierarchy defines how access type is defined when there is no explicitly +defined AccessType. To determine implicit hierarchy access type, Hibernate looks for the annotation marking the +identifier for the entity hierarchy (either @Id or @EmbeddedId). The placement (field or getter) defines the implicit +access type for the hierarchy. Let's look at an example: + + +[[hierarchy-level-field]] +.Hierarchy-level FIELD access +==== +[source, JAVA] +---- +@Entity +public class Document { + @Id + private Integer id; + private String title; + @Lob + private Clob content; + + @Transient + private int hashCode; +} + +@Entity +public class PublishedDocument extends Document { + private String isbn; + @Temporal(DATE) + private Date publishDate; +} +---- +==== + +Here we have implicit hierarchy-level field access because of the placement of @Id on a field, which means: + +. We look at the declared fields for each class to determine its persistent attributes. For the `Document` class, + that means we have 3 fields that would be considered persistent attributes: `id`, `title`, and `content`; for + `PublishedDocument` we have 2: `isbn` and `publishDate`. Given field "access type", to indicate that a particular + field is not persistent, the field would be annotated with the `javax.persistence.Transient` annotation; here we + see an example of that for the `hashCode` field. +. We use the annotations attached to those fields as the mapping annotations for the persistent attribute it indicates. + Annotations on the getter associated with that field (if one/any) are ignored (although we do try to log warnings + in such cases). +. In terms of runtime access, Hibernate will use direct field access (via reflection) to get and set attribute values + using `java.lang.reflection.Field`. + + +Implicit property access works similarly: + +[[hierarchy-level-property]] +.Hierarchy-level PROPERTY access +==== +[source, JAVA] +---- +@Entity +public class Document { + private Integer id; + private String title; + private Clob content; + + @Id + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + + @Lob + public Clob getContent() { return content; } + public void setContent(Clob content) { this.content = content; } +} + +@Entity +public class PublishedDocument extends Document { + private String isbn; + private Date publishDate; + + public String getIsbn() { return isbn; } + public void setIsbn(String isbn) { this.isbn = isbn; } + + @Temporal(DATE) + public Date getPublishDate() { return publishDate; } + public void setPublishDate(Date publishDate) { this.publishDate = publishDate; } +} +---- +==== + +In this case, we have implicit hierarchy-level property access because of the placement of @Id on the getter, +which here means: + +. We look at the declared methods for each class looking for JavaBean-style getters to determine the persistent + attributes for that class. For the `Document` class, we have 3 getters that would indicate persistent attributes: + `getId()`, `getTitle()` and `getContent()`; for `PublishedDocument` we have 2: `getIsbn()` and `getPublishDate()`. + The "attribute name" is taken following JavaBean-conventions. To indicate that a getter does is not indicate a + persistent attribute, the getter would be annotated with the `javax.persistence.Transient` annotation. +. We use the annotations attached to those getter methods as the mapping annotations for the persistent attribute + it indicates. Annotations on the field associated with that getter (if one/any) are ignored (although, again, we do + try to log warnings in such cases). +. In terms of runtime access, Hibernate will use getter/setter access (via reflection) to get and set attribute values + using `java.lang.reflection.Method`. + + +== Explicit access type + +Access type may also be explicitly indicate via the `javax.persistence.Access` annotation, which can be applied to +either a class or attribute. + + +=== Class-level + +Annotating a class (`MappedSuperclass`, `Entity`, or `Embeddable`) applies the indicated access type to the class, +although not its superclass nor subclasses. Let's go back to the <> where we saw +implicit hierarchy-level field access. But lets instead use `javax.persistence.Access` and see what affect that has: + + +[[class-level-property]] +.Class-level PROPERTY access +==== +[source, JAVA] +---- +@Entity +public class Document { + @Id + private Integer id; + private String title; + @Lob + private Clob content; +} + +@Entity +@Access(PROPERTY) +public class PublishedDocument extends Document { + private String isbn; + private Date publishDate; + + public String getIsbn() { return isbn; } + public void setIsbn(String isbn) { this.isbn = isbn; } + + @Temporal(DATE) + public Date getPublishDate() { return publishDate; } + public void setPublishDate(Date publishDate) { this.publishDate = publishDate; } +} +---- +==== + +The hierarchy still has an implicit field access type. The `Document` class implicitly uses field access as the +hierarchy default. The `PublishedDocument` class however overrides that to say that it uses property access. This +class-level `javax.persistence.Access` override is only in effect for that class; if another entity extended from +`PublishedClass` and did not specify a `javax.persistence.Access`, that entity subclass would use field access +as the hierarchy default. But in terms of the `PublishedDocument` class, it has the same effect we saw in the +<>: + +. We look at the declared methods for `PublishedDocument` to determine the persistent attributes, here: + `getIsbn()` and `getPublishDate()`. +. We use the annotations attached to those getter methods as the mapping annotations. +. We will use getter/setter runtime access. + + +Similarly, the explicit class-level access type can be set to FIELD: + +[[class-level-field]] +.Class-level FIELD access +==== +[source, JAVA] +---- +@Entity +public class Document { + private Integer id; + private String title; + private Clob content; + + @Id + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + + public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + + @Lob + public Clob getContent() { return content; } + public void setContent(Clob content) { this.content = content; } +} + +@Entity +@Access(PROPERTY) +public class PublishedDocument extends Document { + private String isbn; + @Temporal(DATE) + private Date publishDate; +} +---- +==== + + +=== Attribute-level + + +JPA also says that access type can be explicitly specified on an individual attribute... + + + + + + +== Extensions + +As discussed above, whether defined implicitly or explicitly, the notion of access type controls: + +. identifying persistent attributes +. locating each persistent attribute's mapping information +. runtime access to each persistent attribute. + +Regardless of implicit/explicit the following are always true: + +* FIELD access always indicates runtime access via direct field access +* PROPERTY access always indicates runtime access via getter/setter + +In terms of default behavior: + +* Given FIELD access, all mapping annotations are expected to be placed on the corresponding class field +* Given PROPERTY access, all mapping annotations are expected to be placed on the corresponding class getter method + + +That being said, Hibernate offers a number of extensions that affect these statements... + + +=== PropertyAccessor + +Thus far we have focused on FIELD and PROPERTY runtime access because those are the strategies defined by JPA. +Hibernate, however, has a more open-ended strategy for runtime access defined by the +`org.hibernate.property.PropertyAccessor`. + +NOTE: Hibernate's use of the phrase "property" here pre-dates JPA. Think of "property accessor" as "attribute accessor". + +`org.hibernate.property.PropertyAccessor` essentially defines contract for extracting (`org.hibernate.property.Getter`) +and injecting (`org.hibernate.property.Setter`) attribute values at runtime. To specify a custom runtime access +strategy, simply use the `org.hibernate.annotations.AttributeAccessor` annotation: + +[[custom-accessor]] +.Custom PropertyAccessor +==== +[source, JAVA] +---- +@Entity +public class Document { + ... + + @Id + @AttributeAccessor( "com.acme.CustomHibernateIdPropertyAccessor" ) + public Integer getId() { return id; } + ... +} +---- +==== + +`org.hibernate.annotations.AttributeAccessor` can also be specified at the class-level to apply to all attributes +for the annotated class. + + +=== PersistentAttributeMemberResolver + +The `org.hibernate.metamodel.spi.PersistentAttributeMemberResolver` contract allows swapping the manner in +which Hibernate decides which fields/methods constitute a persistent attribute. The information described above is +in accordance with the standard, default resolver : +`org.hibernate.metamodel.spi.StandardPersistentAttributeMemberResolver`. This standard implementation follows the +JPA very closely in not allowing certain things, although it always warns or throws an exception when ignoring or +not allowing things. + +Hibernate ships with another resolver implementation : `org.hibernate.metamodel.spi.LenientPersistentAttributeMemberResolver` +As its name implies, it aims at being more lenient that what is mandated by JPA specification. + +TODO : discuss specific leniencies + +To specify alternate PersistentAttributeMemberResolver to use (whether a Hibernate-provided one or a custom one), use +the `org.hibernate.metamodel.MetadataBuilder.with(PersistentAttributeMemberResolver)` method. \ No newline at end of file diff --git a/documentation/src/main/asciidoc/topical/index.adoc b/documentation/src/main/asciidoc/topical/index.adoc index 1cf2e3b4c259..b70c5e69fc7c 100644 --- a/documentation/src/main/asciidoc/topical/index.adoc +++ b/documentation/src/main/asciidoc/topical/index.adoc @@ -9,6 +9,7 @@ NOTE: This is still very much a work in progress. <> is definitely == User Guides * For information on generated (non-identifier) values, see the <> +* For information on logging, see <> * Others coming soon == Tooling diff --git a/documentation/src/main/asciidoc/topical/logging/Logging.adoc b/documentation/src/main/asciidoc/topical/logging/Logging.adoc new file mode 100644 index 000000000000..6600097271b4 --- /dev/null +++ b/documentation/src/main/asciidoc/topical/logging/Logging.adoc @@ -0,0 +1,92 @@ += Logging Guide +:toc: + +Since version 4.0, Hibernate has used the JBoss Logging library for its logging needs. Like SLF4J and +Jakarta's commons-logging, JBoss Logging is a "logging bridge" providing integration with numerous logging +frameworks. JBoss Logging was chosen because of its i18n support and its support for "message ids". This is largely +the seminal documentation of JBoss Logging since JBoss Logging currently provides no documentation of its own. + + +== Supported Back-ends + +JBoss Logging understands the following back-ends as first-class citizens: + +. JBoss LogManager (mainly used only inside the WildFly app server) +. Log4j 2 +. Log4j 1 +. Slf4j +. JDK logging + +Note the order above, it is important. By default JBoss Logging will search the ClassLoader for the availability of +classes that indicate one of the above "providers" being available. It does this in the order defined above. So, +for example, if you have both JBoss LogManager and Slf4j available your classpath then JBoss LogManager will be used +as it has the "higher precedence". + +This can sometimes lead to an unwanted logging set up to be used. In such cases, JBoss Logging provides for you to +tell it specifically which provider to use and circumvent the discovery process just described. It allows 2 different +mechanisms for this: + +. First, JBoss Logging will look for a *System* setting with the key `org.jboss.logging.provider`, which can be set to +one of the following values: + + * jboss + * jdk + * log4j2 + * log4j + * slf4j + +. Next, JBoss Logging will look for a JDK service (see javadocs for +java.util.ServiceLoader+ for details) for its +"provider" contract (+org.jboss.logging.Provider+). If multiple are available, it will use the first one returned by +the ClassLoader. + + +== Usage + +Most of the time, the discovery process JustWorks. The discovery process relies on the jars available on the classpath. +The jboss-logging jar is a required dependency of Hibernate and therefore will always need to be on the classpath. + +* To use JBoss Logging with Log4j, the log4j jar would also need to be available on the classpath. +* To use JBoss Logging with Log4j2, the log4j2 jar would also need to be available on the classpath. +* To use JBoss Logging with Slf4j, the slf4j-api jar would also need to be available on the classpath *plus* any needed +slf4j backend. + +JDK Logging would be used if none of the other framework jars are available. + + +== Log Categories of Interest + +It is recommended that you familiarize yourself with the log messages sent from Hibernate. A lot of work has been put +into making the Hibernate loggiong as detailed as possible, without making it unreadable. It is an essential +troubleshooting device. Some log categories of particular interest include: + +.Hibernate Log Categories of Interest +|=== +|Category|Description + +|org.hibernate.SQL +|Log all SQL statements as they are executed with through JDBC + +|org.hibernate.type.descriptor.sql +|Log all values as they are bound to JDBC parameters and extracted from JDBC results + +|org.hibernate.tool.hbm2ddl +|Log all SQL DDL statements as they are executed during execution of any of the schema migration tools + +|org.hibernate.pretty +|Log the state of all entities (max 20 entities) associated with the session at flush time + +|org.hibernate.cache +|Log all second-level cache activity + +|org.hibernate.hql.internal.ast.AST +|Log HQL and SQL ASTs during query parsing + +|org.hibernate +|Log everything. This is a lot of information but it is useful for troubleshooting +|=== + + +== Message Id Index + +Coming soon. + diff --git a/documentation/src/main/docbook/devguide/en-US/Database_Access.xml b/documentation/src/main/docbook/devguide/en-US/Database_Access.xml index 481a7e758c84..b19ca70a6c97 100644 --- a/documentation/src/main/docbook/devguide/en-US/Database_Access.xml +++ b/documentation/src/main/docbook/devguide/en-US/Database_Access.xml @@ -266,110 +266,365 @@ - - DB2 - org.hibernate.dialect.DB2Dialect - - - DB2 AS/400 - org.hibernate.dialect.DB2400Dialect - - - DB2 OS390 - org.hibernate.dialect.DB2390Dialect - - - Firebird - org.hibernate.dialect.FirebirdDialect - - - FrontBase - org.hibernate.dialect.FrontbaseDialect - - - HypersonicSQL - org.hibernate.dialect.HSQLDialect - - - Informix - org.hibernate.dialect.InformixDialect - - - Interbase - org.hibernate.dialect.InterbaseDialect - - - Ingres - org.hibernate.dialect.IngresDialect - - - Microsoft SQL Server 2005 - org.hibernate.dialect.SQLServer2005Dialect - - - Microsoft SQL Server 2008 - org.hibernate.dialect.SQLServer2008Dialect - - - Mckoi SQL - org.hibernate.dialect.MckoiDialect - - - MySQL - org.hibernate.dialect.MySQLDialect - - - MySQL with InnoDB - org.hibernate.dialect.MySQL5InnoDBDialect - - - MySQL with MyISAM - org.hibernate.dialect.MySQLMyISAMDialect - - - Oracle 8i - org.hibernate.dialect.Oracle8iDialect - - - Oracle 9i - org.hibernate.dialect.Oracle9iDialect - - - Oracle 10g - org.hibernate.dialect.Oracle10gDialect - - - Pointbase - org.hibernate.dialect.PointbaseDialect - - - PostgreSQL 8.1 - org.hibernate.dialect.PostgreSQL81Dialect - - - PostgreSQL 8.2 and later - org.hibernate.dialect.PostgreSQL82Dialect - - - Progress - org.hibernate.dialect.ProgressDialect - - - SAP DB - org.hibernate.dialect.SAPDBDialect - - - Sybase ASE 15.5 - org.hibernate.dialect.SybaseASE15Dialect - - - Sybase ASE 15.7 - org.hibernate.dialect.SybaseASE157Dialect - - - Sybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect - + + CUBRID 8.3 and later + + + org.hibernate.dialect.CUBRIDDialect + + + + + DB2 + + + org.hibernate.dialect.DB2Dialect + + + + + DB2 AS/400 + + + org.hibernate.dialect.DB2400Dialect + + + + + DB2 OS390 + + + org.hibernate.dialect.DB2390Dialect + + + + + Firebird + + + org.hibernate.dialect.FirebirdDialect + + + + + FrontBase + + + org.hibernate.dialect.FrontbaseDialect + + + + + H2 + + + org.hibernate.dialect.H2Dialect + + + + + HyperSQL (HSQL) + + + org.hibernate.dialect.HSQLDialect + + + + + Informix + + + org.hibernate.dialect.InformixDialect + + + + + Ingres + + + org.hibernate.dialect.IngresDialect + + + + + Ingres 9 + + + org.hibernate.dialect.Ingres9Dialect + + + + + Ingres 10 + + + org.hibernate.dialect.Ingres10Dialect + + + + + Interbase + + + org.hibernate.dialect.InterbaseDialect + + + + + InterSystems Cache 2007.1 + + + org.hibernate.dialect.Cache71Dialect + + + + + JDataStore + + + org.hibernate.dialect.JDataStoreDialect + + + + + Mckoi SQL + + + org.hibernate.dialect.MckoiDialect + + + + + Microsoft SQL Server 2000 + + + org.hibernate.dialect.SQLServerDialect + + + + + Microsoft SQL Server 2005 + + + org.hibernate.dialect.SQLServer2005Dialect + + + + + Microsoft SQL Server 2008 + + + org.hibernate.dialect.SQLServer2008Dialect + + + + + Microsoft SQL Server 2012 + + + org.hibernate.dialect.SQLServer2012Dialect + + + + + Mimer SQL + + + org.hibernate.dialect.MimerSQLDialect + + + + + MySQL + + + org.hibernate.dialect.MySQLDialect + + + + + MySQL with InnoDB + + + org.hibernate.dialect.MySQLInnoDBDialect + + + + + MySQL with MyISAM + + + org.hibernate.dialect.MySQLMyISAMDialect + + + + + MySQL5 + + + org.hibernate.dialect.MySQL5Dialect + + + + + MySQL5 with InnoDB + + + org.hibernate.dialect.MySQL5InnoDBDialect + + + + + Oracle 8i + + + org.hibernate.dialect.Oracle8iDialect + + + + + Oracle 9i + + + org.hibernate.dialect.Oracle9iDialect + + + + + Oracle 10g and later + + + org.hibernate.dialect.Oracle10gDialect + + + + + Oracle TimesTen + + + org.hibernate.dialect.TimesTenDialect + + + + + Pointbase + + + org.hibernate.dialect.PointbaseDialect + + + + + PostgreSQL 8.1 + + + org.hibernate.dialect.PostgreSQL81Dialect + + + + + PostgreSQL 8.2 + + + org.hibernate.dialect.PostgreSQL82Dialect + + + + + PostgreSQL 9 and later + + + org.hibernate.dialect.PostgreSQL9Dialect + + + + + Progress + + + org.hibernate.dialect.ProgressDialect + + + + + SAP DB + + + org.hibernate.dialect.SAPDBDialect + + + + + SAP HANA (column store) + + + org.hibernate.dialect.HANAColumnStoreDialect + + + + + SAP HANA (row store) + + + org.hibernate.dialect.HANARowStoreDialect + + + + + Sybase + + + org.hibernate.dialect.SybaseDialect + + + + + Sybase 11 + + + org.hibernate.dialect.Sybase11Dialect + + + + + Sybase ASE 15.5 + + + org.hibernate.dialect.SybaseASE15Dialect + + + + + Sybase ASE 15.7 + + + org.hibernate.dialect.SybaseASE157Dialect + + + + + Sybase Anywhere + + + org.hibernate.dialect.SybaseAnywhereDialect + + + + + Teradata + + + org.hibernate.dialect.TeradataDialect + + + + + Unisys OS 2200 RDMS + + + org.hibernate.dialect.RDMSOS2200Dialect + + diff --git a/documentation/src/main/docbook/devguide/en-US/chapters/events/extras/SessionScopedExample.java b/documentation/src/main/docbook/devguide/en-US/chapters/events/extras/SessionScopedExample.java index 390b89f180b2..ff5136373e33 100644 --- a/documentation/src/main/docbook/devguide/en-US/chapters/events/extras/SessionScopedExample.java +++ b/documentation/src/main/docbook/devguide/en-US/chapters/events/extras/SessionScopedExample.java @@ -1 +1 @@ -Session session = sf.withOptions( new AuditInterceptor() ).openSession(); \ No newline at end of file +Session session = sf.withOptions().interceptor( new AuditInterceptor() ).openSession(); diff --git a/documentation/src/main/docbook/manual/en-US/content/collection_mapping.xml b/documentation/src/main/docbook/manual/en-US/content/collection_mapping.xml index 26b6c0f1663d..6f9011483f72 100644 --- a/documentation/src/main/docbook/manual/en-US/content/collection_mapping.xml +++ b/documentation/src/main/docbook/manual/en-US/content/collection_mapping.xml @@ -643,14 +643,14 @@ public class Order { Maps The question with Maps is where the key - value is stored. There are everal options. Maps can borrow their keys + value is stored. There are several options. Maps can borrow their keys from one of the associated entity properties or have dedicated columns to store an explicit key. To use one of the target entity property as a key of the map, use @MapKey(name="myProperty"), where myProperty is a property name in the target entity. - When using @MapKey without the name attribuate, the + When using @MapKey without the name attribute, the target entity primary key is used. The map key uses the same column as the property pointed out. There is no additional column defined to hold the map key, because the map key represent a target property. Be diff --git a/documentation/src/main/docbook/manual/en-US/content/configuration.xml b/documentation/src/main/docbook/manual/en-US/content/configuration.xml index 90094287b8ca..d9569e4feb38 100644 --- a/documentation/src/main/docbook/manual/en-US/content/configuration.xml +++ b/documentation/src/main/docbook/manual/en-US/content/configuration.xml @@ -963,177 +963,366 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQL82Dialect - - - DB2 - - org.hibernate.dialect.DB2Dialect - - - - DB2 AS/400 - - org.hibernate.dialect.DB2400Dialect - - - - DB2 OS390 - - org.hibernate.dialect.DB2390Dialect - - - - PostgreSQL 8.1 - - org.hibernate.dialect.PostgreSQL81Dialect - - - PostgreSQL 8.2 and later - - org.hibernate.dialect.PostgreSQL82Dialect - - - MySQL5 - - org.hibernate.dialect.MySQL5Dialect - - - - MySQL5 with InnoDB - - org.hibernate.dialect.MySQL5InnoDBDialect - - - - MySQL with MyISAM - - org.hibernate.dialect.MySQLMyISAMDialect - - - - Oracle (any version) - - org.hibernate.dialect.OracleDialect - - - - Oracle 9i - - org.hibernate.dialect.Oracle9iDialect - - - - Oracle 10g - - org.hibernate.dialect.Oracle10gDialect - - - - Oracle 11g - - org.hibernate.dialect.Oracle10gDialect - - - - Sybase ASE 15.5 - - org.hibernate.dialect.SybaseASE15Dialect - - - - Sybase ASE 15.7 - - org.hibernate.dialect.SybaseASE157Dialect - - - Sybase Anywhere - - org.hibernate.dialect.SybaseAnywhereDialect - - - - Microsoft SQL Server 2000 - - org.hibernate.dialect.SQLServerDialect - - - - Microsoft SQL Server 2005 - - org.hibernate.dialect.SQLServer2005Dialect - - - - Microsoft SQL Server 2008 - - org.hibernate.dialect.SQLServer2008Dialect - - - - SAP DB - - org.hibernate.dialect.SAPDBDialect - - - - Informix - - org.hibernate.dialect.InformixDialect - - - - HypersonicSQL - - org.hibernate.dialect.HSQLDialect - - - - H2 Database - - org.hibernate.dialect.H2Dialect - - - - Ingres - - org.hibernate.dialect.IngresDialect - - - - Progress - - org.hibernate.dialect.ProgressDialect - - - - Mckoi SQL - - org.hibernate.dialect.MckoiDialect - - - - Interbase - - org.hibernate.dialect.InterbaseDialect - - - - Pointbase - - org.hibernate.dialect.PointbaseDialect - - - - FrontBase - - org.hibernate.dialect.FrontbaseDialect - - - - Firebird - - org.hibernate.dialect.FirebirdDialect - + + + CUBRID 8.3 and later + + + org.hibernate.dialect.CUBRIDDialect + + + + + DB2 + + + org.hibernate.dialect.DB2Dialect + + + + + DB2 AS/400 + + + org.hibernate.dialect.DB2400Dialect + + + + + DB2 OS390 + + + org.hibernate.dialect.DB2390Dialect + + + + + Firebird + + + org.hibernate.dialect.FirebirdDialect + + + + + FrontBase + + + org.hibernate.dialect.FrontbaseDialect + + + + + H2 + + + org.hibernate.dialect.H2Dialect + + + + + HyperSQL (HSQL) + + + org.hibernate.dialect.HSQLDialect + + + + + Informix + + + org.hibernate.dialect.InformixDialect + + + + + Ingres + + + org.hibernate.dialect.IngresDialect + + + + + Ingres 9 + + + org.hibernate.dialect.Ingres9Dialect + + + + + Ingres 10 + + + org.hibernate.dialect.Ingres10Dialect + + + + + Interbase + + + org.hibernate.dialect.InterbaseDialect + + + + + InterSystems Cache 2007.1 + + + org.hibernate.dialect.Cache71Dialect + + + + + JDataStore + + + org.hibernate.dialect.JDataStoreDialect + + + + + Mckoi SQL + + + org.hibernate.dialect.MckoiDialect + + + + + Microsoft SQL Server 2000 + + + org.hibernate.dialect.SQLServerDialect + + + + + Microsoft SQL Server 2005 + + + org.hibernate.dialect.SQLServer2005Dialect + + + + + Microsoft SQL Server 2008 + + + org.hibernate.dialect.SQLServer2008Dialect + + + + + Microsoft SQL Server 2012 + + + org.hibernate.dialect.SQLServer2012Dialect + + + + + Mimer SQL + + + org.hibernate.dialect.MimerSQLDialect + + + + + MySQL + + + org.hibernate.dialect.MySQLDialect + + + + + MySQL with InnoDB + + + org.hibernate.dialect.MySQLInnoDBDialect + + + + + MySQL with MyISAM + + + org.hibernate.dialect.MySQLMyISAMDialect + + + + + MySQL5 + + + org.hibernate.dialect.MySQL5Dialect + + + + + MySQL5 with InnoDB + + + org.hibernate.dialect.MySQL5InnoDBDialect + + + + + Oracle 8i + + + org.hibernate.dialect.Oracle8iDialect + + + + + Oracle 9i + + + org.hibernate.dialect.Oracle9iDialect + + + + + Oracle 10g and later + + + org.hibernate.dialect.Oracle10gDialect + + + + + Oracle TimesTen + + + org.hibernate.dialect.TimesTenDialect + + + + + Pointbase + + + org.hibernate.dialect.PointbaseDialect + + + + + PostgreSQL 8.1 + + + org.hibernate.dialect.PostgreSQL81Dialect + + + + + PostgreSQL 8.2 + + + org.hibernate.dialect.PostgreSQL82Dialect + + + + + PostgreSQL 9 and later + + + org.hibernate.dialect.PostgreSQL9Dialect + + + + + Progress + + + org.hibernate.dialect.ProgressDialect + + + + + SAP DB + + + org.hibernate.dialect.SAPDBDialect + + + + + SAP HANA (column store) + + + org.hibernate.dialect.HANAColumnStoreDialect + + + + + SAP HANA (row store) + + + org.hibernate.dialect.HANARowStoreDialect + + + + + Sybase + + + org.hibernate.dialect.SybaseDialect + + + + + Sybase 11 + + + org.hibernate.dialect.Sybase11Dialect + + + + + Sybase ASE 15.5 + + + org.hibernate.dialect.SybaseASE15Dialect + + + + + Sybase ASE 15.7 + + + org.hibernate.dialect.SybaseASE157Dialect + + + + + Sybase Anywhere + + + org.hibernate.dialect.SybaseAnywhereDialect + + + + + Teradata + + + org.hibernate.dialect.TeradataDialect + + + + + Unisys OS 2200 RDMS + + + org.hibernate.dialect.RDMSOS2200Dialect + + diff --git a/documentation/src/main/docbook/manual/en-US/content/filters.xml b/documentation/src/main/docbook/manual/en-US/content/filters.xml index 851f13d6e52d..e76151520cda 100755 --- a/documentation/src/main/docbook/manual/en-US/content/filters.xml +++ b/documentation/src/main/docbook/manual/en-US/content/filters.xml @@ -63,15 +63,38 @@ public class Forest { ... } Using <classname>@FilterJoinTable</classname> for filterting on the association table - @OneToMany - @JoinTable - //filter on the target entity table - @Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length") - //filter on the association table - @FilterJoinTable(name="security", condition=":userlevel >= requredLevel") - public Set<Forest> getForests() { ... } + @OneToMany +@JoinTable +//filter on the target entity table +@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length") +//filter on the association table +@FilterJoinTable(name="security", condition=":userlevel >= requredLevel") +public Set<Forest> getForests() { ... } + By default, Hibernate attempts to automatically determine all points within the + @Filter SQL condition fragment that an alias should be injected. To control the alias injection, + set deduceAliasInjectionPoints to false within the + @Filter. Injection points are then marked using @SqlFragmentAlias annotations or + within the SQL's condition fragment using {alias}. + + In addition to allowing explicit alias control, deduceAliasInjectionPoints + provides an out when Hibernate assumes an ANSI SQL reserved keyword is a column and incorrectly aliases it. + + + @Filter annotation, disabling deduceAliasInjectionPoints + + @Entity +@Table(name="T_TREE") +@Filters({ + @Filter(name="isTall", condition="{alias}.LENGTH >= 100", deduceAliasInjectionPoints = false), + @Filter(name="isOak", condition="{t}.WOODTYPE like 'oak'", deduceAliasInjectionPoints = false, + aliases={@SqlFragmentAlias(alias="t", table="T_TREE")}) +}) +public class Tree { ... } + + + Using Hibernate mapping files for defining filters the situtation is very similar. The filters must first be defined and then attached to the appropriate mapping elements. To define a filter, use the diff --git a/documentation/src/main/docbook/manual/en-US/content/tutorial.xml b/documentation/src/main/docbook/manual/en-US/content/tutorial.xml index 4dd5984f24fa..bb8e571bef7a 100644 --- a/documentation/src/main/docbook/manual/en-US/content/tutorial.xml +++ b/documentation/src/main/docbook/manual/en-US/content/tutorial.xml @@ -553,7 +553,7 @@ public class Event { -
+
Startup and helpers @@ -579,6 +579,7 @@ public class Event { + * Yes this *could* be handled with Boolean, but then you run into potential + * problems with unwanted auto-unboxing. + * + * @author Steve Ebersole + */ +public enum TruthValue { + TRUE, + FALSE, + UNKNOWN; + + @SuppressWarnings("SimplifiableIfStatement") + public static boolean toBoolean(TruthValue value, boolean defaultValue) { + if ( value == TruthValue.TRUE ) { + return true; + } + if ( value == TruthValue.FALSE ) { + return false; + } + return defaultValue; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java index 094973f5ae3f..69aa2562e94b 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java @@ -34,6 +34,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitDeleteEventListener; import org.hibernate.event.spi.PostDeleteEvent; import org.hibernate.event.spi.PostDeleteEventListener; import org.hibernate.event.spi.PreDeleteEvent; @@ -170,7 +171,7 @@ private void postDelete() { } } - private void postCommitDelete() { + private void postCommitDelete(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_DELETE ); if ( listenerGroup.isEmpty() ) { return; @@ -182,8 +183,19 @@ private void postCommitDelete() { getPersister(), eventSource() ); - for( PostDeleteEventListener listener : listenerGroup.listeners() ){ - listener.onPostDelete( event ); + for ( PostDeleteEventListener listener : listenerGroup.listeners() ) { + if ( PostCommitDeleteEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostDelete( event ); + } + else { + ((PostCommitDeleteEventListener) listener).onPostDeleteCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostDelete( event ); + } } } @@ -197,7 +209,7 @@ public void doAfterTransactionCompletion(boolean success, SessionImplementor ses ); getPersister().getCacheAccessStrategy().unlockItem( ck, lock ); } - postCommitDelete(); + postCommitDelete( success ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java index b6a0f280b74c..50ce35e162c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java @@ -31,6 +31,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitInsertEventListener; import org.hibernate.event.spi.PostInsertEvent; import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PreInsertEvent; @@ -149,7 +150,7 @@ public void doAfterTransactionCompletion(boolean success, SessionImplementor ses if ( success && persister.hasCache() && !persister.isCacheInvalidationRequired() ) { persister.getCache().afterInsert( getGeneratedId(), cacheEntry ); }*/ - postCommitInsert(); + postCommitInsert( success ); } private void postInsert() { @@ -173,7 +174,7 @@ private void postInsert() { } } - private void postCommitInsert() { + private void postCommitInsert(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -186,7 +187,18 @@ private void postCommitInsert() { eventSource() ); for ( PostInsertEventListener listener : listenerGroup.listeners() ) { - listener.onPostInsert( event ); + if ( PostCommitInsertEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostInsert( event ); + } + else { + ((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostInsert( event ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java index 19fc0809c4d6..87d35bb03427 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java @@ -36,6 +36,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitInsertEventListener; import org.hibernate.event.spi.PostInsertEvent; import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PreInsertEvent; @@ -177,7 +178,7 @@ private void postInsert() { } } - private void postCommitInsert() { + private void postCommitInsert(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -190,7 +191,18 @@ private void postCommitInsert() { eventSource() ); for ( PostInsertEventListener listener : listenerGroup.listeners() ) { - listener.onPostInsert( event ); + if ( PostCommitInsertEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostInsert( event ); + } + else { + ((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostInsert( event ); + } } } @@ -220,7 +232,7 @@ public void doAfterTransactionCompletion(boolean success, SessionImplementor ses .secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); } } - postCommitInsert(); + postCommitInsert( success ); } private boolean cacheAfterInsert(EntityPersister persister, CacheKey ck) { diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java index 85af4a6dcfd2..5d7caec0f12f 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java @@ -39,6 +39,7 @@ import org.hibernate.engine.spi.Status; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitUpdateEventListener; import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; import org.hibernate.event.spi.PreUpdateEvent; @@ -277,7 +278,7 @@ private void postUpdate() { } } - private void postCommitUpdate() { + private void postCommitUpdate(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_UPDATE ); if ( listenerGroup.isEmpty() ) { return; @@ -292,7 +293,18 @@ private void postCommitUpdate() { eventSource() ); for ( PostUpdateEventListener listener : listenerGroup.listeners() ) { - listener.onPostUpdate( event ); + if ( PostCommitUpdateEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostUpdate( event ); + } + else { + ((PostCommitUpdateEventListener) listener).onPostUpdateCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostUpdate( event ); + } } } @@ -330,7 +342,7 @@ public void doAfterTransactionCompletion(boolean success, SessionImplementor ses persister.getCacheAccessStrategy().unlockItem( ck, lock ); } } - postCommitUpdate(); + postCommitUpdate( success ); } private boolean cacheAfterUpdate(EntityPersister persister, CacheKey ck) { diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/AccessType.java b/hibernate-core/src/main/java/org/hibernate/annotations/AccessType.java deleted file mode 100644 index 94c5eb032914..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/AccessType.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Property Access type. Prefer the standard {@link javax.persistence.Access} annotation; however, - * {@code @Access} is limited to field/property access definitions. - * - * @author Emmanuel Bernard - * - * @deprecated Use {@link AttributeAccessor} instead; renamed to avoid confusion with the JPA - * {@link javax.persistence.AccessType} enum. - */ -@Target({ TYPE, METHOD, FIELD }) -@Retention(RUNTIME) -@Deprecated -public @interface AccessType { - /** - * The access strategy name. - */ - String value(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/CascadeType.java b/hibernate-core/src/main/java/org/hibernate/annotations/CascadeType.java index 96ad7ec1f7be..15933ff957fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/CascadeType.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/CascadeType.java @@ -59,24 +59,10 @@ public enum CascadeType { * Corresponds to the Hibernate native REPLICATE action. */ REPLICATE, - /** - * Hibernate originally handled orphan removal as a specialized cascade. - * - * @deprecated use @OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true) - */ - @Deprecated - DELETE_ORPHAN, /** * Corresponds to the Hibernate native LOCK action. */ LOCK, - /** - * JPA originally planned on calling DETACH EVICT. - * - * @deprecated use javax.persistence.CascadeType.DETACH - */ - @Deprecated - EVICT, /** * Corresponds to {@link javax.persistence.CascadeType#REFRESH}. */ diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/CollectionType.java b/hibernate-core/src/main/java/org/hibernate/annotations/CollectionType.java index 31c5c759f4e4..7b4cadfb3bf1 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/CollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/CollectionType.java @@ -30,11 +30,15 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * Names a custom collection type for a persistent collection. The collection can also name a @Type, which defines - * the Hibernate Type of the collection elements. + * Names a custom collection type for a persistent collection. The collection + * can also name a @Type, which defines the Hibernate Type of the collection + * elements. If the collection is a Map, can als use @MapKeyType to define the + * Hibernate Type of the map key. * * @see org.hibernate.type.CollectionType * @see org.hibernate.usertype.UserCollectionType + * @see org.hibernate.annotations.Type + * @see org.hibernate.annotations.MapKeyType * * @author Steve Ebersole */ @@ -42,18 +46,21 @@ @Retention(RUNTIME) public @interface CollectionType { /** - * Names the type. + * Name of the collection type to use. * - * Could name the implementation class (an implementation of {@link org.hibernate.type.CollectionType} or - * {@link org.hibernate.usertype.UserCollectionType}). Could also name a custom type defined via a - * {@link TypeDef @TypeDef} + * Could name either:
    + *
  • the implementation class (an implementation of {@link org.hibernate.type.CollectionType}
  • + *
  • the implementation class (an implementation of {@link org.hibernate.usertype.UserCollectionType}
  • + *
  • a type defined via a {@link TypeDef @TypeDef}
  • + *
*/ String type(); /** - * Specifies configuration information for the type. Note that if the named type is a - * {@link org.hibernate.usertype.UserCollectionType}, it must also implement - * {@link org.hibernate.usertype.ParameterizedType} in order to receive these values. + * Specifies configuration information for the type. Note that if the named + * type is a {@link org.hibernate.usertype.UserCollectionType}, it must also + * implement {@link org.hibernate.usertype.ParameterizedType} in order to + * receive these values. */ Parameter[] parameters() default {}; } diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Entity.java b/hibernate-core/src/main/java/org/hibernate/annotations/Entity.java deleted file mode 100644 index 00527d5092b1..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Entity.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Extends {@link javax.persistence.Entity} with Hibernate features. - * - * @author Emmanuel Bernard - * - * @deprecated See individual attributes for intended replacements. To be removed in 4.1 - */ -@Target(TYPE) -@Retention(RUNTIME) -@Deprecated -public @interface Entity { - /** - * Is this entity mutable (read only) or not. - * - * @deprecated use {@link org.hibernate.annotations.Immutable} - */ - @Deprecated - boolean mutable() default true; - /** - * Needed column only in SQL on insert. - * @deprecated use {@link DynamicInsert} instead - */ - @Deprecated - boolean dynamicInsert() default false; - /** - * Needed column only in SQL on update. - * @deprecated Use {@link DynamicUpdate} instead - */ - @Deprecated - boolean dynamicUpdate() default false; - /** - * Do a select to retrieve the entity before any potential update. - * @deprecated Use {@link SelectBeforeUpdate} instead - */ - @Deprecated - boolean selectBeforeUpdate() default false; - /** - * polymorphism strategy for this entity. - * @deprecated use {@link Polymorphism} instead - */ - @Deprecated - PolymorphismType polymorphism() default PolymorphismType.IMPLICIT; - /** - * optimistic locking strategy. - * @deprecated use {@link OptimisticLocking} instead. - */ - @Deprecated - OptimisticLockType optimisticLock() default OptimisticLockType.VERSION; - /** - * persister of this entity, default is hibernate internal one. - * @deprecated use {@link Persister} instead - */ - @Deprecated - String persister() default ""; -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Filter.java b/hibernate-core/src/main/java/org/hibernate/annotations/Filter.java index eea2379bac0e..74dde8886a26 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Filter.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Filter.java @@ -53,8 +53,9 @@ String condition() default ""; /** - * Do we need to determine all points within the condition fragment that are alias injection points? Or - * are injection points already marked? + * If true, automatically determine all points within the condition fragment that an alias should be injected. + * Otherwise, injection will only replace instances of explicit "{alias}" instances or + * @SqlFragmentAlias descriptors. */ boolean deduceAliasInjectionPoints() default true; diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java b/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java index 69bc487d83e3..8b942af119a2 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java @@ -41,13 +41,6 @@ public enum FlushModeType { * Corresponds to {@link org.hibernate.FlushMode#COMMIT}. */ COMMIT, - /** - * Corresponds to {@link org.hibernate.FlushMode#NEVER}. - * - * @deprecated use MANUAL, will be removed in a subsequent release - */ - @Deprecated - NEVER, /** * Corresponds to {@link org.hibernate.FlushMode#MANUAL}. */ diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/annotations/ForeignKey.java deleted file mode 100644 index c1963ec1626b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/ForeignKey.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Define the foreign key name. - * - * @deprecated Prefer the JPA 2.1 introduced {@link javax.persistence.ForeignKey} instead. - */ -@Target({FIELD, METHOD, TYPE}) -@Retention(RUNTIME) -@Deprecated -public @interface ForeignKey { - /** - * Name of the foreign key. Used in OneToMany, ManyToOne, and OneToOne - * relationships. Used for the owning side in ManyToMany relationships - */ - String name(); - - /** - * Used for the non-owning side of a ManyToMany relationship. Ignored - * in other relationships - */ - String inverseName() default ""; -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Index.java b/hibernate-core/src/main/java/org/hibernate/annotations/Index.java deleted file mode 100644 index 5b6a9ea0db79..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Index.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Define a DB index. - * - * @author Emmanuel Bernard - * - * @deprecated Using {@link javax.persistence.Index} instead. - */ -@Target({FIELD, METHOD}) -@Retention(RUNTIME) -@Deprecated -public @interface Index { - /** - * The index name. - */ - String name(); - - /** - * The column(s) that are indexed. - */ - String[] columnNames() default {}; -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/IndexColumn.java b/hibernate-core/src/main/java/org/hibernate/annotations/IndexColumn.java deleted file mode 100644 index 88c228ccc202..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/IndexColumn.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Describe an index column of a List. - * - * @author Matthew Inger - * - * @deprecated Prefer the standard JPA {@link javax.persistence.OrderColumn} annotation and the Hibernate specific - * {@link ListIndexBase} (for replacing {@link #base()}). - */ -@Target({METHOD, FIELD}) -@Retention(RUNTIME) -@Deprecated -public @interface IndexColumn { - /** - * The column name. - */ - String name(); - - /** - * The starting index value. Zero (0) by default, since Lists indexes start at zero (0). - */ - int base() default 0; - - /** - * Is the column nullable? - */ - boolean nullable() default true; - - /** - * An explicit column definition. - */ - String columnDefinition() default ""; -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java b/hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java new file mode 100644 index 000000000000..2e664acb5311 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/annotations/MultiTenancy.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.annotations; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Annotation used to indicate that an entity represents shared (non tenant aware) data in a multi-tenant + * application. + * + * Valid only at the root of an inheritance hierarchy. + * + * @author Steve Ebersole + */ +@java.lang.annotation.Target(TYPE) +@Retention(RUNTIME) +public @interface MultiTenancy { + public boolean shared() default true; + + /** + * The discriminator values can be either be handled as literals or handled through JDBC parameter binding. + * {@code true} here (the default) indicates that the parameter binding approach should be used; {@code false} + * indicates the value should be handled as a literal. + *

+ * Care should be used specifying to use literals here. PreparedStatements will not be able to be reused + * nearly as often by the database/driver which can potentially cause a significant performance impact to your + * application. + */ + public boolean useParameterBinding() default true; +} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Sort.java b/hibernate-core/src/main/java/org/hibernate/annotations/Sort.java deleted file mode 100644 index 3dd90115e68f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Sort.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Collection sort (in-memory sorting). Different that ordering, which is applied during the SQL select. - * - * @author Emmanuel Bernard - * - * @see OrderBy - * - * @deprecated Use {@link SortComparator} or {@link SortNatural} instead depending on need. - */ -@Target({METHOD, FIELD}) -@Retention(RUNTIME) -@Deprecated -public @interface Sort { - /** - * The type of sorting to use. The default is to not use sorting. - */ - SortType type() default SortType.UNSORTED; - - /** - * Specifies the comparator to use. Only valid when {@link #type} specifies {@link SortType#COMPARATOR}. - * - * TODO find a way to use Class -> see HHH-8164 - */ - Class comparator() default void.class; -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/SortComparator.java b/hibernate-core/src/main/java/org/hibernate/annotations/SortComparator.java index 6ed0c2710a1f..83fb0749316d 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SortComparator.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/SortComparator.java @@ -23,6 +23,12 @@ */ package org.hibernate.annotations; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; import java.util.Comparator; /** @@ -38,6 +44,8 @@ * * @author Steve Ebersole */ +@Target({METHOD, FIELD}) +@Retention(RUNTIME) public @interface SortComparator { /** * Specifies the comparator class to use. diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/SortNatural.java b/hibernate-core/src/main/java/org/hibernate/annotations/SortNatural.java index 9fc285dedc23..1c3ad5a61cc6 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SortNatural.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/SortNatural.java @@ -23,6 +23,13 @@ */ package org.hibernate.annotations; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** * Specifies in-memory Set/Map sorting using natural sorting. * @@ -36,5 +43,7 @@ * * @author Steve Ebersole */ +@Target({METHOD, FIELD}) +@Retention(RUNTIME) public @interface SortNatural { } diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/SortType.java b/hibernate-core/src/main/java/org/hibernate/annotations/SortType.java deleted file mode 100644 index b8f0ea4baa01..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SortType.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.annotations; - -/** - * Possible collection sorting strategies. - * - * @author Emmanuel Bernard - * - * @deprecated Since {@link Sort} is deprecated. - */ -@Deprecated -public enum SortType { - /** - * The collection is unsorted. - */ - UNSORTED, - /** - * The collection is sorted using its natural sorting. - */ - NATURAL, - /** - * The collection is sorted using a supplied comparator. - */ - COMPARATOR -} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Table.java b/hibernate-core/src/main/java/org/hibernate/annotations/Table.java index 43338e0dc181..48d1c2f4e3fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Table.java @@ -23,11 +23,14 @@ */ package org.hibernate.annotations; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + import java.lang.annotation.Retention; import java.lang.annotation.Target; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; +import javax.persistence.ForeignKey; +import javax.persistence.Index; /** * Complementary information to a table either primary or secondary. diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java b/hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java new file mode 100644 index 000000000000..eba993f1107a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/annotations/TenantColumn.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.annotations; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Describes the column to use as the multi-tenancy discriminator value for the entity. + * + * @author Steve Ebersole + */ +@java.lang.annotation.Target( TYPE ) +@Retention( RUNTIME ) +public @interface TenantColumn { + /** + * Name of the column to use. + */ + public String name(); + + /** + * (Optional) The name of the table that contains the column. If absent the column is assumed to be in the + * primary table. + */ + public String table() default ""; + + /** + * Names the Hibernate mapping type to use for mapping values to/from the specified column. Defaults to + * {@code "string"} which is a {@link String}/{@link java.sql.Types#VARCHAR VARCHAR} mapping. + */ + public String type() default "string"; + + /** + * (Optional) The column length. (Applies only if a string-valued column is used.) + */ + int length() default 255; + + /** + * (Optional) The precision for a decimal (exact numeric) column. (Applies only if a decimal column is used.) + * Value must be set by developer if used when generating the DDL for the column. + */ + int precision() default 0; + + /** + * (Optional) The scale for a decimal (exact numeric) column. (Applies only if a decimal column is used.) + */ + int scale() default 0; +} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java b/hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java new file mode 100644 index 000000000000..fd1cbd111785 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/annotations/TenantFormula.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.annotations; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Describes a formula fragment to use as the multi-tenancy discriminator value for the entity. + * + * @author Steve Ebersole + * @see Formula + */ +@java.lang.annotation.Target(TYPE) +@Retention(RUNTIME) +public @interface TenantFormula { + /** + * The formula fragment. + */ + public String value(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizer.java b/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizer.java index c692a36455f3..9720e2f9fbc2 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizer.java @@ -45,15 +45,12 @@ */ Class impl(); - /** - * either pojo, dynamic-map or dom4j. - * @deprecated should use #entityModeType instead - */ - @Deprecated - String entityMode() default "pojo"; - /** * The entity mode. + * + * @deprecated Specifying multiple entity modes and/or tuplizers for a thing + * is no longer supported */ + @Deprecated EntityMode entityModeType() default EntityMode.POJO; } diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizers.java b/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizers.java index 6a14061d014a..cee1d0065a67 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizers.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Tuplizers.java @@ -31,9 +31,13 @@ * Grouping of tuplizers. * * @author Emmanuel Bernard + * + * @deprecated Specifying multiple entity modes and/or tuplizers for a thing + * is no longer supported */ @java.lang.annotation.Target( {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} ) @Retention( RetentionPolicy.RUNTIME ) +@Deprecated public @interface Tuplizers { /** * The grouping of tuplizers. diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/BootstrapServiceRegistryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/BootstrapServiceRegistryBuilder.java index ce592024095c..f6c2a67f6e85 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/BootstrapServiceRegistryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/BootstrapServiceRegistryBuilder.java @@ -51,10 +51,13 @@ */ public class BootstrapServiceRegistryBuilder { private final LinkedHashSet providedIntegrators = new LinkedHashSet(); + private List providedClassLoaders; private ClassLoaderService providedClassLoaderService; private StrategySelectorBuilder strategySelectorBuilder = new StrategySelectorBuilder(); - + + private boolean autoCloseRegistry = true; + /** * Add an {@link Integrator} to be applied to the bootstrap registry. * @@ -190,6 +193,35 @@ public BootstrapServiceRegistryBuilder withStrategySelectors(StrategyRegistratio return this; } + /** + * By default, when a ServiceRegistry is no longer referenced by any other + * registries as a parent it will be closed. + *

+ * Some applications that explicitly build "shared registries" may want to + * circumvent that behavior. + *

+ * This method indicates that the registry being built should not be + * automatically closed. The caller agrees to take responsibility to + * close it themselves. + * + * @return this, for method chaining + */ + public BootstrapServiceRegistryBuilder disableAutoClose() { + this.autoCloseRegistry = false; + return this; + } + + /** + * See the discussion on {@link #disableAutoClose}. This method enables + * the auto-closing. + * + * @return this, for method chaining + */ + public BootstrapServiceRegistryBuilder enableAutoClose() { + this.autoCloseRegistry = true; + return this; + } + /** * Build the bootstrap registry. * @@ -219,6 +251,7 @@ public BootstrapServiceRegistry build() { return new BootstrapServiceRegistryImpl( + autoCloseRegistry, classLoaderService, strategySelectorBuilder.buildSelector( classLoaderService ), integratorService diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java index 949be8967bd1..f5f565a21184 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java @@ -23,6 +23,8 @@ */ package org.hibernate.boot.registry; +import java.io.File; +import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; @@ -34,8 +36,8 @@ import org.hibernate.cfg.Environment; import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.IntegratorService; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.service.ConfigLoader; import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; @@ -43,6 +45,8 @@ import org.hibernate.service.internal.ProvidedService; import org.hibernate.service.spi.ServiceContributor; +import static org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbProperty; + /** * Builder for standard {@link org.hibernate.service.ServiceRegistry} instances. * @@ -61,6 +65,8 @@ public class StandardServiceRegistryBuilder { private final List initiators = standardInitiatorList(); private final List providedServices = new ArrayList(); + private boolean autoCloseRegistry = true; + private final BootstrapServiceRegistry bootstrapServiceRegistry; private final ConfigLoader configLoader; @@ -97,6 +103,10 @@ public BootstrapServiceRegistry getBootstrapServiceRegistry() { return bootstrapServiceRegistry; } + public ConfigLoader getConfigLoader() { + return configLoader; + } + /** * Read settings from a {@link java.util.Properties} file by resource name. * @@ -106,9 +116,6 @@ public BootstrapServiceRegistry getBootstrapServiceRegistry() { * @param resourceName The name by which to perform a resource look up for the properties file. * * @return this, for method chaining - * - * @see #configure() - * @see #configure(String) */ @SuppressWarnings( {"unchecked"}) public StandardServiceRegistryBuilder loadProperties(String resourceName) { @@ -116,6 +123,22 @@ public StandardServiceRegistryBuilder loadProperties(String resourceName) { return this; } + /** + * Read settings from a {@link java.util.Properties} file. + * + * Differs from {@link #configure()} and {@link #configure(String)} in that here we expect to read a + * {@link java.util.Properties} file while for {@link #configure} we read the XML variant. + * + * @param propertyFile The property file reference + * + * @return this, for method chaining + */ + @SuppressWarnings( {"unchecked"}) + public StandardServiceRegistryBuilder loadProperties(File propertyFile) { + settings.putAll( configLoader.loadProperties( propertyFile ) ); + return this; + } + /** * Read setting information from an XML file using the standard resource location. * @@ -140,14 +163,64 @@ public StandardServiceRegistryBuilder configure() { */ @SuppressWarnings( {"unchecked"}) public StandardServiceRegistryBuilder configure(String resourceName) { - final JaxbHibernateConfiguration configurationElement = configLoader.loadConfigXmlResource( resourceName ); - for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbProperty xmlProperty : configurationElement.getSessionFactory().getProperty() ) { + return configure( configLoader.loadConfigXmlResource( resourceName ) ); + } + + /** + * Read setting information from an XML file using the named resource location. + * + * @param file The config file reference + * + * @return this, for method chaining + * + * @see #loadProperties(String) + */ + @SuppressWarnings( {"unchecked"}) + public StandardServiceRegistryBuilder configure(File file) { + return configure( configLoader.loadConfigFile( file ) ); + } + + /** + * Read setting information from an XML file using the named resource location. + * + * @param configFileUrl The config file url reference + * + * @return this, for method chaining + * + * @see #loadProperties(String) + */ + @SuppressWarnings( {"unchecked"}) + public StandardServiceRegistryBuilder configure(URL configFileUrl) { + final JaxbHibernateConfiguration configurationElement = configLoader.loadConfig( configFileUrl ); + for ( JaxbProperty xmlProperty : configurationElement.getSessionFactory().getProperty() ) { settings.put( xmlProperty.getName(), xmlProperty.getValue() ); } return this; } + /** + * Reads configuration values from the JAXB representation of the legacy {@code cfg.xml} XML format. + * + * @param jaxbHibernateConfiguration The JAXB model + * + * @return this, for method chaining + * + * @see #loadProperties(String) + */ + @SuppressWarnings( {"unchecked"}) + public StandardServiceRegistryBuilder configure(JaxbHibernateConfiguration jaxbHibernateConfiguration) { + for ( JaxbProperty xmlProperty : jaxbHibernateConfiguration.getSessionFactory().getProperty() ) { + String settingName = xmlProperty.getName(); + if ( !settingName.startsWith( "hibernate." ) ) { + settingName = "hibernate." + settingName; + } + settings.put( settingName, xmlProperty.getValue() ); + } + + return this; + } + /** * Apply a setting value. * @@ -202,6 +275,35 @@ public StandardServiceRegistryBuilder addService(final Class serviceRole, final return this; } + /** + * By default, when a ServiceRegistry is no longer referenced by any other + * registries as a parent it will be closed. + *

+ * Some applications that explicitly build "shared registries" may want to + * circumvent that behavior. + *

+ * This method indicates that the registry being built should not be + * automatically closed. The caller agrees to take responsibility to + * close it themselves. + * + * @return this, for method chaining + */ + public StandardServiceRegistryBuilder disableAutoClose() { + this.autoCloseRegistry = false; + return this; + } + + /** + * See the discussion on {@link #disableAutoClose}. This method enables + * the auto-closing. + * + * @return this, for method chaining + */ + public StandardServiceRegistryBuilder enableAutoClose() { + this.autoCloseRegistry = true; + return this; + } + /** * Build the StandardServiceRegistry. * @@ -217,7 +319,13 @@ public StandardServiceRegistry build() { applyServiceContributingIntegrators(); applyServiceContributors(); - return new StandardServiceRegistryImpl( bootstrapServiceRegistry, initiators, providedServices, settingsCopy ); + return new StandardServiceRegistryImpl( + autoCloseRegistry, + bootstrapServiceRegistry, + initiators, + providedServices, + settingsCopy + ); } @SuppressWarnings("deprecation") diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java index df0a48d48d32..050c2586faea 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java @@ -31,7 +31,6 @@ import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -43,7 +42,6 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.util.ClassLoaderHelper; - import org.jboss.logging.Logger; /** @@ -182,7 +180,7 @@ private AggregatedClassLoader(final LinkedHashSet orderedClassLoade @Override public Enumeration getResources(String name) throws IOException { - final HashSet resourceUrls = new HashSet(); + final LinkedHashSet resourceUrls = new LinkedHashSet(); for ( ClassLoader classLoader : individualClassLoaders ) { final Enumeration urls = classLoader.getResources( name ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/BootstrapServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/BootstrapServiceRegistryImpl.java index d6d5b6b13c1b..539048174cf2 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/BootstrapServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/BootstrapServiceRegistryImpl.java @@ -23,7 +23,9 @@ */ package org.hibernate.boot.registry.internal; +import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.Set; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; @@ -33,6 +35,7 @@ import org.hibernate.integrator.internal.IntegratorServiceImpl; import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.IntegratorService; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; @@ -42,8 +45,6 @@ import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.Stoppable; -import org.jboss.logging.Logger; - /** * {@link ServiceRegistry} implementation containing specialized "bootstrap" services, specifically:

    *
  • {@link ClassLoaderService}
  • @@ -61,17 +62,19 @@ public class BootstrapServiceRegistryImpl implements ServiceRegistryImplementor, BootstrapServiceRegistry, ServiceBinding.ServiceLifecycleOwner { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - BootstrapServiceRegistryImpl.class.getName() - ); - + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( BootstrapServiceRegistryImpl.class ); + + private final boolean autoCloseRegistry; + private boolean active = true; + private static final LinkedHashSet NO_INTEGRATORS = new LinkedHashSet(); private final ServiceBinding classLoaderServiceBinding; private final ServiceBinding strategySelectorBinding; private final ServiceBinding integratorServiceBinding; + private Set childRegistries; + /** * Constructs a BootstrapServiceRegistryImpl. * @@ -83,6 +86,22 @@ public class BootstrapServiceRegistryImpl public BootstrapServiceRegistryImpl() { this( new ClassLoaderServiceImpl(), NO_INTEGRATORS ); } + /** + * Constructs a BootstrapServiceRegistryImpl. + * + * Do not use directly generally speaking. Use {@link org.hibernate.boot.registry.BootstrapServiceRegistryBuilder} + * instead. + * + * @param classLoaderService The ClassLoaderService to use + * @param providedIntegrators The group of explicitly provided integrators + * + * @see org.hibernate.boot.registry.BootstrapServiceRegistryBuilder + */ + public BootstrapServiceRegistryImpl( + ClassLoaderService classLoaderService, + LinkedHashSet providedIntegrators) { + this( true, classLoaderService, providedIntegrators ); + } /** * Constructs a BootstrapServiceRegistryImpl. @@ -90,14 +109,19 @@ public BootstrapServiceRegistryImpl() { * Do not use directly generally speaking. Use {@link org.hibernate.boot.registry.BootstrapServiceRegistryBuilder} * instead. * + * @param autoCloseRegistry See discussion on + * {@link org.hibernate.boot.registry.BootstrapServiceRegistryBuilder#disableAutoClose} * @param classLoaderService The ClassLoaderService to use * @param providedIntegrators The group of explicitly provided integrators * * @see org.hibernate.boot.registry.BootstrapServiceRegistryBuilder */ public BootstrapServiceRegistryImpl( + boolean autoCloseRegistry, ClassLoaderService classLoaderService, LinkedHashSet providedIntegrators) { + this.autoCloseRegistry = autoCloseRegistry; + this.classLoaderServiceBinding = new ServiceBinding( this, ClassLoaderService.class, @@ -135,6 +159,31 @@ public BootstrapServiceRegistryImpl( ClassLoaderService classLoaderService, StrategySelector strategySelector, IntegratorService integratorService) { + this( true, classLoaderService, strategySelector, integratorService ); + } + + + /** + * Constructs a BootstrapServiceRegistryImpl. + * + * Do not use directly generally speaking. Use {@link org.hibernate.boot.registry.BootstrapServiceRegistryBuilder} + * instead. + * + * @param autoCloseRegistry See discussion on + * {@link org.hibernate.boot.registry.BootstrapServiceRegistryBuilder#disableAutoClose} + * @param classLoaderService The ClassLoaderService to use + * @param strategySelector The StrategySelector to use + * @param integratorService The IntegratorService to use + * + * @see org.hibernate.boot.registry.BootstrapServiceRegistryBuilder + */ + public BootstrapServiceRegistryImpl( + boolean autoCloseRegistry, + ClassLoaderService classLoaderService, + StrategySelector strategySelector, + IntegratorService integratorService) { + this.autoCloseRegistry = autoCloseRegistry; + this.classLoaderServiceBinding = new ServiceBinding( this, ClassLoaderService.class, @@ -180,6 +229,10 @@ else if ( IntegratorService.class.equals( serviceRole ) ) { @Override public void destroy() { + if ( !active ) { + return; + } + active = false; destroy( classLoaderServiceBinding ); destroy( strategySelectorBinding ); destroy( integratorServiceBinding ); @@ -189,6 +242,10 @@ private void destroy(ServiceBinding serviceBinding) { serviceBinding.getLifecycleOwner().stopService( serviceBinding ); } + public boolean isActive() { + return active; + } + @Override public ServiceRegistry getParentServiceRegistry() { return null; @@ -227,4 +284,39 @@ public void stopService(ServiceBinding binding) { } } + @Override + public void registerChild(ServiceRegistryImplementor child) { + if ( childRegistries == null ) { + childRegistries = new HashSet(); + } + if ( !childRegistries.add( child ) ) { + LOG.warnf( + "Child ServiceRegistry [%s] was already registered; this will end badly later...", + child + ); + } + } + + @Override + public void deRegisterChild(ServiceRegistryImplementor child) { + if ( childRegistries == null ) { + throw new IllegalStateException( "No child ServiceRegistry registrations found" ); + } + childRegistries.remove( child ); + if ( childRegistries.isEmpty() ) { + if ( autoCloseRegistry ) { + LOG.debug( + "Implicitly destroying Boot-strap registry on de-registration " + + "of all child ServiceRegistries" + ); + destroy(); + } + else { + LOG.debug( + "Skipping implicitly destroying Boot-strap registry on de-registration " + + "of all child ServiceRegistries" + ); + } + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/StandardServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/StandardServiceRegistryImpl.java index 29ed9b56f318..607fc4820e0e 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/StandardServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/internal/StandardServiceRegistryImpl.java @@ -35,7 +35,6 @@ import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.ServiceBinding; import org.hibernate.service.spi.ServiceInitiator; -import org.hibernate.service.spi.ServiceRegistryImplementor; /** * Standard Hibernate implementation of the standard service registry. @@ -62,7 +61,30 @@ public StandardServiceRegistryImpl( List serviceInitiators, List providedServices, Map configurationValues) { - super( bootstrapServiceRegistry ); + this( true, bootstrapServiceRegistry, serviceInitiators, providedServices, configurationValues ); + } + + /** + * Constructs a StandardServiceRegistryImpl. Should not be instantiated directly; use + * {@link org.hibernate.boot.registry.StandardServiceRegistryBuilder} instead + * + * @param autoCloseRegistry See discussion on + * {@link org.hibernate.boot.registry.StandardServiceRegistryBuilder#disableAutoClose} + * @param bootstrapServiceRegistry The bootstrap service registry. + * @param serviceInitiators Any StandardServiceInitiators provided by the user to the builder + * @param providedServices Any standard services provided directly to the builder + * @param configurationValues Configuration values + * + * @see org.hibernate.boot.registry.StandardServiceRegistryBuilder + */ + @SuppressWarnings( {"unchecked"}) + public StandardServiceRegistryImpl( + boolean autoCloseRegistry, + BootstrapServiceRegistry bootstrapServiceRegistry, + List serviceInitiators, + List providedServices, + Map configurationValues) { + super( bootstrapServiceRegistry, autoCloseRegistry ); this.configurationValues = configurationValues; @@ -89,12 +111,4 @@ public void configureService(ServiceBinding serviceBindin ( (Configurable) serviceBinding.getService() ).configure( configurationValues ); } } - - @Override - public void destroy() { - super.destroy(); - if ( getParentServiceRegistry() != null ) { - ( (ServiceRegistryImplementor) getParentServiceRegistry() ).destroy(); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java index d118018d1eed..d41157435cb4 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorBuilder.java @@ -140,7 +140,8 @@ public void addExplicitStrategyRegistration(StrategyRegistration strategy throw new StrategySelectionException( "Implementation class [" + strategyRegistration.getStrategyImplementation().getName() + "] does not implement strategy interface [" - + strategyRegistration.getStrategyRole().getName() + "]" + + strategyRegistration.getStrategyRole().getName() + "]", + strategyRegistration.getStrategyImplementation().getName() ); } explicitStrategyRegistrations.add( strategyRegistration ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java index fd408184f8ae..14be66161c6c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java @@ -126,7 +126,8 @@ public Class selectStrategyImplementor(Class strategy, Strin } catch (ClassLoadingException e) { throw new StrategySelectionException( - "Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]" + "Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]", + name ); } } @@ -161,7 +162,8 @@ public T resolveDefaultableStrategy(Class strategy, Object strategyRefere catch (Exception e) { throw new StrategySelectionException( String.format( "Could not instantiate named strategy class [%s]", implementationClass.getName() ), - e + e, + implementationClass.getName() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java index 118bda69a088..f5d3be94d6be 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelectionException.java @@ -31,13 +31,16 @@ * @author Steve Ebersole */ public class StrategySelectionException extends HibernateException { + + private final String implementationClassName; /** * Constructs a StrategySelectionException using the specified message. * * @param message A message explaining the exception condition. */ - public StrategySelectionException(String message) { + public StrategySelectionException(String message, String implementationClassName) { super( message ); + this.implementationClassName = implementationClassName; } /** @@ -46,7 +49,17 @@ public StrategySelectionException(String message) { * @param message A message explaining the exception condition. * @param cause The underlying cause. */ - public StrategySelectionException(String message, Throwable cause) { + public StrategySelectionException(String message, Throwable cause, String implementationClassName) { super( message, cause ); + this.implementationClassName = implementationClassName; + } + + /** + * Gets the selected implementation class involved with the exception. + * + * @return the implementation class name. + */ + public String getImplementationClassName() { + return implementationClassName; } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java new file mode 100644 index 000000000000..4838e12cc73b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/CacheRegionDefinition.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.boot.spi; + +/** + * Models the definition of caching settings for a particular region. Generally as found in either:
      + *
    • {@code cfg.xml}
    • + *
    • {@code hbm.xml}
    • + *
    • annotation
    • + *
    + * Though certainly other custom sources are acceptable too. + * + * @author Steve Ebersole + */ +public class CacheRegionDefinition { + public static enum CacheRegionType { + ENTITY, + COLLECTION, + QUERY + } + + private final CacheRegionType regionType; + private final String role; + private final String usage; + private final String region; + private final boolean cacheLazy; + + public CacheRegionDefinition( + CacheRegionType cacheType, + String role, + String usage, + String region, + boolean cacheLazy) { + this.regionType = cacheType; + this.role = role; + this.usage = usage; + this.region = region; + this.cacheLazy = cacheLazy; + } + + public CacheRegionType getRegionType() { + return regionType; + } + + public String getRole() { + return role; + } + + public String getUsage() { + return usage; + } + + public String getRegion() { + return region; + } + + public boolean isCacheLazy() { + return cacheLazy; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/JaccPermissionDefinition.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/JaccPermissionDefinition.java new file mode 100644 index 000000000000..cb89c8cf57fc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/JaccPermissionDefinition.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.boot.spi; + +/** +* @author Steve Ebersole +*/ +public class JaccPermissionDefinition { + public final String contextId; + public final String role; + public final String clazz; + public final String actions; + + public JaccPermissionDefinition(String contextId, String role, String clazz, String actions) { + this.contextId = contextId; + this.role = role; + this.clazz = clazz; + this.actions = actions; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java index e4917d1200b8..308fa684c6c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java @@ -28,8 +28,8 @@ import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.type.VersionType; /** @@ -96,7 +96,11 @@ public static CacheDataDescriptionImpl decode(PersistentClass model) { * @return The constructed CacheDataDescriptionImpl */ public static CacheDataDescriptionImpl decode(EntityBinding model) { - return new CacheDataDescriptionImpl( model.isMutable(), model.isVersioned(), getVersionComparator( model ) ); + return new CacheDataDescriptionImpl( + model.getHierarchyDetails().isMutable(), + model.getHierarchyDetails().isVersioned(), + getVersionComparator( model ) + ); } /** @@ -126,15 +130,15 @@ public static CacheDataDescriptionImpl decode(Collection model) { public static CacheDataDescriptionImpl decode(PluralAttributeBinding model) { return new CacheDataDescriptionImpl( model.isMutable(), - model.getContainer().seekEntityBinding().isVersioned(), + model.getContainer().seekEntityBinding().getHierarchyDetails().isVersioned(), getVersionComparator( model.getContainer().seekEntityBinding() ) ); } private static Comparator getVersionComparator(EntityBinding model ) { - if ( model.isVersioned() ) { + if ( model.getHierarchyDetails().isVersioned() ) { final VersionType versionType = (VersionType) model.getHierarchyDetails() - .getVersioningAttributeBinding() + .getEntityVersion().getVersioningAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping(); diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java index 637776f2ef24..1a04d361897e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/CollectionCacheInvalidator.java @@ -39,7 +39,7 @@ import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.spi.SessionFactoryServiceRegistry; diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java index b852b8af4edb..fdbd30208d42 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java @@ -47,6 +47,7 @@ public class NaturalIdCacheKey implements Serializable { private final String entityName; private final String tenantId; private final int hashCode; + // "transient" is important here -- NaturalIdCacheKey needs to be Serializable private transient ValueHolder toString; /** diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java index 45eaa636356b..e08033cee622 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -87,7 +87,6 @@ import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; import org.hibernate.FetchMode; import org.hibernate.MappingException; import org.hibernate.annotations.BatchSize; @@ -107,11 +106,9 @@ import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.FilterDefs; import org.hibernate.annotations.Filters; -import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Formula; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerators; -import org.hibernate.annotations.Index; import org.hibernate.annotations.LazyToOne; import org.hibernate.annotations.LazyToOneOption; import org.hibernate.annotations.ListIndexBase; @@ -128,7 +125,6 @@ import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Parent; import org.hibernate.annotations.Proxy; -import org.hibernate.annotations.Sort; import org.hibernate.annotations.SortComparator; import org.hibernate.annotations.SortNatural; import org.hibernate.annotations.Source; @@ -607,11 +603,8 @@ public static void bindClass( PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity ); Entity entityAnn = clazzToProcess.getAnnotation( Entity.class ); - org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation( - org.hibernate.annotations.Entity.class - ); EntityBinder entityBinder = new EntityBinder( - entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings + entityAnn, clazzToProcess, persistentClass, mappings ); entityBinder.setInheritanceState( inheritanceState ); @@ -713,10 +706,6 @@ else if ( clazzToProcess.isAnnotationPresent( Table.class ) ) { final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass; SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() ); jsc.setKey( key ); - ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class ); - if ( fk != null && !BinderHelper.isEmptyAnnotationValue( fk.name() ) ) { - key.setForeignKeyName( fk.name() ); - } if ( onDeleteAnn != null ) { key.setCascadeDeleteEnabled( OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) ); } @@ -1359,10 +1348,6 @@ private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassTy || AnnotatedClassType.NONE.equals( classType ) //to be ignored || AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration ) { - if ( AnnotatedClassType.NONE.equals( classType ) - && clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) { - LOG.missingEntityAnnotation( clazzToProcess.getName() ); - } return false; } @@ -1892,29 +1877,15 @@ else if ( property.isAnnotationPresent( OneToMany.class ) ManyToMany manyToManyAnn = property.getAnnotation( ManyToMany.class ); ElementCollection elementCollectionAnn = property.getAnnotation( ElementCollection.class ); - final IndexColumn indexColumn; - - if ( property.isAnnotationPresent( OrderColumn.class ) ) { - indexColumn = IndexColumn.buildColumnFromAnnotation( - property.getAnnotation( OrderColumn.class ), - propertyHolder, - inferredData, - entityBinder.getSecondaryTables(), - mappings - ); - if ( property.isAnnotationPresent( ListIndexBase.class ) ) { - indexColumn.setBase( ( property.getAnnotation( ListIndexBase.class ) ).value() ); - } - } - else { - //if @IndexColumn is not there, the generated IndexColumn is an implicit column and not used. - //so we can leave the legacy processing as the default - indexColumn = IndexColumn.buildColumnFromAnnotation( - property.getAnnotation( org.hibernate.annotations.IndexColumn.class ), - propertyHolder, - inferredData, - mappings - ); + final IndexColumn indexColumn = IndexColumn.buildColumnFromAnnotation( + property.getAnnotation( OrderColumn.class ), + propertyHolder, + inferredData, + entityBinder.getSecondaryTables(), + mappings + ); + if ( property.isAnnotationPresent( ListIndexBase.class ) ) { + indexColumn.setBase( ( property.getAnnotation( ListIndexBase.class ) ).value() ); } CollectionBinder collectionBinder = CollectionBinder.getCollectionBinder( propertyHolder.getEntityName(), @@ -1932,7 +1903,6 @@ else if ( property.isAnnotationPresent( OneToMany.class ) collectionBinder.setJpaOrderBy( property.getAnnotation( javax.persistence.OrderBy.class ) ); collectionBinder.setSqlOrderBy( property.getAnnotation( OrderBy.class ) ); - collectionBinder.setSort( property.getAnnotation( Sort.class ) ); collectionBinder.setNaturalSort( property.getAnnotation( SortNatural.class ) ); collectionBinder.setComparatorSort( property.getAnnotation( SortComparator.class ) ); @@ -2274,24 +2244,6 @@ else if ( !isId || !entityBinder.isIgnoreIdAnnotations() ) { } } } - //init index - //process indexes after everything: in second pass, many to one has to be done before indexes - Index index = property.getAnnotation( Index.class ); - if ( index != null ) { - if ( joinColumns != null ) { - - for ( Ejb3Column column : joinColumns ) { - column.addIndex( index, inSecondPass ); - } - } - else { - if ( columns != null ) { - for ( Ejb3Column column : columns ) { - column.addIndex( index, inSecondPass ); - } - } - } - } // Natural ID columns must reside in one single UniqueKey within the Table. // For now, simply ensure consistent naming. @@ -2795,16 +2747,12 @@ private static void setupComponentTuplizer(XProperty property, Component compone } if ( property.isAnnotationPresent( Tuplizers.class ) ) { for ( Tuplizer tuplizer : property.getAnnotation( Tuplizers.class ).value() ) { - EntityMode mode = EntityMode.parse( tuplizer.entityMode() ); - //todo tuplizer.entityModeType - component.addTuplizer( mode, tuplizer.impl().getName() ); + component.addTuplizer( tuplizer.entityModeType(), tuplizer.impl().getName() ); } } if ( property.isAnnotationPresent( Tuplizer.class ) ) { Tuplizer tuplizer = property.getAnnotation( Tuplizer.class ); - EntityMode mode = EntityMode.parse( tuplizer.entityMode() ); - //todo tuplizer.entityModeType - component.addTuplizer( mode, tuplizer.impl().getName() ); + component.addTuplizer( tuplizer.entityModeType(), tuplizer.impl().getName() ); } } @@ -2881,10 +2829,6 @@ private static void bindManyToOne( if ( joinColumn != null && joinColumn.foreignKey() != null ) { fkName = joinColumn.foreignKey().name(); } - if ( StringHelper.isEmpty( fkName ) ) { - ForeignKey fk = property.getAnnotation( ForeignKey.class ); - fkName = fk != null ? fk.name() : ""; - } if ( !StringHelper.isEmpty( fkName ) ) { value.setForeignKeyName( fkName ); } @@ -3164,7 +3108,6 @@ private static String getCascadeStrategy( } if ( orphanRemoval ) { - hibernateCascadeSet.add( CascadeType.DELETE_ORPHAN ); hibernateCascadeSet.add( CascadeType.REMOVE ); } if ( forcePersist ) { @@ -3195,16 +3138,12 @@ private static String getCascadeStrategy( case REPLICATE: cascade.append( "," ).append( "replicate" ); break; - case EVICT: case DETACH: cascade.append( "," ).append( "evict" ); break; case DELETE: cascade.append( "," ).append( "delete" ); break; - case DELETE_ORPHAN: - cascade.append( "," ).append( "delete-orphan" ); - break; case REMOVE: cascade.append( "," ).append( "delete" ); break; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java index 80f4fd6d2dfb..ef8a8e6a34ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java @@ -66,10 +66,6 @@ public AnnotationConfiguration addPackage(String packageName) throws MappingExce return (AnnotationConfiguration) super.addPackage( packageName ); } - public ExtendedMappings createExtendedMappings() { - return new ExtendedMappingsImpl(); - } - @Override public AnnotationConfiguration addFile(String xmlFile) throws MappingException { super.addFile( xmlFile ); @@ -160,12 +156,6 @@ public AnnotationConfiguration addProperties(Properties extraProperties) { return this; } - @Override - public AnnotationConfiguration mergeProperties(Properties properties) { - super.mergeProperties( properties ); - return this; - } - @Override public AnnotationConfiguration setProperty(String propertyName, String value) { super.setProperty( propertyName, value ); @@ -196,50 +186,15 @@ public AnnotationConfiguration configure(File configFile) throws HibernateExcept return this; } - @Override - protected AnnotationConfiguration doConfigure(InputStream stream, String resourceName) throws HibernateException { - super.doConfigure( stream, resourceName ); - return this; - } - @Override public AnnotationConfiguration configure(org.w3c.dom.Document document) throws HibernateException { super.configure( document ); return this; } - @Override - protected AnnotationConfiguration doConfigure(Document doc) throws HibernateException { - super.doConfigure( doc ); - return this; - } - - @Override - public AnnotationConfiguration setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy) { - super.setCacheConcurrencyStrategy( clazz, concurrencyStrategy ); - return this; - } - - @Override - public AnnotationConfiguration setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region) { - super.setCacheConcurrencyStrategy( clazz, concurrencyStrategy, region ); - return this; - } - - @Override - public AnnotationConfiguration setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy) - throws MappingException { - super.setCollectionCacheConcurrencyStrategy( collectionRole, concurrencyStrategy ); - return this; - } - @Override public AnnotationConfiguration setNamingStrategy(NamingStrategy namingStrategy) { super.setNamingStrategy( namingStrategy ); return this; } - - @Deprecated - protected class ExtendedMappingsImpl extends MappingsImpl { - } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 7aa0874c9578..bee2baa4f786 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -636,7 +636,51 @@ public interface AvailableSettings { */ String IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.ignore_explicit_for_joined"; - String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans"; + /** + * Names a {@link org.hibernate.Interceptor} implementation to be applied to the {@link org.hibernate.SessionFactory} + * Can reference
      + *
    • Interceptor instance
    • + *
    • Interceptor implementation {@link Class} reference
    • + *
    • Interceptor implementation class name
    • + *
    + * + * @since 5.0 + */ + String INTERCEPTOR = "hibernate.sessionFactory.interceptor"; + + /** + * Setting that controls whether we seek out JPA "static metamodel" classes and populate them. Accepts + * 3 values:
      + *
    • + * enabled - Do the population + *
    • + *
    • + * disabled - Do not do the population + *
    • + *
    • + * ignoreUnsupported - Do the population, but ignore any non-JPA features that would otherwise + * result in the population failing. + *
    • + *
    + */ + public static final String JPA_METAMODEL_POPULATION = "hibernate.ejb.metamodel.population"; + + /** + * Used to specify the {@link org.hibernate.tool.schema.spi.SchemaManagementTool} to use for performing + * schema management. The default is to use {@link org.hibernate.tool.schema.internal.HibernateSchemaManagementTool} + * + * @since 5.0 + */ + String SCHEMA_MANAGEMENT_TOOL = "hibernate.schema_management_tool"; + + /** + * A constant naming the setting used to identify the {@link org.hibernate.engine.jdbc.spi.SchemaNameResolver} to use + *

    + * TODO : add to Environment + */ + String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver"; + + String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans"; String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy"; @@ -701,6 +745,15 @@ public interface AvailableSettings { */ String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy"; + /** + * If enabled, an entity's member field types and method return types will automatically be indexed. This allows, + * for example, auto-discovery of @Embeddables without explicitly listing them in the annotated classes. This + * setting will also check classes identified by certain annotations (such as @Target). JPA requires these classes + * to be identified in the annotated classes, however legacy Hibernate behavior was to allow it. Due to the + * performance hit, disabled by default. + */ + String ENABLE_AUTO_INDEX_MEMBER_TYPES = "hibernate.enable_auto_index_member_types"; + /** * A setting to control whether to {@link org.hibernate.engine.internal.StatisticalLoggingSessionEventListener} is * enabled on all Sessions (unless explicitly disabled for a given Session). The default value of this diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java index 6ecbdcd47ec8..4f804cbf419d 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java @@ -24,143 +24,59 @@ package org.hibernate.cfg; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.io.StringReader; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; import javax.persistence.AttributeConverter; import javax.persistence.Converter; -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.MapsId; import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; -import org.hibernate.DuplicateMappingException; import org.hibernate.EmptyInterceptor; import org.hibernate.HibernateException; import org.hibernate.Interceptor; -import org.hibernate.InvalidMappingException; import org.hibernate.MappingException; -import org.hibernate.MappingNotFoundException; import org.hibernate.SessionFactory; import org.hibernate.SessionFactoryObserver; -import org.hibernate.annotations.AnyMetaDef; -import org.hibernate.annotations.common.reflection.MetadataProvider; -import org.hibernate.annotations.common.reflection.MetadataProviderInjector; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.annotations.common.reflection.XClass; -import org.hibernate.annotations.common.reflection.java.JavaReflectionManager; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.cfg.annotations.NamedProcedureCallDefinition; -import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider; import org.hibernate.context.spi.CurrentTenantIdentifierResolver; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.function.SQLFunction; import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.NamedQueryDefinition; import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.IdentifierGeneratorAggregator; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory; -import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.SessionFactoryImpl; -import org.hibernate.internal.util.ClassLoaderHelper; -import org.hibernate.internal.util.ConfigHelper; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.internal.util.SerializationHelper; import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.internal.util.collections.JoinedIterator; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.internal.util.xml.ErrorLogger; -import org.hibernate.internal.util.xml.MappingReader; -import org.hibernate.internal.util.xml.Origin; -import org.hibernate.internal.util.xml.OriginImpl; -import org.hibernate.internal.util.xml.XMLHelper; import org.hibernate.internal.util.xml.XmlDocument; -import org.hibernate.internal.util.xml.XmlDocumentImpl; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.mapping.AuxiliaryDatabaseObject; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Constraint; -import org.hibernate.mapping.DenormalizedTable; -import org.hibernate.mapping.FetchProfile; -import org.hibernate.mapping.ForeignKey; -import org.hibernate.mapping.IdGenerator; -import org.hibernate.mapping.IdentifierCollection; -import org.hibernate.mapping.Index; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.MappedSuperclass; -import org.hibernate.mapping.MetadataSource; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.RootClass; -import org.hibernate.mapping.SimpleValue; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.TypeDef; -import org.hibernate.mapping.UniqueKey; -import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.spi.TypeContributor; import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.secure.spi.GrantedPermission; -import org.hibernate.secure.spi.JaccPermissionDeclarations; import org.hibernate.service.ServiceRegistry; -import org.hibernate.tool.hbm2ddl.DatabaseMetadata; -import org.hibernate.tool.hbm2ddl.IndexMetadata; -import org.hibernate.tool.hbm2ddl.SchemaUpdateScript; -import org.hibernate.tool.hbm2ddl.TableMetadata; -import org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy; import org.hibernate.tuple.entity.EntityTuplizerFactory; import org.hibernate.type.BasicType; +import org.hibernate.type.CompositeCustomType; +import org.hibernate.type.CustomType; import org.hibernate.type.SerializationException; -import org.hibernate.type.Type; -import org.hibernate.type.TypeResolver; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.UserType; import org.jboss.logging.Logger; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; +import static org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping; /** * An instance of Configuration allows the application @@ -187,290 +103,280 @@ * @see org.hibernate.SessionFactory */ @SuppressWarnings( {"UnusedDeclaration"}) -public class Configuration implements Serializable { +public class Configuration { + private static final CoreMessageLogger log = Logger.getMessageLogger(CoreMessageLogger.class, Configuration.class.getName()); - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Configuration.class.getName()); + private final BootstrapServiceRegistry bootstrapServiceRegistry; + private final MetadataSources metadataSources; - public static final String DEFAULT_CACHE_CONCURRENCY_STRATEGY = AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY; - - public static final String USE_NEW_ID_GENERATOR_MAPPINGS = AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS; - - public static final String ARTEFACT_PROCESSING_ORDER = "hibernate.mapping.precedence"; - - /** - * Class name of the class needed to enable Search. - */ - private static final String SEARCH_STARTUP_CLASS = "org.hibernate.search.event.EventListenerRegister"; - - /** - * Method to call to enable Search. - */ - private static final String SEARCH_STARTUP_METHOD = "enableHibernateSearch"; - - protected MetadataSourceQueue metadataSourceQueue; - private transient ReflectionManager reflectionManager; - - protected Map classes; - protected Map imports; - protected Map collections; - protected Map tables; - protected List auxiliaryDatabaseObjects; - - protected Map namedQueries; - protected Map namedSqlQueries; - protected Map namedProcedureCallMap; - protected Map sqlResultSetMappings; - protected Map namedEntityGraphMap; - - protected Map typeDefs; - protected Map filterDefinitions; - protected Map fetchProfiles; - - protected Map tableNameBinding; - protected Map columnNameBindingPerTable; - - protected List secondPasses; - protected List propertyReferences; - protected Map extendsQueue; - - protected Map sqlFunctions; - - private TypeResolver typeResolver = new TypeResolver(); + // used during processing mappings + private NamingStrategy namingStrategy; + private List basicTypes = new ArrayList(); private List typeContributorRegistrations = new ArrayList(); + private List auxiliaryDatabaseObjects; + private Map namedQueries; + private Map namedSqlQueries; + private Map namedProcedureCallMap; + private Map sqlResultSetMappings; + private Map namedEntityGraphMap; + private Map sqlFunctions; + private ConcurrentHashMap attributeConverterDefinitionsByClass; + // used to build SF + private StandardServiceRegistryBuilder standardServiceRegistryBuilder; + private EntityNotFoundDelegate entityNotFoundDelegate; private EntityTuplizerFactory entityTuplizerFactory; -// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907 - + //private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907 private Interceptor interceptor; - private Properties properties; - private EntityResolver entityResolver; - private EntityNotFoundDelegate entityNotFoundDelegate; - - protected transient XMLHelper xmlHelper; - protected NamingStrategy namingStrategy; private SessionFactoryObserver sessionFactoryObserver; - - protected final SettingsFactory settingsFactory; - - private transient Mapping mapping = buildMapping(); - - private MutableIdentifierGeneratorFactory identifierGeneratorFactory; - - private Map, org.hibernate.mapping.MappedSuperclass> mappedSuperClasses; - - private Map namedGenerators; - private Map> joins; - private Map classTypes; - private Set defaultNamedQueryNames; - private Set defaultNamedNativeQueryNames; - private Set defaultSqlResultSetMappingNames; - private Set defaultNamedProcedure; - - private Set defaultNamedGenerators; - private Map generatorTables; - private Map> uniqueConstraintHoldersByTable; - private Map> jpaIndexHoldersByTable; - private Map mappedByResolver; - private Map propertyRefResolver; - private Map anyMetaDefs; - private List caches; - private boolean inSecondPass = false; - private boolean isDefaultProcessed = false; - private boolean isValidatorNotPresentLogged; - private Map> propertiesAnnotatedWithMapsId; - private Map> propertiesAnnotatedWithIdAndToOne; private CurrentTenantIdentifierResolver currentTenantIdentifierResolver; - private boolean specjProprietarySyntaxEnabled; + private Properties properties; - private ConcurrentHashMap attributeConverterDefinitionsByClass; + public Configuration() { + this( new BootstrapServiceRegistryBuilder().build() ); + } - protected Configuration(SettingsFactory settingsFactory) { - this.settingsFactory = settingsFactory; + public Configuration(BootstrapServiceRegistry serviceRegistry) { + this.bootstrapServiceRegistry = serviceRegistry; + this.metadataSources = new MetadataSources( serviceRegistry ); reset(); } - public Configuration() { - this( new SettingsFactory() ); + public Configuration(MetadataSources metadataSources) { + this.bootstrapServiceRegistry = getBootstrapRegistry( metadataSources.getServiceRegistry() ); + this.metadataSources = metadataSources; + reset(); } - protected void reset() { - metadataSourceQueue = new MetadataSourceQueue(); - createReflectionManager(); + private static BootstrapServiceRegistry getBootstrapRegistry(ServiceRegistry serviceRegistry) { + if ( BootstrapServiceRegistry.class.isInstance( serviceRegistry ) ) { + return (BootstrapServiceRegistry) serviceRegistry; + } + else if ( StandardServiceRegistry.class.isInstance( serviceRegistry ) ) { + final StandardServiceRegistry ssr = (StandardServiceRegistry) serviceRegistry; + return (BootstrapServiceRegistry) ssr.getParentServiceRegistry(); + } - classes = new HashMap(); - imports = new HashMap(); - collections = new HashMap(); - tables = new TreeMap(); + throw new HibernateException( + "No ServiceRegistry was passed to Configuration#buildSessionFactory " + + "and could not determine how to locate BootstrapServiceRegistry within ServiceRegistry " + + "from Configuration instantiation" + ); + } + protected void reset() { + namingStrategy = EJB3NamingStrategy.INSTANCE; + auxiliaryDatabaseObjects = new ArrayList(); namedQueries = new HashMap(); namedSqlQueries = new HashMap(); sqlResultSetMappings = new HashMap(); namedEntityGraphMap = new HashMap(); namedProcedureCallMap = new HashMap( ); - typeDefs = new HashMap(); - filterDefinitions = new HashMap(); - fetchProfiles = new HashMap(); - auxiliaryDatabaseObjects = new ArrayList(); - - tableNameBinding = new HashMap(); - columnNameBindingPerTable = new HashMap(); - - secondPasses = new ArrayList(); - propertyReferences = new ArrayList(); - extendsQueue = new HashMap(); - - xmlHelper = new XMLHelper(); - interceptor = EmptyInterceptor.INSTANCE; - properties = Environment.getProperties(); - entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER; - sqlFunctions = new HashMap(); + standardServiceRegistryBuilder = new StandardServiceRegistryBuilder( bootstrapServiceRegistry ); entityTuplizerFactory = new EntityTuplizerFactory(); -// componentTuplizerFactory = new ComponentTuplizerFactory(); - - identifierGeneratorFactory = new DefaultIdentifierGeneratorFactory(); - - mappedSuperClasses = new HashMap, MappedSuperclass>(); - - metadataSourcePrecedence = Collections.emptyList(); - - namedGenerators = new HashMap(); - joins = new HashMap>(); - classTypes = new HashMap(); - generatorTables = new HashMap(); - defaultNamedQueryNames = new HashSet(); - defaultNamedNativeQueryNames = new HashSet(); - defaultSqlResultSetMappingNames = new HashSet(); - defaultNamedProcedure = new HashSet( ); - defaultNamedGenerators = new HashSet(); - uniqueConstraintHoldersByTable = new HashMap>(); - jpaIndexHoldersByTable = new HashMap>( ); - mappedByResolver = new HashMap(); - propertyRefResolver = new HashMap(); - caches = new ArrayList(); - namingStrategy = EJB3NamingStrategy.INSTANCE; - setEntityResolver( new EJB3DTDEntityResolver() ); - anyMetaDefs = new HashMap(); - propertiesAnnotatedWithMapsId = new HashMap>(); - propertiesAnnotatedWithIdAndToOne = new HashMap>(); - specjProprietarySyntaxEnabled = System.getProperty( "hibernate.enable_specj_proprietary_syntax" ) != null; + //componentTuplizerFactory = new ComponentTuplizerFactory(); + interceptor = EmptyInterceptor.INSTANCE; + properties = new Properties( ); + properties.putAll( standardServiceRegistryBuilder.getSettings()); } - public EntityTuplizerFactory getEntityTuplizerFactory() { - return entityTuplizerFactory; - } - public ReflectionManager getReflectionManager() { - return reflectionManager; - } + // properties/settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// public ComponentTuplizerFactory getComponentTuplizerFactory() { -// return componentTuplizerFactory; -// } + /** + * Get all properties + * + * @return all properties + */ + public Properties getProperties() { + return properties; + } /** - * Iterate the entity mappings + * Specify a completely new set of properties + * + * @param properties The new set of properties * - * @return Iterator of the entity mappings currently contained in the configuration. + * @return this for method chaining */ - public Iterator getClassMappings() { - return classes.values().iterator(); + public Configuration setProperties(Properties properties) { + this.properties = properties; + return this; } /** - * Iterate the collection mappings + * Get a property value by name * - * @return Iterator of the collection mappings currently contained in the configuration. + * @param propertyName The name of the property + * + * @return The value currently associated with that property name; may be null. */ - public Iterator getCollectionMappings() { - return collections.values().iterator(); + public String getProperty(String propertyName) { + Object o = properties.get( propertyName ); + return o instanceof String ? (String) o : null; } /** - * Iterate the table mappings + * Set a property value by name + * + * @param propertyName The name of the property to set + * @param value The new property value * - * @return Iterator of the table mappings currently contained in the configuration. + * @return this for method chaining */ - public Iterator getTableMappings() { - return tables.values().iterator(); + public Configuration setProperty(String propertyName, String value) { + properties.setProperty( propertyName, value ); + return this; } /** - * Iterate the mapped super class mappings - * EXPERIMENTAL Consider this API as PRIVATE + * Add the given properties to ours. + * + * @param properties The properties to add. * - * @return iterator over the MappedSuperclass mapping currently contained in the configuration. + * @return this for method chaining */ - public Iterator getMappedSuperclassMappings() { - return mappedSuperClasses.values().iterator(); + public Configuration addProperties(Properties properties) { + this.properties.putAll( properties ); + return this; } /** - * Get a copy of all known MappedSuperclasses - *

    - * EXPERIMENTAL Consider this API as PRIVATE + * Use the mappings and properties specified in an application resource named hibernate.cfg.xml. + * + * @return this for method chaining * - * @return Set of all known MappedSuperclasses + * @throws HibernateException Generally indicates we cannot find hibernate.cfg.xml + * + * @see #configure(String) */ - public java.util.Set getMappedSuperclassMappingsCopy() { - return new HashSet( mappedSuperClasses.values() ); + public Configuration configure() throws HibernateException { + return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME ); } /** - * Get the mapping for a particular entity + * Use the mappings and properties specified in the given application resource. The format of the resource is + * defined in hibernate-configuration-3.0.dtd. + * + * @param resource The resource to use * - * @param entityName An entity name. - * @return the entity mapping information + * @return this for method chaining + * + * @throws HibernateException Generally indicates we cannot find the named resource */ - public PersistentClass getClassMapping(String entityName) { - return classes.get( entityName ); + public Configuration configure(String resource) throws HibernateException { + final JaxbHibernateConfiguration jaxbHibernateConfiguration = standardServiceRegistryBuilder.getConfigLoader() + .loadConfigXmlResource( resource ); + doConfigure( jaxbHibernateConfiguration ); + return this; + } + + private void doConfigure(JaxbHibernateConfiguration jaxbHibernateConfiguration) { + standardServiceRegistryBuilder.configure( jaxbHibernateConfiguration ); + + for ( JaxbMapping jaxbMapping : jaxbHibernateConfiguration.getSessionFactory().getMapping() ) { + if ( StringHelper.isNotEmpty( jaxbMapping.getClazz() ) ) { + addResource( jaxbMapping.getClazz().replace( '.', '/' ) + ".hbm.xml" ); + } + else if ( StringHelper.isNotEmpty( jaxbMapping.getFile() ) ) { + addFile( jaxbMapping.getFile() ); + } + else if ( StringHelper.isNotEmpty( jaxbMapping.getJar() ) ) { + addJar( new File( jaxbMapping.getJar() ) ); + } + else if ( StringHelper.isNotEmpty( jaxbMapping.getPackage() ) ) { + addPackage( jaxbMapping.getPackage() ); + } + else if ( StringHelper.isNotEmpty( jaxbMapping.getResource() ) ) { + addResource( jaxbMapping.getResource() ); + } + } } /** - * Get the mapping for a particular collection role + * Use the mappings and properties specified in the given document. The format of the document is defined in + * hibernate-configuration-3.0.dtd. + * + * @param url URL from which you wish to load the configuration + * + * @return this for method chaining * - * @param role a collection role - * @return The collection mapping information + * @throws HibernateException Generally indicates a problem access the url */ - public Collection getCollectionMapping(String role) { - return collections.get( role ); + public Configuration configure(URL url) throws HibernateException { + final JaxbHibernateConfiguration jaxbHibernateConfiguration = standardServiceRegistryBuilder.getConfigLoader() + .loadConfig( url ); + doConfigure( jaxbHibernateConfiguration ); + return this; } /** - * Set a custom entity resolver. This entity resolver must be - * set before addXXX(misc) call. - * Default value is {@link org.hibernate.internal.util.xml.DTDEntityResolver} + * Use the mappings and properties specified in the given application file. The format of the file is defined in + * hibernate-configuration-3.0.dtd. + * + * @param configFile File from which you wish to load the configuration + * + * @return this for method chaining * - * @param entityResolver entity resolver to use + * @throws HibernateException Generally indicates a problem access the file + */ + public Configuration configure(File configFile) throws HibernateException { + final JaxbHibernateConfiguration jaxbHibernateConfiguration = standardServiceRegistryBuilder.getConfigLoader() + .loadConfigFile( configFile ); + doConfigure( jaxbHibernateConfiguration ); + return this; + } + + /** + * @deprecated No longer supported. */ - public void setEntityResolver(EntityResolver entityResolver) { - this.entityResolver = entityResolver; + @Deprecated + public Configuration configure(org.w3c.dom.Document document) throws HibernateException { + return this; } - public EntityResolver getEntityResolver() { - return entityResolver; + + // MetadataSources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public void registerTypeContributor(TypeContributor typeContributor) { + typeContributorRegistrations.add( typeContributor ); } /** - * Retrieve the user-supplied delegate to handle non-existent entity - * scenarios. May be null. + * Allows registration of a type into the type registry. The phrase 'override' in the method name simply + * reminds that registration *potentially* replaces a previously registered type . * - * @return The user-supplied delegate + * @param type The type to register. */ - public EntityNotFoundDelegate getEntityNotFoundDelegate() { - return entityNotFoundDelegate; + public void registerTypeOverride(BasicType type) { + basicTypes.add( type ); + } + + + public void registerTypeOverride(UserType type, String[] keys) { + basicTypes.add( new CustomType( type, keys ) ); + } + + public void registerTypeOverride(CompositeUserType type, String[] keys) { + basicTypes.add( new CompositeCustomType( type, keys ) ); + } + + public NamingStrategy getNamingStrategy() { + return namingStrategy; } /** - * Specify a user-supplied delegate to be used to handle scenarios where an entity could not be - * located by specified id. This is mainly intended for EJB3 implementations to be able to - * control how proxy initialization errors should be handled... + * Set a custom naming strategy * - * @param entityNotFoundDelegate The delegate to use + * @param namingStrategy the NamingStrategy to set + * + * @return this for method chaining */ - public void setEntityNotFoundDelegate(EntityNotFoundDelegate entityNotFoundDelegate) { - this.entityNotFoundDelegate = entityNotFoundDelegate; + public Configuration setNamingStrategy(NamingStrategy namingStrategy) { + this.namingStrategy = namingStrategy; + return this; } /** @@ -483,9 +389,9 @@ public void setEntityNotFoundDelegate(EntityNotFoundDelegate entityNotFoundDeleg * @see #addFile(java.io.File) */ public Configuration addFile(String xmlFile) throws MappingException { - return addFile( new File( xmlFile ) ); + metadataSources.addFile( xmlFile ); + return this; } - /** * Read mappings from a particular XML file * @@ -494,52 +400,16 @@ public Configuration addFile(String xmlFile) throws MappingException { * @throws MappingException Indicates inability to locate the specified mapping file. Historically this could * have indicated a problem parsing the XML document, but that is now delayed until after {@link #buildMappings} */ - public Configuration addFile(final File xmlFile) throws MappingException { - LOG.readingMappingsFromFile( xmlFile.getPath() ); - final String name = xmlFile.getAbsolutePath(); - final InputSource inputSource; - try { - inputSource = new InputSource( new FileInputStream( xmlFile ) ); - } - catch ( FileNotFoundException e ) { - throw new MappingNotFoundException( "file", xmlFile.toString() ); - } - add( inputSource, "file", name ); + public Configuration addFile(File xmlFile) throws MappingException { + metadataSources.addFile( xmlFile ); return this; } - private XmlDocument add(InputSource inputSource, String originType, String originName) { - return add( inputSource, new OriginImpl( originType, originName ) ); - } - - private XmlDocument add(InputSource inputSource, Origin origin) { - XmlDocument metadataXml = MappingReader.INSTANCE.readMappingDocument( entityResolver, inputSource, origin ); - add( metadataXml ); - return metadataXml; - } - + /** + * @deprecated No longer supported. + */ + @Deprecated public void add(XmlDocument metadataXml) { - if ( inSecondPass || !isOrmXml( metadataXml ) ) { - metadataSourceQueue.add( metadataXml ); - } - else { - final MetadataProvider metadataProvider = ( (MetadataProviderInjector) reflectionManager ).getMetadataProvider(); - JPAMetadataProvider jpaMetadataProvider = ( JPAMetadataProvider ) metadataProvider; - List classNames = jpaMetadataProvider.getXMLContext().addDocument( metadataXml.getDocumentTree() ); - for ( String className : classNames ) { - try { - metadataSourceQueue.add( reflectionManager.classForName( className, this.getClass() ) ); - } - catch ( ClassNotFoundException e ) { - throw new AnnotationException( "Unable to load class defined in XML: " + className, e ); - } - } - jpaMetadataProvider.getXMLContext().applyDiscoveredAttributeConverters( this ); - } - } - - private static boolean isOrmXml(XmlDocument xmlDocument) { - return "entity-mappings".equals( xmlDocument.getDocumentTree().getRootElement().getName() ); } /** @@ -559,45 +429,10 @@ private static boolean isOrmXml(XmlDocument xmlDocument) { * the non-cached file. */ public Configuration addCacheableFile(File xmlFile) throws MappingException { - File cachedFile = determineCachedDomFile( xmlFile ); - - try { - return addCacheableFileStrictly( xmlFile ); - } - catch ( SerializationException e ) { - LOG.unableToDeserializeCache( cachedFile.getPath(), e ); - } - catch ( FileNotFoundException e ) { - LOG.cachedFileNotFound( cachedFile.getPath(), e ); - } - - final String name = xmlFile.getAbsolutePath(); - final InputSource inputSource; - try { - inputSource = new InputSource( new FileInputStream( xmlFile ) ); - } - catch ( FileNotFoundException e ) { - throw new MappingNotFoundException( "file", xmlFile.toString() ); - } - - LOG.readingMappingsFromFile( xmlFile.getPath() ); - XmlDocument metadataXml = add( inputSource, "file", name ); - - try { - LOG.debugf( "Writing cache file for: %s to: %s", xmlFile, cachedFile ); - SerializationHelper.serialize( ( Serializable ) metadataXml.getDocumentTree(), new FileOutputStream( cachedFile ) ); - } - catch ( Exception e ) { - LOG.unableToWriteCachedFile( cachedFile.getPath(), e.getMessage() ); - } - + metadataSources.addCacheableFile( xmlFile ); return this; } - private File determineCachedDomFile(File xmlFile) { - return new File( xmlFile.getAbsolutePath() + ".bin" ); - } - /** * INTENDED FOR TESTSUITE USE ONLY! *

    @@ -612,19 +447,7 @@ private File determineCachedDomFile(File xmlFile) { * @throws FileNotFoundException Indicates that the cached file was not found or was not usable. */ public Configuration addCacheableFileStrictly(File xmlFile) throws SerializationException, FileNotFoundException { - final File cachedFile = determineCachedDomFile( xmlFile ); - - final boolean useCachedFile = xmlFile.exists() - && cachedFile.exists() - && xmlFile.lastModified() < cachedFile.lastModified(); - - if ( ! useCachedFile ) { - throw new FileNotFoundException( "Cached file could not be found or could not be used" ); - } - - LOG.readingCachedMappings( cachedFile ); - Document document = ( Document ) SerializationHelper.deserialize( new FileInputStream( cachedFile ) ); - add( new XmlDocumentImpl( document, "file", xmlFile.getAbsolutePath() ) ); + metadataSources.addCacheableFileStrictly( xmlFile ); return this; } @@ -639,22 +462,16 @@ public Configuration addCacheableFileStrictly(File xmlFile) throws Serialization * @see #addCacheableFile(java.io.File) */ public Configuration addCacheableFile(String xmlFile) throws MappingException { - return addCacheableFile( new File( xmlFile ) ); + metadataSources.addCacheableFile( xmlFile ); + return this; } /** - * Read mappings from a String - * - * @param xml an XML string - * @return this (for method chaining purposes) - * @throws org.hibernate.MappingException Indicates problems parsing the - * given XML string + * @deprecated No longer supported */ + @Deprecated public Configuration addXML(String xml) throws MappingException { - LOG.debugf( "Mapping XML:\n%s", xml ); - final InputSource inputSource = new InputSource( new StringReader( xml ) ); - add( inputSource, "string", "XML String" ); return this; } @@ -667,34 +484,10 @@ public Configuration addXML(String xml) throws MappingException { * the mapping document. */ public Configuration addURL(URL url) throws MappingException { - final String urlExternalForm = url.toExternalForm(); - - LOG.debugf( "Reading mapping document from URL : %s", urlExternalForm ); - - try { - add( url.openStream(), "URL", urlExternalForm ); - } - catch ( IOException e ) { - throw new InvalidMappingException( "Unable to open url stream [" + urlExternalForm + "]", "URL", urlExternalForm, e ); - } + metadataSources.addURL( url ); return this; } - private XmlDocument add(InputStream inputStream, final String type, final String name) { - final InputSource inputSource = new InputSource( inputStream ); - try { - return add( inputSource, type, name ); - } - finally { - try { - inputStream.close(); - } - catch ( IOException ignore ) { - LOG.trace( "Was unable to close input stream"); - } - } - } - /** * Read mappings from a DOM Document * @@ -704,11 +497,7 @@ private XmlDocument add(InputStream inputStream, final String type, final String * the mapping document. */ public Configuration addDocument(org.w3c.dom.Document doc) throws MappingException { - LOG.debugf( "Mapping Document:\n%s", doc ); - - final Document document = xmlHelper.createDOMReader().read( doc ); - add( new XmlDocumentImpl( document, "unknown", null ) ); - + metadataSources.addDocument( doc ); return this; } @@ -721,27 +510,17 @@ public Configuration addDocument(org.w3c.dom.Document doc) throws MappingExcepti * processing the contained mapping document. */ public Configuration addInputStream(InputStream xmlInputStream) throws MappingException { - add( xmlInputStream, "input stream", null ); + metadataSources.addInputStream( xmlInputStream ); return this; } /** - * Read mappings as a application resource (i.e. classpath lookup). - * - * @param resourceName The resource name - * @param classLoader The class loader to use. - * @return this (for method chaining purposes) - * @throws MappingException Indicates problems locating the resource or - * processing the contained mapping document. + * @deprecated This form (accepting a ClassLoader) is no longer supported. Instead, add the ClassLoader + * to the ClassLoaderService on the ServiceRegistry associated with this Configuration */ + @Deprecated public Configuration addResource(String resourceName, ClassLoader classLoader) throws MappingException { - LOG.readingMappingsFromResource( resourceName ); - InputStream resourceInputStream = classLoader.getResourceAsStream( resourceName ); - if ( resourceInputStream == null ) { - throw new MappingNotFoundException( "resource", resourceName ); - } - add( resourceInputStream, "resource", resourceName ); - return this; + return addResource( resourceName ); } /** @@ -754,19 +533,7 @@ public Configuration addResource(String resourceName, ClassLoader classLoader) t * processing the contained mapping document. */ public Configuration addResource(String resourceName) throws MappingException { - LOG.readingMappingsFromResource( resourceName ); - ClassLoader contextClassLoader = ClassLoaderHelper.getContextClassLoader(); - InputStream resourceInputStream = null; - if ( contextClassLoader != null ) { - resourceInputStream = contextClassLoader.getResourceAsStream( resourceName ); - } - if ( resourceInputStream == null ) { - resourceInputStream = Environment.class.getClassLoader().getResourceAsStream( resourceName ); - } - if ( resourceInputStream == null ) { - throw new MappingNotFoundException( "resource", resourceName ); - } - add( resourceInputStream, "resource", resourceName ); + metadataSources.addResource( resourceName ); return this; } @@ -781,9 +548,8 @@ public Configuration addResource(String resourceName) throws MappingException { * processing the contained mapping document. */ public Configuration addClass(Class persistentClass) throws MappingException { - String mappingResourceName = persistentClass.getName().replace( '.', '/' ) + ".hbm.xml"; - LOG.readingMappingsFromResource( mappingResourceName ); - return addResource( mappingResourceName, persistentClass.getClassLoader() ); + metadataSources.addClass( persistentClass ); + return this; } /** @@ -795,8 +561,7 @@ public Configuration addClass(Class persistentClass) throws MappingException { */ @SuppressWarnings({ "unchecked" }) public Configuration addAnnotatedClass(Class annotatedClass) { - XClass xClass = reflectionManager.toXClass( annotatedClass ); - metadataSourceQueue.add( xClass ); + metadataSources.addAnnotatedClass( annotatedClass ); return this; } @@ -810,15 +575,8 @@ public Configuration addAnnotatedClass(Class annotatedClass) { * @throws MappingException in case there is an error in the mapping data */ public Configuration addPackage(String packageName) throws MappingException { - LOG.debugf( "Mapping Package %s", packageName ); - try { - AnnotationBinder.bindPackage( packageName, createMappings() ); - return this; - } - catch ( MappingException me ) { - LOG.unableToParseMetadata( packageName ); - throw me; - } + metadataSources.addPackage( packageName ); + return this; } /** @@ -832,48 +590,7 @@ public Configuration addPackage(String packageName) throws MappingException { * processing the contained mapping documents. */ public Configuration addJar(File jar) throws MappingException { - LOG.searchingForMappingDocuments( jar.getName() ); - JarFile jarFile = null; - try { - try { - jarFile = new JarFile( jar ); - } - catch (IOException ioe) { - throw new InvalidMappingException( - "Could not read mapping documents from jar: " + jar.getName(), "jar", jar.getName(), - ioe - ); - } - Enumeration jarEntries = jarFile.entries(); - while ( jarEntries.hasMoreElements() ) { - ZipEntry ze = (ZipEntry) jarEntries.nextElement(); - if ( ze.getName().endsWith( ".hbm.xml" ) ) { - LOG.foundMappingDocument( ze.getName() ); - try { - addInputStream( jarFile.getInputStream( ze ) ); - } - catch (Exception e) { - throw new InvalidMappingException( - "Could not read mapping documents from jar: " + jar.getName(), - "jar", - jar.getName(), - e - ); - } - } - } - } - finally { - try { - if ( jarFile != null ) { - jarFile.close(); - } - } - catch (IOException ioe) { - LOG.unableToCloseJar( ioe.getMessage() ); - } - } - + metadataSources.addJar( jar ); return this; } @@ -888,3016 +605,264 @@ public Configuration addJar(File jar) throws MappingException { * processing the contained mapping documents. */ public Configuration addDirectory(File dir) throws MappingException { - File[] files = dir.listFiles(); - if ( files != null ) { - for ( File file : files ) { - if ( file.isDirectory() ) { - addDirectory( file ); - } - else if ( file.getName().endsWith( ".hbm.xml" ) ) { - addFile( file ); - } - } - } + metadataSources.addDirectory( dir ); return this; } + + // SessionFactory building ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + /** - * Create a new Mappings to add class and collection mappings to. + * Retrieve the configured {@link Interceptor}. * - * @return The created mappings + * @return The current {@link Interceptor} */ - public Mappings createMappings() { - return new MappingsImpl(); - } - - - @SuppressWarnings({ "unchecked" }) - public Iterator iterateGenerators(Dialect dialect) throws MappingException { - - TreeMap generators = new TreeMap(); - String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG ); - String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA ); - - for ( PersistentClass pc : classes.values() ) { - if ( !pc.isInherited() ) { - IdentifierGenerator ig = pc.getIdentifier().createIdentifierGenerator( - getIdentifierGeneratorFactory(), - dialect, - defaultCatalog, - defaultSchema, - (RootClass) pc - ); - - if ( ig instanceof PersistentIdentifierGenerator ) { - generators.put( ( (PersistentIdentifierGenerator) ig ).generatorKey(), ig ); - } - else if ( ig instanceof IdentifierGeneratorAggregator ) { - ( (IdentifierGeneratorAggregator) ig ).registerPersistentGenerators( generators ); - } - } - } - - for ( Collection collection : collections.values() ) { - if ( collection.isIdentified() ) { - IdentifierGenerator ig = ( ( IdentifierCollection ) collection ).getIdentifier().createIdentifierGenerator( - getIdentifierGeneratorFactory(), - dialect, - defaultCatalog, - defaultSchema, - null - ); - - if ( ig instanceof PersistentIdentifierGenerator ) { - generators.put( ( (PersistentIdentifierGenerator) ig ).generatorKey(), ig ); - } - } - } - - return generators.values().iterator(); + public Interceptor getInterceptor() { + return interceptor; } /** - * Generate DDL for dropping tables + * Set the current {@link Interceptor} * - * @param dialect The dialect for which to generate the drop script - - * @return The sequence of DDL commands to drop the schema objects - - * @throws HibernateException Generally indicates a problem calling {@link #buildMappings()} - - * @see org.hibernate.tool.hbm2ddl.SchemaExport + * @param interceptor The {@link Interceptor} to use for the {@link #buildSessionFactory built} + * {@link SessionFactory}. + * + * @return this for method chaining */ - public String[] generateDropSchemaScript(Dialect dialect) throws HibernateException { - secondPassCompile(); - - String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG ); - String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA ); - - ArrayList script = new ArrayList( 50 ); - - // drop them in reverse order in case db needs it done that way... - { - ListIterator itr = auxiliaryDatabaseObjects.listIterator( auxiliaryDatabaseObjects.size() ); - while ( itr.hasPrevious() ) { - AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr.previous(); - if ( object.appliesToDialect( dialect ) ) { - script.add( object.sqlDropString( dialect, defaultCatalog, defaultSchema ) ); - } - } - } - - if ( dialect.dropConstraints() ) { - Iterator itr = getTableMappings(); - while ( itr.hasNext() ) { - Table table = (Table) itr.next(); - if ( table.isPhysicalTable() ) { - Iterator subItr = table.getForeignKeyIterator(); - while ( subItr.hasNext() ) { - ForeignKey fk = (ForeignKey) subItr.next(); - if ( fk.isPhysicalConstraint() ) { - script.add( - fk.sqlDropString( - dialect, - defaultCatalog, - defaultSchema - ) - ); - } - } - } - } - } - - - Iterator itr = getTableMappings(); - while ( itr.hasNext() ) { + public Configuration setInterceptor(Interceptor interceptor) { + this.interceptor = interceptor; + return this; + } - Table table = (Table) itr.next(); - if ( table.isPhysicalTable() ) { + public EntityTuplizerFactory getEntityTuplizerFactory() { + return entityTuplizerFactory; + } - /*Iterator subIter = table.getIndexIterator(); - while ( subIter.hasNext() ) { - Index index = (Index) subIter.next(); - if ( !index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey() ) { - script.add( index.sqlDropString(dialect) ); - } - }*/ + /** + * Retrieve the user-supplied delegate to handle non-existent entity + * scenarios. May be null. + * + * @return The user-supplied delegate + */ + public EntityNotFoundDelegate getEntityNotFoundDelegate() { + return entityNotFoundDelegate; + } - script.add( - table.sqlDropString( - dialect, - defaultCatalog, - defaultSchema - ) - ); + /** + * Specify a user-supplied delegate to be used to handle scenarios where an entity could not be + * located by specified id. This is mainly intended for EJB3 implementations to be able to + * control how proxy initialization errors should be handled... + * + * @param entityNotFoundDelegate The delegate to use + */ + public void setEntityNotFoundDelegate(EntityNotFoundDelegate entityNotFoundDelegate) { + this.entityNotFoundDelegate = entityNotFoundDelegate; + } - } + public SessionFactoryObserver getSessionFactoryObserver() { + return sessionFactoryObserver; + } - } + public void setSessionFactoryObserver(SessionFactoryObserver sessionFactoryObserver) { + this.sessionFactoryObserver = sessionFactoryObserver; + } - itr = iterateGenerators( dialect ); - while ( itr.hasNext() ) { - String[] lines = ( (PersistentIdentifierGenerator) itr.next() ).sqlDropStrings( dialect ); - script.addAll( Arrays.asList( lines ) ); - } + public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { + return currentTenantIdentifierResolver; + } - return ArrayHelper.toStringArray( script ); + public void setCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver currentTenantIdentifierResolver) { + this.currentTenantIdentifierResolver = currentTenantIdentifierResolver; } /** - * @param dialect The dialect for which to generate the creation script + * Create a {@link SessionFactory} using the properties and mappings in this configuration. The + * {@link SessionFactory} will be immutable, so changes made to {@code this} {@link Configuration} after + * building the {@link SessionFactory} will not affect it. * - * @return The sequence of DDL commands to create the schema objects + * @param serviceRegistry The registry of services to be used in creating this session factory. * - * @throws HibernateException Generally indicates a problem calling {@link #buildMappings()} + * @return The built {@link SessionFactory} * - * @see org.hibernate.tool.hbm2ddl.SchemaExport + * @throws HibernateException usually indicates an invalid configuration or invalid mapping information */ - @SuppressWarnings({ "unchecked" }) - public String[] generateSchemaCreationScript(Dialect dialect) throws HibernateException { - secondPassCompile(); - - ArrayList script = new ArrayList( 50 ); - String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG ); - String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA ); - - Iterator iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - if ( table.isPhysicalTable() ) { - script.add( - table.sqlCreateString( - dialect, - mapping, - defaultCatalog, - defaultSchema - ) - ); - Iterator comments = table.sqlCommentStrings( dialect, defaultCatalog, defaultSchema ); - while ( comments.hasNext() ) { - script.add( comments.next() ); - } - } - } - - iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - if ( table.isPhysicalTable() ) { - - Iterator subIter = table.getUniqueKeyIterator(); - while ( subIter.hasNext() ) { - UniqueKey uk = (UniqueKey) subIter.next(); - String constraintString = uk.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema ); - if (constraintString != null) script.add( constraintString ); - } - - - subIter = table.getIndexIterator(); - while ( subIter.hasNext() ) { - Index index = (Index) subIter.next(); - script.add( - index.sqlCreateString( - dialect, - mapping, - defaultCatalog, - defaultSchema - ) - ); - } - } - } + public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException { + log.debug( "Building session factory using provided StandardServiceRegistry" ); - // Foreign keys must be created *after* unique keys for numerous DBs. See HH-8390. - iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - if ( table.isPhysicalTable() ) { - - if ( dialect.hasAlterTable() ) { - Iterator subIter = table.getForeignKeyIterator(); - while ( subIter.hasNext() ) { - ForeignKey fk = (ForeignKey) subIter.next(); - if ( fk.isPhysicalConstraint() ) { - script.add( - fk.sqlCreateString( - dialect, mapping, - defaultCatalog, - defaultSchema - ) - ); - } - } - } + // todo : account for : + // * auxiliary db objects + // * named queries (all sorts) + // * functions + // * attribute converters - } + final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( (StandardServiceRegistry) serviceRegistry ); + if ( namingStrategy != null ) { + metadataBuilder.with( namingStrategy ); } - - iter = iterateGenerators( dialect ); - while ( iter.hasNext() ) { - String[] lines = ( (PersistentIdentifierGenerator) iter.next() ).sqlCreateStrings( dialect ); - script.addAll( Arrays.asList( lines ) ); + if ( !typeContributorRegistrations.isEmpty() ) { + for ( TypeContributor typeContributor : typeContributorRegistrations ) { + metadataBuilder.with( typeContributor ); + } } - - for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : auxiliaryDatabaseObjects ) { - if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) ) { - script.add( auxiliaryDatabaseObject.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema ) ); + if ( !basicTypes.isEmpty() ) { + for ( BasicType basicType : basicTypes ) { + metadataBuilder.with( basicType ); } } - return ArrayHelper.toStringArray( script ); + return metadataBuilder.build().buildSessionFactory(); } + /** - * @param dialect The dialect for which to generate the creation script - * @param databaseMetadata The database catalog information for the database to be updated; needed to work out what - * should be created/altered - * - * @return The sequence of DDL commands to apply the schema objects + * Create a {@link SessionFactory} using the properties and mappings in this configuration. The + * {@link SessionFactory} will be immutable, so changes made to {@code this} {@link Configuration} after + * building the {@link SessionFactory} will not affect it. * - * @throws HibernateException Generally indicates a problem calling {@link #buildMappings()} + * @return The build {@link SessionFactory} * - * @see org.hibernate.tool.hbm2ddl.SchemaUpdate - * - * @deprecated Use {@link #generateSchemaUpdateScriptList(Dialect, DatabaseMetadata)} instead + * @throws HibernateException usually indicates an invalid configuration or invalid mapping information */ - @SuppressWarnings({ "unchecked" }) - @Deprecated - public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata) - throws HibernateException { - List scripts = generateSchemaUpdateScriptList( dialect, databaseMetadata ); - return SchemaUpdateScript.toStringArray( scripts ); + public SessionFactory buildSessionFactory() throws HibernateException { + log.debug( "Building session factory using internal StandardServiceRegistryBuilder" ); + standardServiceRegistryBuilder.applySettings( properties ); + return buildSessionFactory( standardServiceRegistryBuilder.build() ); } - - /** - * @param dialect The dialect for which to generate the creation script - * @param databaseMetadata The database catalog information for the database to be updated; needed to work out what - * should be created/altered - * - * @return The sequence of DDL commands to apply the schema objects - * - * @throws HibernateException Generally indicates a problem calling {@link #buildMappings()} - * - * @see org.hibernate.tool.hbm2ddl.SchemaUpdate - */ - public List generateSchemaUpdateScriptList(Dialect dialect, DatabaseMetadata databaseMetadata) - throws HibernateException { - secondPassCompile(); - - String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG ); - String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA ); - UniqueConstraintSchemaUpdateStrategy constraintMethod = UniqueConstraintSchemaUpdateStrategy.interpret( properties - .get( Environment.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY ) ); - - List scripts = new ArrayList(); - - Iterator iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema(); - String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog(); - if ( table.isPhysicalTable() ) { - - TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema, - tableCatalog, table.isQuoted() ); - if ( tableInfo == null ) { - scripts.add( new SchemaUpdateScript( table.sqlCreateString( dialect, mapping, tableCatalog, - tableSchema ), false ) ); - } - else { - Iterator subiter = table.sqlAlterStrings( dialect, mapping, tableInfo, tableCatalog, - tableSchema ); - while ( subiter.hasNext() ) { - scripts.add( new SchemaUpdateScript( subiter.next(), false ) ); - } - } - - Iterator comments = table.sqlCommentStrings( dialect, defaultCatalog, defaultSchema ); - while ( comments.hasNext() ) { - scripts.add( new SchemaUpdateScript( comments.next(), false ) ); - } - } - } - iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema(); - String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog(); - if ( table.isPhysicalTable() ) { - - TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema, - tableCatalog, table.isQuoted() ); - - if (! constraintMethod.equals( UniqueConstraintSchemaUpdateStrategy.SKIP )) { - Iterator uniqueIter = table.getUniqueKeyIterator(); - while ( uniqueIter.hasNext() ) { - final UniqueKey uniqueKey = (UniqueKey) uniqueIter.next(); - // Skip if index already exists. Most of the time, this - // won't work since most Dialects use Constraints. However, - // keep it for the few that do use Indexes. - if ( tableInfo != null && StringHelper.isNotEmpty( uniqueKey.getName() ) ) { - final IndexMetadata meta = tableInfo.getIndexMetadata( uniqueKey.getName() ); - if ( meta != null ) { - continue; - } - } - String constraintString = uniqueKey.sqlCreateString( dialect, mapping, tableCatalog, tableSchema ); - if ( constraintString != null && !constraintString.isEmpty() ) - if ( constraintMethod.equals( UniqueConstraintSchemaUpdateStrategy.DROP_RECREATE_QUIETLY ) ) { - String constraintDropString = uniqueKey.sqlDropString( dialect, tableCatalog, tableSchema ); - scripts.add( new SchemaUpdateScript( constraintDropString, true) ); - } - scripts.add( new SchemaUpdateScript( constraintString, true) ); - } - } - - Iterator subIter = table.getIndexIterator(); - while ( subIter.hasNext() ) { - final Index index = (Index) subIter.next(); - // Skip if index already exists - if ( tableInfo != null && StringHelper.isNotEmpty( index.getName() ) ) { - final IndexMetadata meta = tableInfo.getIndexMetadata( index.getName() ); - if ( meta != null ) { - continue; - } - } - scripts.add( new SchemaUpdateScript( index.sqlCreateString( dialect, mapping, tableCatalog, - tableSchema ), false ) ); - } - } - } - // Foreign keys must be created *after* unique keys for numerous DBs. See HH-8390. - iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema(); - String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog(); - if ( table.isPhysicalTable() ) { - - TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema, - tableCatalog, table.isQuoted() ); - - if ( dialect.hasAlterTable() ) { - Iterator subIter = table.getForeignKeyIterator(); - while ( subIter.hasNext() ) { - ForeignKey fk = (ForeignKey) subIter.next(); - if ( fk.isPhysicalConstraint() ) { - boolean create = tableInfo == null || ( tableInfo.getForeignKeyMetadata( fk ) == null && ( - // Icky workaround for MySQL bug: - !( dialect instanceof MySQLDialect ) || tableInfo.getIndexMetadata( fk.getName() ) == null ) ); - if ( create ) { - scripts.add( new SchemaUpdateScript( fk.sqlCreateString( dialect, mapping, - tableCatalog, tableSchema ), false ) ); - } - } - } - } - } - } - iter = iterateGenerators( dialect ); - while ( iter.hasNext() ) { - PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter.next(); - Object key = generator.generatorKey(); - if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) { - String[] lines = generator.sqlCreateStrings( dialect ); - scripts.addAll( SchemaUpdateScript.fromStringArray( lines, false ) ); - } - } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // todo : decide about these - return scripts; + public Map getNamedSQLQueries() { + return namedSqlQueries; } - public void validateSchema(Dialect dialect, DatabaseMetadata databaseMetadata)throws HibernateException { - secondPassCompile(); - - String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG ); - String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA ); - - Iterator iter = getTableMappings(); - while ( iter.hasNext() ) { - Table table = (Table) iter.next(); - if ( table.isPhysicalTable() ) { - - - TableMetadata tableInfo = databaseMetadata.getTableMetadata( - table.getName(), - ( table.getSchema() == null ) ? defaultSchema : table.getSchema(), - ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog(), - table.isQuoted()); - if ( tableInfo == null ) { - throw new HibernateException( "Missing table: " + table.getName() ); - } - else { - table.validateColumns( dialect, mapping, tableInfo ); - } + public Map getSqlResultSetMappings() { + return sqlResultSetMappings; + } - } - } + public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) { + auxiliaryDatabaseObjects.add( object ); + } - iter = iterateGenerators( dialect ); - while ( iter.hasNext() ) { - PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter.next(); - Object key = generator.generatorKey(); - if (key instanceof String) { - key = normalizer.normalizeIdentifierQuoting( (String) key ); - } - if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) { - throw new HibernateException( "Missing sequence or table: " + key ); - } - } + public Map getSqlFunctions() { + return sqlFunctions; } - private void validate() throws MappingException { - Iterator iter = classes.values().iterator(); - while ( iter.hasNext() ) { - ( (PersistentClass) iter.next() ).validate( mapping ); - } - iter = collections.values().iterator(); - while ( iter.hasNext() ) { - ( (Collection) iter.next() ).validate( mapping ); - } + public void addSqlFunction(String functionName, SQLFunction function) { + // HHH-7721: SQLFunctionRegistry expects all lowercase. Enforce, + // just in case a user's customer dialect uses mixed cases. + sqlFunctions.put( functionName.toLowerCase(), function ); } + /** - * Call this to ensure the mappings are fully compiled/built. Usefull to ensure getting - * access to all information in the metamodel when calling e.g. getClassMappings(). + * Adds the AttributeConverter Class to this Configuration. + * + * @param attributeConverterClass The AttributeConverter class. + * @param autoApply Should the AttributeConverter be auto applied to property types as specified + * by its "entity attribute" parameterized type? */ - public void buildMappings() { - secondPassCompile(); - } - - protected void secondPassCompile() throws MappingException { - LOG.trace( "Starting secondPassCompile() processing" ); - - // TEMPORARY - // Ensure the correct ClassLoader is used in commons-annotations. - ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader( ClassLoaderHelper.getContextClassLoader() ); - - //process default values first - { - if ( !isDefaultProcessed ) { - //use global delimiters if orm.xml declare it - Map defaults = reflectionManager.getDefaults(); - final Object isDelimited = defaults.get( "delimited-identifier" ); - if ( isDelimited != null && isDelimited == Boolean.TRUE ) { - getProperties().put( Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true" ); - } - // Set default schema name if orm.xml declares it. - final String schema = (String) defaults.get( "schema" ); - if ( StringHelper.isNotEmpty( schema ) ) { - getProperties().put( Environment.DEFAULT_SCHEMA, schema ); - } - // Set default catalog name if orm.xml declares it. - final String catalog = (String) defaults.get( "catalog" ); - if ( StringHelper.isNotEmpty( catalog ) ) { - getProperties().put( Environment.DEFAULT_CATALOG, catalog ); - } - - AnnotationBinder.bindDefaults( createMappings() ); - isDefaultProcessed = true; - } - } - - // process metadata queue - { - metadataSourceQueue.syncAnnotatedClasses(); - metadataSourceQueue.processMetadata( determineMetadataSourcePrecedence() ); - } - - - + public void addAttributeConverter(Class attributeConverterClass, boolean autoApply) { + final AttributeConverter attributeConverter; try { - inSecondPass = true; - processSecondPassesOfType( PkDrivenByDefaultMapsIdSecondPass.class ); - processSecondPassesOfType( SetSimpleValueTypeSecondPass.class ); - processSecondPassesOfType( CopyIdentifierComponentSecondPass.class ); - processFkSecondPassInOrder(); - processSecondPassesOfType( CreateKeySecondPass.class ); - processSecondPassesOfType( SecondaryTableSecondPass.class ); - - originalSecondPassCompile(); - - inSecondPass = false; - } - catch ( RecoverableException e ) { - //the exception was not recoverable after all - throw ( RuntimeException ) e.getCause(); - } - - // process cache queue - { - for ( CacheHolder holder : caches ) { - if ( holder.isClass ) { - applyCacheConcurrencyStrategy( holder ); - } - else { - applyCollectionCacheConcurrencyStrategy( holder ); - } - } - caches.clear(); - } - - for ( Map.Entry> tableListEntry : uniqueConstraintHoldersByTable.entrySet() ) { - final Table table = tableListEntry.getKey(); - final List uniqueConstraints = tableListEntry.getValue(); - for ( UniqueConstraintHolder holder : uniqueConstraints ) { - buildUniqueKeyFromColumnNames( table, holder.getName(), holder.getColumns() ); - } - } - - for(Table table : jpaIndexHoldersByTable.keySet()){ - final List jpaIndexHolders = jpaIndexHoldersByTable.get( table ); - for ( JPAIndexHolder holder : jpaIndexHolders ) { - buildUniqueKeyFromColumnNames( table, holder.getName(), holder.getColumns(), holder.getOrdering(), holder.isUnique() ); - } + attributeConverter = attributeConverterClass.newInstance(); } - - Thread.currentThread().setContextClassLoader( tccl ); - } - - private void processSecondPassesOfType(Class type) { - Iterator iter = secondPasses.iterator(); - while ( iter.hasNext() ) { - SecondPass sp = ( SecondPass ) iter.next(); - //do the second pass of simple value types first and remove them - if ( type.isInstance( sp ) ) { - sp.doSecondPass( classes ); - iter.remove(); - } + catch (Exception e) { + throw new AnnotationException( + "Unable to instantiate AttributeConverter [" + attributeConverterClass.getName() + "]" + ); } + addAttributeConverter( attributeConverter, autoApply ); } /** - * Processes FKSecondPass instances trying to resolve any - * graph circularity (ie PK made of a many to one linking to - * an entity having a PK made of a ManyToOne ...). + * Adds the AttributeConverter Class to this Configuration. + * + * @param attributeConverterClass The AttributeConverter class. */ - private void processFkSecondPassInOrder() { - LOG.debug("Processing fk mappings (*ToOne and JoinedSubclass)"); - List fkSecondPasses = getFKSecondPassesOnly(); - - if ( fkSecondPasses.size() == 0 ) { - return; // nothing to do here - } - - // split FkSecondPass instances into primary key and non primary key FKs. - // While doing so build a map of class names to FkSecondPass instances depending on this class. - Map> isADependencyOf = new HashMap>(); - List endOfQueueFkSecondPasses = new ArrayList( fkSecondPasses.size() ); - for ( FkSecondPass sp : fkSecondPasses ) { - if ( sp.isInPrimaryKey() ) { - String referenceEntityName = sp.getReferencedEntityName(); - PersistentClass classMapping = getClassMapping( referenceEntityName ); - String dependentTable = quotedTableName(classMapping.getTable()); - if ( !isADependencyOf.containsKey( dependentTable ) ) { - isADependencyOf.put( dependentTable, new HashSet() ); - } - isADependencyOf.get( dependentTable ).add( sp ); - } - else { - endOfQueueFkSecondPasses.add( sp ); - } - } - - // using the isADependencyOf map we order the FkSecondPass recursively instances into the right order for processing - List orderedFkSecondPasses = new ArrayList( fkSecondPasses.size() ); - for ( String tableName : isADependencyOf.keySet() ) { - buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, tableName, tableName ); + public void addAttributeConverter(Class attributeConverterClass) { + final AttributeConverter attributeConverter; + try { + attributeConverter = attributeConverterClass.newInstance(); } - - // process the ordered FkSecondPasses - for ( FkSecondPass sp : orderedFkSecondPasses ) { - sp.doSecondPass( classes ); + catch (Exception e) { + throw new AnnotationException( + "Unable to instantiate AttributeConverter [" + attributeConverterClass.getName() + "]" + ); } - processEndOfQueue( endOfQueueFkSecondPasses ); + addAttributeConverter( attributeConverter ); } /** - * @return Returns a list of all secondPasses instances which are a instance of - * FkSecondPass. + * Adds the AttributeConverter instance to this Configuration. This form is mainly intended for developers + * to programatically add their own AttributeConverter instance. HEM, instead, uses the + * {@link #addAttributeConverter(Class, boolean)} form + * + * @param attributeConverter The AttributeConverter instance. */ - private List getFKSecondPassesOnly() { - Iterator iter = secondPasses.iterator(); - List fkSecondPasses = new ArrayList( secondPasses.size() ); - while ( iter.hasNext() ) { - SecondPass sp = ( SecondPass ) iter.next(); - //do the second pass of fk before the others and remove them - if ( sp instanceof FkSecondPass ) { - fkSecondPasses.add( ( FkSecondPass ) sp ); - iter.remove(); - } + public void addAttributeConverter(AttributeConverter attributeConverter) { + boolean autoApply = false; + Converter converterAnnotation = attributeConverter.getClass().getAnnotation( Converter.class ); + if ( converterAnnotation != null ) { + autoApply = converterAnnotation.autoApply(); } - return fkSecondPasses; + + addAttributeConverter( new AttributeConverterDefinition( attributeConverter, autoApply ) ); } /** - * Recursively builds a list of FkSecondPass instances ready to be processed in this order. - * Checking all dependencies recursively seems quite expensive, but the original code just relied - * on some sort of table name sorting which failed in certain circumstances. - *

    - * See ANN-722 and ANN-730 + * Adds the AttributeConverter instance to this Configuration. This form is mainly intended for developers + * to programatically add their own AttributeConverter instance. HEM, instead, uses the + * {@link #addAttributeConverter(Class, boolean)} form * - * @param orderedFkSecondPasses The list containing the FkSecondPass instances ready - * for processing. - * @param isADependencyOf Our lookup data structure to determine dependencies between tables - * @param startTable Table name to start recursive algorithm. - * @param currentTable The current table name used to check for 'new' dependencies. + * @param attributeConverter The AttributeConverter instance. + * @param autoApply Should the AttributeConverter be auto applied to property types as specified + * by its "entity attribute" parameterized type? */ - private void buildRecursiveOrderedFkSecondPasses( - List orderedFkSecondPasses, - Map> isADependencyOf, - String startTable, - String currentTable) { - - Set dependencies = isADependencyOf.get( currentTable ); + public void addAttributeConverter(AttributeConverter attributeConverter, boolean autoApply) { + addAttributeConverter( new AttributeConverterDefinition( attributeConverter, autoApply ) ); + } - // bottom out - if ( dependencies == null || dependencies.size() == 0 ) { - return; + public void addAttributeConverter(AttributeConverterDefinition definition) { + if ( attributeConverterDefinitionsByClass == null ) { + attributeConverterDefinitionsByClass = new ConcurrentHashMap(); } - for ( FkSecondPass sp : dependencies ) { - String dependentTable = quotedTableName(sp.getValue().getTable()); - if ( dependentTable.compareTo( startTable ) == 0 ) { - String sb = "Foreign key circularity dependency involving the following tables: "; - throw new AnnotationException( sb ); - } - buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable, dependentTable ); - if ( !orderedFkSecondPasses.contains( sp ) ) { - orderedFkSecondPasses.add( 0, sp ); - } - } - } + final Object old = attributeConverterDefinitionsByClass.put( definition.getAttributeConverter().getClass(), definition ); - private String quotedTableName(Table table) { - return Table.qualify( table.getCatalog(), table.getQuotedSchema(), table.getQuotedName() ); - } - - private void processEndOfQueue(List endOfQueueFkSecondPasses) { - /* - * If a second pass raises a recoverableException, queue it for next round - * stop of no pass has to be processed or if the number of pass to processes - * does not diminish between two rounds. - * If some failing pass remain, raise the original exception - */ - boolean stopProcess = false; - RuntimeException originalException = null; - while ( !stopProcess ) { - List failingSecondPasses = new ArrayList(); - for ( FkSecondPass pass : endOfQueueFkSecondPasses ) { - try { - pass.doSecondPass( classes ); - } - catch (RecoverableException e) { - failingSecondPasses.add( pass ); - if ( originalException == null ) { - originalException = (RuntimeException) e.getCause(); - } - } - } - stopProcess = failingSecondPasses.size() == 0 || failingSecondPasses.size() == endOfQueueFkSecondPasses.size(); - endOfQueueFkSecondPasses = failingSecondPasses; - } - if ( endOfQueueFkSecondPasses.size() > 0 ) { - throw originalException; + if ( old != null ) { + throw new AssertionFailure( + String.format( + "AttributeConverter class [%s] registered multiple times", + definition.getAttributeConverter().getClass() + ) + ); } } - private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames){ - buildUniqueKeyFromColumnNames( table, keyName, columnNames, null, true ); + public java.util.Collection getNamedEntityGraphs() { + return namedEntityGraphMap == null + ? Collections.emptyList() + : namedEntityGraphMap.values(); } - private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames, String[] orderings, boolean unique) { - int size = columnNames.length; - Column[] columns = new Column[size]; - Set unbound = new HashSet(); - Set unboundNoLogical = new HashSet(); - for ( int index = 0; index < size; index++ ) { - String column = columnNames[index]; - try { - final String columnName = createMappings().getPhysicalColumnName( column, table ); - columns[index] = new Column( columnName ); - unbound.add( columns[index] ); - //column equals and hashcode is based on column name - } - catch ( MappingException e ) { - // If at least 1 columnName does exist, 'columns' will contain a mix of Columns and nulls. In order - // to exhaustively report all of the unbound columns at once, w/o an NPE in - // Constraint#generateName's array sorting, simply create a fake Column. - columns[index] = new Column( column ); - unboundNoLogical.add( columns[index] ); - } - } - - if ( StringHelper.isEmpty( keyName ) ) { - keyName = Constraint.generateName( "UK_", table, columns ); - } - keyName = normalizer.normalizeIdentifierQuoting( keyName ); - - if ( unique ) { - UniqueKey uk = table.getOrCreateUniqueKey( keyName ); - for ( int i = 0; i < columns.length; i++ ) { - Column column = columns[i]; - String order = orderings != null ? orderings[i] : null; - if ( table.containsColumn( column ) ) { - uk.addColumn( column, order ); - unbound.remove( column ); - } - } - } - else { - Index index = table.getOrCreateIndex( keyName ); - for ( int i = 0; i < columns.length; i++ ) { - Column column = columns[i]; - String order = orderings != null ? orderings[i] : null; - if ( table.containsColumn( column ) ) { - index.addColumn( column, order ); - unbound.remove( column ); - } - } - } - if ( unbound.size() > 0 || unboundNoLogical.size() > 0 ) { - StringBuilder sb = new StringBuilder( "Unable to create unique key constraint (" ); - for ( String columnName : columnNames ) { - sb.append( columnName ).append( ", " ); - } - sb.setLength( sb.length() - 2 ); - sb.append( ") on table " ).append( table.getName() ).append( ": database column " ); - for ( Column column : unbound ) { - sb.append("'").append( column.getName() ).append( "', " ); - } - for ( Column column : unboundNoLogical ) { - sb.append("'").append( column.getName() ).append( "', " ); - } - sb.setLength( sb.length() - 2 ); - sb.append( " not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)" ); - throw new AnnotationException( sb.toString() ); - } + public Map getNamedQueries() { + return namedQueries; } - private void originalSecondPassCompile() throws MappingException { - LOG.debug( "Processing extends queue" ); - processExtendsQueue(); - - LOG.debug( "Processing collection mappings" ); - Iterator itr = secondPasses.iterator(); - while ( itr.hasNext() ) { - SecondPass sp = (SecondPass) itr.next(); - if ( ! (sp instanceof QuerySecondPass) ) { - sp.doSecondPass( classes ); - itr.remove(); - } - } - - LOG.debug( "Processing native query and ResultSetMapping mappings" ); - itr = secondPasses.iterator(); - while ( itr.hasNext() ) { - SecondPass sp = (SecondPass) itr.next(); - sp.doSecondPass( classes ); - itr.remove(); - } - - LOG.debug( "Processing association property references" ); - - itr = propertyReferences.iterator(); - while ( itr.hasNext() ) { - Mappings.PropertyReference upr = (Mappings.PropertyReference) itr.next(); - - PersistentClass clazz = getClassMapping( upr.referencedClass ); - if ( clazz == null ) { - throw new MappingException( - "property-ref to unmapped class: " + - upr.referencedClass - ); - } - - Property prop = clazz.getReferencedProperty( upr.propertyName ); - if ( upr.unique ) { - ( (SimpleValue) prop.getValue() ).setAlternateUniqueKey( true ); - } - } - - //TODO: Somehow add the newly created foreign keys to the internal collection - - LOG.debug( "Creating tables' unique integer identifiers" ); - LOG.debug( "Processing foreign key constraints" ); - - itr = getTableMappings(); - int uniqueInteger = 0; - Set done = new HashSet(); - while ( itr.hasNext() ) { - Table table = (Table) itr.next(); - table.setUniqueInteger( uniqueInteger++ ); - secondPassCompileForeignKeys( table, done ); - } - - } - - private int processExtendsQueue() { - LOG.debug( "Processing extends queue" ); - int added = 0; - ExtendsQueueEntry extendsQueueEntry = findPossibleExtends(); - while ( extendsQueueEntry != null ) { - metadataSourceQueue.processHbmXml( extendsQueueEntry.getMetadataXml(), extendsQueueEntry.getEntityNames() ); - extendsQueueEntry = findPossibleExtends(); - } - - if ( extendsQueue.size() > 0 ) { - Iterator iterator = extendsQueue.keySet().iterator(); - StringBuilder buf = new StringBuilder( "Following super classes referenced in extends not found: " ); - while ( iterator.hasNext() ) { - final ExtendsQueueEntry entry = ( ExtendsQueueEntry ) iterator.next(); - buf.append( entry.getExplicitName() ); - if ( entry.getMappingPackage() != null ) { - buf.append( "[" ).append( entry.getMappingPackage() ).append( "]" ); - } - if ( iterator.hasNext() ) { - buf.append( "," ); - } - } - throw new MappingException( buf.toString() ); - } - - return added; - } - - protected ExtendsQueueEntry findPossibleExtends() { - Iterator itr = extendsQueue.keySet().iterator(); - while ( itr.hasNext() ) { - final ExtendsQueueEntry entry = itr.next(); - boolean found = getClassMapping( entry.getExplicitName() ) != null - || getClassMapping( HbmBinder.getClassName( entry.getExplicitName(), entry.getMappingPackage() ) ) != null; - if ( found ) { - itr.remove(); - return entry; - } - } - return null; - } - - protected void secondPassCompileForeignKeys(Table table, Set done) throws MappingException { - table.createForeignKeys(); - Iterator iter = table.getForeignKeyIterator(); - while ( iter.hasNext() ) { - - ForeignKey fk = (ForeignKey) iter.next(); - if ( !done.contains( fk ) ) { - done.add( fk ); - final String referencedEntityName = fk.getReferencedEntityName(); - if ( referencedEntityName == null ) { - throw new MappingException( - "An association from the table " + - fk.getTable().getName() + - " does not specify the referenced entity" - ); - } - LOG.debugf( "Resolving reference to class: %s", referencedEntityName ); - PersistentClass referencedClass = classes.get( referencedEntityName ); - if ( referencedClass == null ) { - throw new MappingException( - "An association from the table " + - fk.getTable().getName() + - " refers to an unmapped class: " + - referencedEntityName - ); - } - if ( referencedClass.isJoinedSubclass() ) { - secondPassCompileForeignKeys( referencedClass.getSuperclass().getTable(), done ); - } - fk.setReferencedTable( referencedClass.getTable() ); - fk.alignColumns(); - } - } - } - - public Map getNamedQueries() { - return namedQueries; - } - - public Map getNamedProcedureCallMap() { - return namedProcedureCallMap; - } - - /** - * Create a {@link SessionFactory} using the properties and mappings in this configuration. The - * {@link SessionFactory} will be immutable, so changes made to {@code this} {@link Configuration} after - * building the {@link SessionFactory} will not affect it. - * - * @param serviceRegistry The registry of services to be used in creating this session factory. - * - * @return The built {@link SessionFactory} - * - * @throws HibernateException usually indicates an invalid configuration or invalid mapping information - */ - public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException { - LOG.debugf( "Preparing to build session factory with filters : %s", filterDefinitions ); - - buildTypeRegistrations( serviceRegistry ); - secondPassCompile(); - if ( !metadataSourceQueue.isEmpty() ) { - LOG.incompleteMappingMetadataCacheProcessing(); - } - - validate(); - - Environment.verifyProperties( properties ); - Properties copy = new Properties(); - copy.putAll( properties ); - ConfigurationHelper.resolvePlaceHolders( copy ); - Settings settings = buildSettings( copy, serviceRegistry ); - - return new SessionFactoryImpl( - this, - mapping, - serviceRegistry, - settings, - sessionFactoryObserver - ); - } - - private void buildTypeRegistrations(ServiceRegistry serviceRegistry) { - final TypeContributions typeContributions = new TypeContributions() { - @Override - public void contributeType(BasicType type) { - typeResolver.registerTypeOverride( type ); - } - - @Override - public void contributeType(UserType type, String[] keys) { - typeResolver.registerTypeOverride( type, keys ); - } - - @Override - public void contributeType(CompositeUserType type, String[] keys) { - typeResolver.registerTypeOverride( type, keys ); - } - }; - - // add Dialect contributed types - final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); - dialect.contributeTypes( typeContributions, serviceRegistry ); - - // add TypeContributor contributed types. - ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - for ( TypeContributor contributor : classLoaderService.loadJavaServices( TypeContributor.class ) ) { - contributor.contribute( typeContributions, serviceRegistry ); - } - // from app registrations - for ( TypeContributor contributor : typeContributorRegistrations ) { - contributor.contribute( typeContributions, serviceRegistry ); - } - } - - /** - * Create a {@link SessionFactory} using the properties and mappings in this configuration. The - * {@link SessionFactory} will be immutable, so changes made to {@code this} {@link Configuration} after - * building the {@link SessionFactory} will not affect it. - * - * @return The build {@link SessionFactory} - * - * @throws HibernateException usually indicates an invalid configuration or invalid mapping information - * - * @deprecated Use {@link #buildSessionFactory(ServiceRegistry)} instead - */ - public SessionFactory buildSessionFactory() throws HibernateException { - Environment.verifyProperties( properties ); - ConfigurationHelper.resolvePlaceHolders( properties ); - final ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() - .applySettings( properties ) - .build(); - setSessionFactoryObserver( - new SessionFactoryObserver() { - @Override - public void sessionFactoryCreated(SessionFactory factory) { - } - - @Override - public void sessionFactoryClosed(SessionFactory factory) { - ( (StandardServiceRegistryImpl) serviceRegistry ).destroy(); - } - } - ); - return buildSessionFactory( serviceRegistry ); - } - - /** - * Retrieve the configured {@link Interceptor}. - * - * @return The current {@link Interceptor} - */ - public Interceptor getInterceptor() { - return interceptor; - } - - /** - * Set the current {@link Interceptor} - * - * @param interceptor The {@link Interceptor} to use for the {@link #buildSessionFactory built} - * {@link SessionFactory}. - * - * @return this for method chaining - */ - public Configuration setInterceptor(Interceptor interceptor) { - this.interceptor = interceptor; - return this; - } - - /** - * Get all properties - * - * @return all properties - */ - public Properties getProperties() { - return properties; - } - - /** - * Get a property value by name - * - * @param propertyName The name of the property - * - * @return The value currently associated with that property name; may be null. - */ - public String getProperty(String propertyName) { - return properties.getProperty( propertyName ); - } - - /** - * Specify a completely new set of properties - * - * @param properties The new set of properties - * - * @return this for method chaining - */ - public Configuration setProperties(Properties properties) { - this.properties = properties; - return this; - } - - /** - * Add the given properties to ours. - * - * @param extraProperties The properties to add. - * - * @return this for method chaining - * - */ - public Configuration addProperties(Properties extraProperties) { - this.properties.putAll( extraProperties ); - return this; - } - - /** - * Adds the incoming properties to the internal properties structure, as long as the internal structure does not - * already contain an entry for the given key. - * - * @param properties The properties to merge - * - * @return this for ethod chaining - */ - public Configuration mergeProperties(Properties properties) { - for ( Map.Entry entry : properties.entrySet() ) { - if ( this.properties.containsKey( entry.getKey() ) ) { - continue; - } - this.properties.setProperty( (String) entry.getKey(), (String) entry.getValue() ); - } - return this; - } - - /** - * Set a property value by name - * - * @param propertyName The name of the property to set - * @param value The new property value - * - * @return this for method chaining - */ - public Configuration setProperty(String propertyName, String value) { - properties.setProperty( propertyName, value ); - return this; - } - - private void addProperties(Element parent) { - Iterator itr = parent.elementIterator( "property" ); - while ( itr.hasNext() ) { - Element node = (Element) itr.next(); - String name = node.attributeValue( "name" ); - String value = node.getText().trim(); - LOG.debugf( "%s=%s", name, value ); - properties.setProperty( name, value ); - if ( !name.startsWith( "hibernate" ) ) { - properties.setProperty( "hibernate." + name, value ); - } - } - Environment.verifyProperties( properties ); - } - - /** - * Use the mappings and properties specified in an application resource named hibernate.cfg.xml. - * - * @return this for method chaining - * - * @throws HibernateException Generally indicates we cannot find hibernate.cfg.xml - * - * @see #configure(String) - */ - public Configuration configure() throws HibernateException { - configure( "/hibernate.cfg.xml" ); - return this; - } - - /** - * Use the mappings and properties specified in the given application resource. The format of the resource is - * defined in hibernate-configuration-3.0.dtd. - *

    - * The resource is found via {@link #getConfigurationInputStream} - * - * @param resource The resource to use - * - * @return this for method chaining - * - * @throws HibernateException Generally indicates we cannot find the named resource - * - * @see #doConfigure(java.io.InputStream, String) - */ - public Configuration configure(String resource) throws HibernateException { - LOG.configuringFromResource( resource ); - InputStream stream = getConfigurationInputStream( resource ); - return doConfigure( stream, resource ); - } - - /** - * Get the configuration file as an InputStream. Might be overridden - * by subclasses to allow the configuration to be located by some arbitrary - * mechanism. - *

    - * By default here we use classpath resource resolution - * - * @param resource The resource to locate - * - * @return The stream - * - * @throws HibernateException Generally indicates we cannot find the named resource - */ - protected InputStream getConfigurationInputStream(String resource) throws HibernateException { - LOG.configurationResource( resource ); - return ConfigHelper.getResourceAsStream( resource ); - } - - /** - * Use the mappings and properties specified in the given document. The format of the document is defined in - * hibernate-configuration-3.0.dtd. - * - * @param url URL from which you wish to load the configuration - * - * @return this for method chaining - * - * @throws HibernateException Generally indicates a problem access the url - * - * @see #doConfigure(java.io.InputStream, String) - */ - public Configuration configure(URL url) throws HibernateException { - LOG.configuringFromUrl( url ); - try { - return doConfigure( url.openStream(), url.toString() ); - } - catch (IOException ioe) { - throw new HibernateException( "could not configure from URL: " + url, ioe ); - } - } - - /** - * Use the mappings and properties specified in the given application file. The format of the file is defined in - * hibernate-configuration-3.0.dtd. - * - * @param configFile File from which you wish to load the configuration - * - * @return this for method chaining - * - * @throws HibernateException Generally indicates a problem access the file - * - * @see #doConfigure(java.io.InputStream, String) - */ - public Configuration configure(File configFile) throws HibernateException { - LOG.configuringFromFile( configFile.getName() ); - try { - return doConfigure( new FileInputStream( configFile ), configFile.toString() ); - } - catch (FileNotFoundException fnfe) { - throw new HibernateException( "could not find file: " + configFile, fnfe ); - } - } - - /** - * Configure this configuration's state from the contents of the given input stream. The expectation is that - * the stream contents represent an XML document conforming to the Hibernate Configuration DTD. See - * {@link #doConfigure(Document)} for further details. - * - * @param stream The input stream from which to read - * @param resourceName The name to use in warning/error messages - * - * @return this for method chaining - * - * @throws HibernateException Indicates a problem reading the stream contents. - */ - protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException { - try { - ErrorLogger errorLogger = new ErrorLogger( resourceName ); - Document document = xmlHelper.createSAXReader( errorLogger, entityResolver ) - .read( new InputSource( stream ) ); - if ( errorLogger.hasErrors() ) { - throw new MappingException( "invalid configuration", errorLogger.getErrors().get( 0 ) ); - } - doConfigure( document ); - } - catch (DocumentException e) { - throw new HibernateException( "Could not parse configuration: " + resourceName, e ); - } - finally { - try { - stream.close(); - } - catch (IOException ioe) { - LOG.unableToCloseInputStreamForResource( resourceName, ioe ); - } - } - return this; - } + public Map getNamedProcedureCallMap() { + return namedProcedureCallMap; + } /** - * Use the mappings and properties specified in the given XML document. - * The format of the file is defined in - * hibernate-configuration-3.0.dtd. - * - * @param document an XML document from which you wish to load the configuration - * @return A configuration configured via the Document - * @throws HibernateException if there is problem in accessing the file. + * @deprecated Does nothing */ - public Configuration configure(org.w3c.dom.Document document) throws HibernateException { - LOG.configuringFromXmlDocument(); - return doConfigure( xmlHelper.createDOMReader().read( document ) ); - } - - /** - * Parse a dom4j document conforming to the Hibernate Configuration DTD (hibernate-configuration-3.0.dtd) - * and use its information to configure this {@link Configuration}'s state - * - * @param doc The dom4j document - * - * @return this for method chaining - * - * @throws HibernateException Indicates a problem performing the configuration task - */ - protected Configuration doConfigure(Document doc) throws HibernateException { - Element sfNode = doc.getRootElement().element( "session-factory" ); - String name = sfNode.attributeValue( "name" ); - if ( name != null ) { - properties.setProperty( Environment.SESSION_FACTORY_NAME, name ); - } - addProperties( sfNode ); - parseSessionFactory( sfNode, name ); - - Element secNode = doc.getRootElement().element( "security" ); - if ( secNode != null ) { - parseSecurity( secNode ); - } - - LOG.configuredSessionFactory( name ); - LOG.debugf( "Properties: %s", properties ); - - return this; - } - - - private void parseSessionFactory(Element sfNode, String name) { - Iterator elements = sfNode.elementIterator(); - while ( elements.hasNext() ) { - Element subelement = (Element) elements.next(); - String subelementName = subelement.getName(); - if ( "mapping".equals( subelementName ) ) { - parseMappingElement( subelement, name ); - } - else if ( "class-cache".equals( subelementName ) ) { - String className = subelement.attributeValue( "class" ); - Attribute regionNode = subelement.attribute( "region" ); - final String region = ( regionNode == null ) ? className : regionNode.getValue(); - boolean includeLazy = !"non-lazy".equals( subelement.attributeValue( "include" ) ); - setCacheConcurrencyStrategy( className, subelement.attributeValue( "usage" ), region, includeLazy ); - } - else if ( "collection-cache".equals( subelementName ) ) { - String role = subelement.attributeValue( "collection" ); - Attribute regionNode = subelement.attribute( "region" ); - final String region = ( regionNode == null ) ? role : regionNode.getValue(); - setCollectionCacheConcurrencyStrategy( role, subelement.attributeValue( "usage" ), region ); - } - } - } - - private void parseMappingElement(Element mappingElement, String name) { - final Attribute resourceAttribute = mappingElement.attribute( "resource" ); - final Attribute fileAttribute = mappingElement.attribute( "file" ); - final Attribute jarAttribute = mappingElement.attribute( "jar" ); - final Attribute packageAttribute = mappingElement.attribute( "package" ); - final Attribute classAttribute = mappingElement.attribute( "class" ); - - if ( resourceAttribute != null ) { - final String resourceName = resourceAttribute.getValue(); - LOG.debugf( "Session-factory config [%s] named resource [%s] for mapping", name, resourceName ); - addResource( resourceName ); - } - else if ( fileAttribute != null ) { - final String fileName = fileAttribute.getValue(); - LOG.debugf( "Session-factory config [%s] named file [%s] for mapping", name, fileName ); - addFile( fileName ); - } - else if ( jarAttribute != null ) { - final String jarFileName = jarAttribute.getValue(); - LOG.debugf( "Session-factory config [%s] named jar file [%s] for mapping", name, jarFileName ); - addJar( new File( jarFileName ) ); - } - else if ( packageAttribute != null ) { - final String packageName = packageAttribute.getValue(); - LOG.debugf( "Session-factory config [%s] named package [%s] for mapping", name, packageName ); - addPackage( packageName ); - } - else if ( classAttribute != null ) { - final String className = classAttribute.getValue(); - LOG.debugf( "Session-factory config [%s] named class [%s] for mapping", name, className ); - try { - addAnnotatedClass( ReflectHelper.classForName( className ) ); - } - catch ( Exception e ) { - throw new MappingException( - "Unable to load class [ " + className + "] declared in Hibernate configuration entry", - e - ); - } - } - else { - throw new MappingException( " element in configuration specifies no known attributes" ); - } - } - - private JaccPermissionDeclarations jaccPermissionDeclarations; - - private void parseSecurity(Element secNode) { - final String nodeContextId = secNode.attributeValue( "context" ); - - final String explicitContextId = getProperty( AvailableSettings.JACC_CONTEXT_ID ); - if ( explicitContextId == null ) { - setProperty( AvailableSettings.JACC_CONTEXT_ID, nodeContextId ); - LOG.jaccContextId( nodeContextId ); - } - else { - // if they dont match, throw an error - if ( ! nodeContextId.equals( explicitContextId ) ) { - throw new HibernateException( "Non-matching JACC context ids" ); - } - } - jaccPermissionDeclarations = new JaccPermissionDeclarations( nodeContextId ); - - Iterator grantElements = secNode.elementIterator(); - while ( grantElements.hasNext() ) { - final Element grantElement = (Element) grantElements.next(); - final String elementName = grantElement.getName(); - if ( "grant".equals( elementName ) ) { - jaccPermissionDeclarations.addPermissionDeclaration( - new GrantedPermission( - grantElement.attributeValue( "role" ), - grantElement.attributeValue( "entity-name" ), - grantElement.attributeValue( "actions" ) - ) - ); - } - } - } - - public JaccPermissionDeclarations getJaccPermissionDeclarations() { - return jaccPermissionDeclarations; - } - - RootClass getRootClassMapping(String clazz) throws MappingException { - try { - return (RootClass) getClassMapping( clazz ); - } - catch (ClassCastException cce) { - throw new MappingException( "You may only specify a cache for root mappings. Attempted on " + clazz ); - } - } - - /** - * Set up a cache for an entity class - * - * @param entityName The name of the entity to which we shoudl associate these cache settings - * @param concurrencyStrategy The cache strategy to use - * - * @return this for method chaining - */ - public Configuration setCacheConcurrencyStrategy(String entityName, String concurrencyStrategy) { - setCacheConcurrencyStrategy( entityName, concurrencyStrategy, entityName ); - return this; - } - - /** - * Set up a cache for an entity class, giving an explicit region name - * - * @param entityName The name of the entity to which we should associate these cache settings - * @param concurrencyStrategy The cache strategy to use - * @param region The name of the cache region to use - * - * @return this for method chaining - */ - public Configuration setCacheConcurrencyStrategy(String entityName, String concurrencyStrategy, String region) { - setCacheConcurrencyStrategy( entityName, concurrencyStrategy, region, true ); - return this; - } - - public void setCacheConcurrencyStrategy( - String entityName, - String concurrencyStrategy, - String region, - boolean cacheLazyProperty) throws MappingException { - caches.add( new CacheHolder( entityName, concurrencyStrategy, region, true, cacheLazyProperty ) ); - } - - private void applyCacheConcurrencyStrategy(CacheHolder holder) { - RootClass rootClass = getRootClassMapping( holder.role ); - if ( rootClass == null ) { - throw new MappingException( "Cannot cache an unknown entity: " + holder.role ); - } - rootClass.setCacheConcurrencyStrategy( holder.usage ); - rootClass.setCacheRegionName( holder.region ); - rootClass.setLazyPropertiesCacheable( holder.cacheLazy ); - } - - /** - * Set up a cache for a collection role - * - * @param collectionRole The name of the collection to which we should associate these cache settings - * @param concurrencyStrategy The cache strategy to use - * - * @return this for method chaining - */ - public Configuration setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy) { - setCollectionCacheConcurrencyStrategy( collectionRole, concurrencyStrategy, collectionRole ); - return this; - } - - /** - * Set up a cache for a collection role, giving an explicit region name - * - * @param collectionRole The name of the collection to which we should associate these cache settings - * @param concurrencyStrategy The cache strategy to use - * @param region The name of the cache region to use - */ - public void setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy, String region) { - caches.add( new CacheHolder( collectionRole, concurrencyStrategy, region, false, false ) ); - } - - private void applyCollectionCacheConcurrencyStrategy(CacheHolder holder) { - Collection collection = getCollectionMapping( holder.role ); - if ( collection == null ) { - throw new MappingException( "Cannot cache an unknown collection: " + holder.role ); - } - collection.setCacheConcurrencyStrategy( holder.usage ); - collection.setCacheRegionName( holder.region ); - } - - /** - * Get the query language imports - * - * @return a mapping from "import" names to fully qualified class names - */ - public Map getImports() { - return imports; - } - - /** - * Create an object-oriented view of the configuration properties - * - * @param serviceRegistry The registry of services to be used in building these settings. - * - * @return The build settings - */ - public Settings buildSettings(ServiceRegistry serviceRegistry) { - Properties clone = ( Properties ) properties.clone(); - ConfigurationHelper.resolvePlaceHolders( clone ); - return buildSettingsInternal( clone, serviceRegistry ); - } - - public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) throws HibernateException { - return buildSettingsInternal( props, serviceRegistry ); - } - - private Settings buildSettingsInternal(Properties props, ServiceRegistry serviceRegistry) { - final Settings settings = settingsFactory.buildSettings( props, serviceRegistry ); - settings.setEntityTuplizerFactory( this.getEntityTuplizerFactory() ); -// settings.setComponentTuplizerFactory( this.getComponentTuplizerFactory() ); - return settings; - } - - public Map getNamedSQLQueries() { - return namedSqlQueries; - } - - public Map getSqlResultSetMappings() { - return sqlResultSetMappings; - } - - public NamingStrategy getNamingStrategy() { - return namingStrategy; - } - - /** - * Set a custom naming strategy - * - * @param namingStrategy the NamingStrategy to set - * - * @return this for method chaining - */ - public Configuration setNamingStrategy(NamingStrategy namingStrategy) { - this.namingStrategy = namingStrategy; - return this; - } - - /** - * Retrieve the IdentifierGeneratorFactory in effect for this configuration. - * - * @return This configuration's IdentifierGeneratorFactory. - */ - public MutableIdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return identifierGeneratorFactory; - } - - public Mapping buildMapping() { - return new Mapping() { - public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return identifierGeneratorFactory; - } - - /** - * Returns the identifier type of a mapped class - */ - public Type getIdentifierType(String entityName) throws MappingException { - PersistentClass pc = classes.get( entityName ); - if ( pc == null ) { - throw new MappingException( "persistent class not known: " + entityName ); - } - return pc.getIdentifier().getType(); - } - - public String getIdentifierPropertyName(String entityName) throws MappingException { - final PersistentClass pc = classes.get( entityName ); - if ( pc == null ) { - throw new MappingException( "persistent class not known: " + entityName ); - } - if ( !pc.hasIdentifierProperty() ) { - return null; - } - return pc.getIdentifierProperty().getName(); - } - - public Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { - final PersistentClass pc = classes.get( entityName ); - if ( pc == null ) { - throw new MappingException( "persistent class not known: " + entityName ); - } - Property prop = pc.getReferencedProperty( propertyName ); - if ( prop == null ) { - throw new MappingException( - "property not known: " + - entityName + '.' + propertyName - ); - } - return prop.getType(); - } - }; - } - - private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - //we need reflectionManager before reading the other components (MetadataSourceQueue in particular) - final MetadataProvider metadataProvider = (MetadataProvider) ois.readObject(); - this.mapping = buildMapping(); - xmlHelper = new XMLHelper(); - createReflectionManager(metadataProvider); - ois.defaultReadObject(); - } - - private void writeObject(java.io.ObjectOutputStream out) throws IOException { - //We write MetadataProvider first as we need reflectionManager before reading the other components - final MetadataProvider metadataProvider = ( ( MetadataProviderInjector ) reflectionManager ).getMetadataProvider(); - out.writeObject( metadataProvider ); - out.defaultWriteObject(); - } - - private void createReflectionManager() { - createReflectionManager( new JPAMetadataProvider() ); - } - - private void createReflectionManager(MetadataProvider metadataProvider) { - reflectionManager = new JavaReflectionManager(); - ( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( metadataProvider ); - } - - public Map getFilterDefinitions() { - return filterDefinitions; - } - - public void addFilterDefinition(FilterDefinition definition) { - filterDefinitions.put( definition.getFilterName(), definition ); - } - - public Iterator iterateFetchProfiles() { - return fetchProfiles.values().iterator(); - } - - public void addFetchProfile(FetchProfile fetchProfile) { - fetchProfiles.put( fetchProfile.getName(), fetchProfile ); - } - - public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) { - auxiliaryDatabaseObjects.add( object ); - } - - public Map getSqlFunctions() { - return sqlFunctions; - } - - public void addSqlFunction(String functionName, SQLFunction function) { - // HHH-7721: SQLFunctionRegistry expects all lowercase. Enforce, - // just in case a user's customer dialect uses mixed cases. - sqlFunctions.put( functionName.toLowerCase(), function ); - } - - public TypeResolver getTypeResolver() { - return typeResolver; - } - - /** - * Allows registration of a type into the type registry. The phrase 'override' in the method name simply - * reminds that registration *potentially* replaces a previously registered type . - * - * @param type The type to register. - */ - public void registerTypeOverride(BasicType type) { - getTypeResolver().registerTypeOverride( type ); - } - - - public void registerTypeOverride(UserType type, String[] keys) { - getTypeResolver().registerTypeOverride( type, keys ); - } - - public void registerTypeOverride(CompositeUserType type, String[] keys) { - getTypeResolver().registerTypeOverride( type, keys ); - } - - public void registerTypeContributor(TypeContributor typeContributor) { - typeContributorRegistrations.add( typeContributor ); - } - - public SessionFactoryObserver getSessionFactoryObserver() { - return sessionFactoryObserver; - } - - public void setSessionFactoryObserver(SessionFactoryObserver sessionFactoryObserver) { - this.sessionFactoryObserver = sessionFactoryObserver; - } - - public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { - return currentTenantIdentifierResolver; - } - - public void setCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver currentTenantIdentifierResolver) { - this.currentTenantIdentifierResolver = currentTenantIdentifierResolver; - } - - /** - * Adds the AttributeConverter Class to this Configuration. - * - * @param attributeConverterClass The AttributeConverter class. - * @param autoApply Should the AttributeConverter be auto applied to property types as specified - * by its "entity attribute" parameterized type? - */ - public void addAttributeConverter(Class attributeConverterClass, boolean autoApply) { - final AttributeConverter attributeConverter; - try { - attributeConverter = attributeConverterClass.newInstance(); - } - catch (Exception e) { - throw new AnnotationException( - "Unable to instantiate AttributeConverter [" + attributeConverterClass.getName() + "]" - ); - } - addAttributeConverter( attributeConverter, autoApply ); - } - - /** - * Adds the AttributeConverter Class to this Configuration. - * - * @param attributeConverterClass The AttributeConverter class. - */ - public void addAttributeConverter(Class attributeConverterClass) { - final AttributeConverter attributeConverter; - try { - attributeConverter = attributeConverterClass.newInstance(); - } - catch (Exception e) { - throw new AnnotationException( - "Unable to instantiate AttributeConverter [" + attributeConverterClass.getName() + "]" - ); - } - - addAttributeConverter( attributeConverter ); - } - - /** - * Adds the AttributeConverter instance to this Configuration. This form is mainly intended for developers - * to programatically add their own AttributeConverter instance. HEM, instead, uses the - * {@link #addAttributeConverter(Class, boolean)} form - * - * @param attributeConverter The AttributeConverter instance. - */ - public void addAttributeConverter(AttributeConverter attributeConverter) { - boolean autoApply = false; - Converter converterAnnotation = attributeConverter.getClass().getAnnotation( Converter.class ); - if ( converterAnnotation != null ) { - autoApply = converterAnnotation.autoApply(); - } - - addAttributeConverter( new AttributeConverterDefinition( attributeConverter, autoApply ) ); - } - - /** - * Adds the AttributeConverter instance to this Configuration. This form is mainly intended for developers - * to programatically add their own AttributeConverter instance. HEM, instead, uses the - * {@link #addAttributeConverter(Class, boolean)} form - * - * @param attributeConverter The AttributeConverter instance. - * @param autoApply Should the AttributeConverter be auto applied to property types as specified - * by its "entity attribute" parameterized type? - */ - public void addAttributeConverter(AttributeConverter attributeConverter, boolean autoApply) { - addAttributeConverter( new AttributeConverterDefinition( attributeConverter, autoApply ) ); - } - - public void addAttributeConverter(AttributeConverterDefinition definition) { - if ( attributeConverterDefinitionsByClass == null ) { - attributeConverterDefinitionsByClass = new ConcurrentHashMap(); - } - - final Object old = attributeConverterDefinitionsByClass.put( definition.getAttributeConverter().getClass(), definition ); - - if ( old != null ) { - throw new AssertionFailure( - String.format( - "AttributeConverter class [%s] registered multiple times", - definition.getAttributeConverter().getClass() - ) - ); - } - } - - public java.util.Collection getNamedEntityGraphs() { - return namedEntityGraphMap == null - ? Collections.emptyList() - : namedEntityGraphMap.values(); - } - - - // Mappings impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - /** - * Internal implementation of the Mappings interface giving access to the Configuration's internal - * metadata repository state ({@link Configuration#classes}, {@link Configuration#tables}, etc). - */ - @SuppressWarnings( {"deprecation", "unchecked"}) - protected class MappingsImpl implements ExtendedMappings, Serializable { - - private String schemaName; - - public String getSchemaName() { - return schemaName; - } - - public void setSchemaName(String schemaName) { - this.schemaName = schemaName; - } - - - private String catalogName; - - public String getCatalogName() { - return catalogName; - } - - public void setCatalogName(String catalogName) { - this.catalogName = catalogName; - } - - - private String defaultPackage; - - public String getDefaultPackage() { - return defaultPackage; - } - - public void setDefaultPackage(String defaultPackage) { - this.defaultPackage = defaultPackage; - } - - - private boolean autoImport; - - public boolean isAutoImport() { - return autoImport; - } - - public void setAutoImport(boolean autoImport) { - this.autoImport = autoImport; - } - - - private boolean defaultLazy; - - public boolean isDefaultLazy() { - return defaultLazy; - } - - public void setDefaultLazy(boolean defaultLazy) { - this.defaultLazy = defaultLazy; - } - - - private String defaultCascade; - - public String getDefaultCascade() { - return defaultCascade; - } - - public void setDefaultCascade(String defaultCascade) { - this.defaultCascade = defaultCascade; - } - - - private String defaultAccess; - - public String getDefaultAccess() { - return defaultAccess; - } - - public void setDefaultAccess(String defaultAccess) { - this.defaultAccess = defaultAccess; - } - - - public NamingStrategy getNamingStrategy() { - return namingStrategy; - } - - public void setNamingStrategy(NamingStrategy namingStrategy) { - Configuration.this.namingStrategy = namingStrategy; - } - - public TypeResolver getTypeResolver() { - return typeResolver; - } - - public Iterator iterateClasses() { - return classes.values().iterator(); - } - - public PersistentClass getClass(String entityName) { - return classes.get( entityName ); - } - - public PersistentClass locatePersistentClassByEntityName(String entityName) { - PersistentClass persistentClass = classes.get( entityName ); - if ( persistentClass == null ) { - String actualEntityName = imports.get( entityName ); - if ( StringHelper.isNotEmpty( actualEntityName ) ) { - persistentClass = classes.get( actualEntityName ); - } - } - return persistentClass; - } - - public void addClass(PersistentClass persistentClass) throws DuplicateMappingException { - Object old = classes.put( persistentClass.getEntityName(), persistentClass ); - if ( old != null ) { - throw new DuplicateMappingException( "class/entity", persistentClass.getEntityName() ); - } - } - - public void addImport(String entityName, String rename) throws DuplicateMappingException { - String existing = imports.put( rename, entityName ); - if ( existing != null ) { - if (existing.equals(entityName)) LOG.duplicateImport(entityName, rename); - else throw new DuplicateMappingException("duplicate import: " + rename + " refers to both " + entityName + " and " - + existing + " (try using auto-import=\"false\")", "import", rename); - } - } - - public Collection getCollection(String role) { - return collections.get( role ); - } - - public Iterator iterateCollections() { - return collections.values().iterator(); - } - - public void addCollection(Collection collection) throws DuplicateMappingException { - Object old = collections.put( collection.getRole(), collection ); - if ( old != null ) { - throw new DuplicateMappingException( "collection role", collection.getRole() ); - } - } - - public Table getTable(String schema, String catalog, String name) { - String key = Table.qualify(catalog, schema, name); - return tables.get( key ); - } - - public Iterator

    iterateTables() { - return tables.values().iterator(); - } - - public Table addTable( - String schema, - String catalog, - String name, - String subselect, - boolean isAbstract) { - name = getObjectNameNormalizer().normalizeIdentifierQuoting( name ); - schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema ); - catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog ); - - String key = subselect == null ? Table.qualify( catalog, schema, name ) : subselect; - Table table = tables.get( key ); - - if ( table == null ) { - table = new Table(); - table.setAbstract( isAbstract ); - table.setName( name ); - table.setSchema( schema ); - table.setCatalog( catalog ); - table.setSubselect( subselect ); - tables.put( key, table ); - } - else { - if ( !isAbstract ) { - table.setAbstract( false ); - } - } - - return table; - } - - public Table addDenormalizedTable( - String schema, - String catalog, - String name, - boolean isAbstract, - String subselect, - Table includedTable) throws DuplicateMappingException { - name = getObjectNameNormalizer().normalizeIdentifierQuoting( name ); - schema = getObjectNameNormalizer().normalizeIdentifierQuoting( schema ); - catalog = getObjectNameNormalizer().normalizeIdentifierQuoting( catalog ); - - String key = subselect == null ? Table.qualify(catalog, schema, name) : subselect; - if ( tables.containsKey( key ) ) { - throw new DuplicateMappingException( "table", name ); - } - - Table table = new DenormalizedTable( includedTable ); - table.setAbstract( isAbstract ); - table.setName( name ); - table.setSchema( schema ); - table.setCatalog( catalog ); - table.setSubselect( subselect ); - - tables.put( key, table ); - return table; - } - - public NamedQueryDefinition getQuery(String name) { - return namedQueries.get( name ); - } - - public void addQuery(String name, NamedQueryDefinition query) throws DuplicateMappingException { - if ( !defaultNamedQueryNames.contains( name ) ) { - applyQuery( name, query ); - } - } - - private void applyQuery(String name, NamedQueryDefinition query) { - checkQueryName( name ); - namedQueries.put( name.intern(), query ); - } - - private void checkQueryName(String name) throws DuplicateMappingException { - if ( namedQueries.containsKey( name ) || namedSqlQueries.containsKey( name ) ) { - throw new DuplicateMappingException( "query", name ); - } - } - - public void addDefaultQuery(String name, NamedQueryDefinition query) { - applyQuery( name, query ); - defaultNamedQueryNames.add( name ); - } - - public NamedSQLQueryDefinition getSQLQuery(String name) { - return namedSqlQueries.get( name ); - } - - public void addSQLQuery(String name, NamedSQLQueryDefinition query) throws DuplicateMappingException { - if ( !defaultNamedNativeQueryNames.contains( name ) ) { - applySQLQuery( name, query ); - } - } - - private void applySQLQuery(String name, NamedSQLQueryDefinition query) throws DuplicateMappingException { - checkQueryName( name ); - namedSqlQueries.put( name.intern(), query ); - } - - @Override - public void addNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) - throws DuplicateMappingException { - final String name = definition.getRegisteredName(); - if ( !defaultNamedProcedure.contains( name ) ) { - final NamedProcedureCallDefinition previous = namedProcedureCallMap.put( name, definition ); - if ( previous != null ) { - throw new DuplicateMappingException( "named stored procedure query", name ); - } - } - } - @Override - public void addDefaultNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) - throws DuplicateMappingException { - addNamedProcedureCallDefinition( definition ); - defaultNamedProcedure.add( definition.getRegisteredName() ); - } - - @Override - public void addNamedEntityGraphDefintion(NamedEntityGraphDefinition definition) - throws DuplicateMappingException { - final String name = definition.getRegisteredName(); - - final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition ); - if ( previous != null ) { - throw new DuplicateMappingException( "NamedEntityGraph", name ); - } - } - - public void addDefaultSQLQuery(String name, NamedSQLQueryDefinition query) { - applySQLQuery( name, query ); - defaultNamedNativeQueryNames.add( name ); - } - - public ResultSetMappingDefinition getResultSetMapping(String name) { - return sqlResultSetMappings.get(name); - } - - public void addResultSetMapping(ResultSetMappingDefinition sqlResultSetMapping) throws DuplicateMappingException { - if ( !defaultSqlResultSetMappingNames.contains( sqlResultSetMapping.getName() ) ) { - applyResultSetMapping( sqlResultSetMapping ); - } - } - - public void applyResultSetMapping(ResultSetMappingDefinition sqlResultSetMapping) throws DuplicateMappingException { - Object old = sqlResultSetMappings.put( sqlResultSetMapping.getName(), sqlResultSetMapping ); - if ( old != null ) { - throw new DuplicateMappingException( "resultSet", sqlResultSetMapping.getName() ); - } - } - - public void addDefaultResultSetMapping(ResultSetMappingDefinition definition) { - final String name = definition.getName(); - if ( !defaultSqlResultSetMappingNames.contains( name ) && getResultSetMapping( name ) != null ) { - removeResultSetMapping( name ); - } - applyResultSetMapping( definition ); - defaultSqlResultSetMappingNames.add( name ); - } - - protected void removeResultSetMapping(String name) { - sqlResultSetMappings.remove( name ); - } - - public TypeDef getTypeDef(String typeName) { - return typeDefs.get( typeName ); - } - - public void addTypeDef(String typeName, String typeClass, Properties paramMap) { - TypeDef def = new TypeDef( typeClass, paramMap ); - typeDefs.put( typeName, def ); - LOG.debugf( "Added %s with class %s", typeName, typeClass ); - } - - public Map getFilterDefinitions() { - return filterDefinitions; - } - - public FilterDefinition getFilterDefinition(String name) { - return filterDefinitions.get( name ); - } - - public void addFilterDefinition(FilterDefinition definition) { - filterDefinitions.put( definition.getFilterName(), definition ); - } - - public FetchProfile findOrCreateFetchProfile(String name, MetadataSource source) { - FetchProfile profile = fetchProfiles.get( name ); - if ( profile == null ) { - profile = new FetchProfile( name, source ); - fetchProfiles.put( name, profile ); - } - return profile; - } - - public Iterator iterateAuxliaryDatabaseObjects() { - return iterateAuxiliaryDatabaseObjects(); - } - - public Iterator iterateAuxiliaryDatabaseObjects() { - return auxiliaryDatabaseObjects.iterator(); - } - - public ListIterator iterateAuxliaryDatabaseObjectsInReverse() { - return iterateAuxiliaryDatabaseObjectsInReverse(); - } - - public ListIterator iterateAuxiliaryDatabaseObjectsInReverse() { - return auxiliaryDatabaseObjects.listIterator( auxiliaryDatabaseObjects.size() ); - } - - public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) { - auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject ); - } - - /** - * Internal struct used to help track physical table names to logical table names. - */ - private class TableDescription implements Serializable { - final String logicalName; - final Table denormalizedSupertable; - - TableDescription(String logicalName, Table denormalizedSupertable) { - this.logicalName = logicalName; - this.denormalizedSupertable = denormalizedSupertable; - } - } - - public String getLogicalTableName(Table table) throws MappingException { - return getLogicalTableName( table.getQuotedSchema(), table.getQuotedCatalog(), table.getQuotedName() ); - } - - private String getLogicalTableName(String schema, String catalog, String physicalName) throws MappingException { - String key = buildTableNameKey( schema, catalog, physicalName ); - TableDescription descriptor = (TableDescription) tableNameBinding.get( key ); - if (descriptor == null) { - throw new MappingException( "Unable to find physical table: " + physicalName); - } - return descriptor.logicalName; - } - - public void addTableBinding( - String schema, - String catalog, - String logicalName, - String physicalName, - Table denormalizedSuperTable) throws DuplicateMappingException { - String key = buildTableNameKey( schema, catalog, physicalName ); - TableDescription tableDescription = new TableDescription( logicalName, denormalizedSuperTable ); - TableDescription oldDescriptor = ( TableDescription ) tableNameBinding.put( key, tableDescription ); - if ( oldDescriptor != null && ! oldDescriptor.logicalName.equals( logicalName ) ) { - //TODO possibly relax that - throw new DuplicateMappingException( - "Same physical table name [" + physicalName + "] references several logical table names: [" + - oldDescriptor.logicalName + "], [" + logicalName + ']', - "table", - physicalName - ); - } - } - - private String buildTableNameKey(String schema, String catalog, String finalName) { - StringBuilder keyBuilder = new StringBuilder(); - if (schema != null) keyBuilder.append( schema ); - keyBuilder.append( "."); - if (catalog != null) keyBuilder.append( catalog ); - keyBuilder.append( "."); - keyBuilder.append( finalName ); - return keyBuilder.toString(); - } - - /** - * Internal struct used to maintain xref between physical and logical column - * names for a table. Mainly this is used to ensure that the defined - * {@link NamingStrategy} is not creating duplicate column names. - */ - private class TableColumnNameBinding implements Serializable { - private final String tableName; - private Map/**/ logicalToPhysical = new HashMap(); - private Map/**/ physicalToLogical = new HashMap(); - - private TableColumnNameBinding(String tableName) { - this.tableName = tableName; - } - - public void addBinding(String logicalName, Column physicalColumn) { - bindLogicalToPhysical( logicalName, physicalColumn ); - bindPhysicalToLogical( logicalName, physicalColumn ); - } - - private void bindLogicalToPhysical(String logicalName, Column physicalColumn) throws DuplicateMappingException { - final String logicalKey = logicalName.toLowerCase(); - final String physicalName = physicalColumn.getQuotedName(); - final String existingPhysicalName = ( String ) logicalToPhysical.put( logicalKey, physicalName ); - if ( existingPhysicalName != null ) { - boolean areSamePhysicalColumn = physicalColumn.isQuoted() - ? existingPhysicalName.equals( physicalName ) - : existingPhysicalName.equalsIgnoreCase( physicalName ); - if ( ! areSamePhysicalColumn ) { - throw new DuplicateMappingException( - " Table [" + tableName + "] contains logical column name [" + logicalName - + "] referenced by multiple physical column names: [" + existingPhysicalName - + "], [" + physicalName + "]", - "column-binding", - tableName + "." + logicalName - ); - } - } - } - - private void bindPhysicalToLogical(String logicalName, Column physicalColumn) throws DuplicateMappingException { - final String physicalName = physicalColumn.getQuotedName(); - final String existingLogicalName = ( String ) physicalToLogical.put( physicalName, logicalName ); - if ( existingLogicalName != null && ! existingLogicalName.equals( logicalName ) ) { - throw new DuplicateMappingException( - " Table [" + tableName + "] contains physical column name [" + physicalName - + "] represented by different logical column names: [" + existingLogicalName - + "], [" + logicalName + "]", - "column-binding", - tableName + "." + physicalName - ); - } - } - } - - public void addColumnBinding(String logicalName, Column physicalColumn, Table table) throws DuplicateMappingException { - TableColumnNameBinding binding = ( TableColumnNameBinding ) columnNameBindingPerTable.get( table ); - if ( binding == null ) { - binding = new TableColumnNameBinding( table.getName() ); - columnNameBindingPerTable.put( table, binding ); - } - binding.addBinding( logicalName, physicalColumn ); - } - - public String getPhysicalColumnName(String logicalName, Table table) throws MappingException { - logicalName = logicalName.toLowerCase(); - String finalName = null; - Table currentTable = table; - do { - TableColumnNameBinding binding = ( TableColumnNameBinding ) columnNameBindingPerTable.get( currentTable ); - if ( binding != null ) { - finalName = ( String ) binding.logicalToPhysical.get( logicalName ); - } - String key = buildTableNameKey( - currentTable.getQuotedSchema(), currentTable.getQuotedCatalog(), currentTable.getQuotedName() - ); - TableDescription description = ( TableDescription ) tableNameBinding.get( key ); - if ( description != null ) { - currentTable = description.denormalizedSupertable; - } - else { - currentTable = null; - } - } while ( finalName == null && currentTable != null ); - - if ( finalName == null ) { - throw new MappingException( - "Unable to find column with logical name " + logicalName + " in table " + table.getName() - ); - } - return finalName; - } - @Override - public String getLogicalColumnName(String physicalName, Table table) throws MappingException { - String logical = null; - Table currentTable = table; - TableDescription description = null; - do { - TableColumnNameBinding binding = ( TableColumnNameBinding ) columnNameBindingPerTable.get( currentTable ); - if ( binding != null ) { - logical = ( String ) binding.physicalToLogical.get( physicalName ); - } - String key = buildTableNameKey( - currentTable.getQuotedSchema(), currentTable.getQuotedCatalog(), currentTable.getQuotedName() - ); - description = ( TableDescription ) tableNameBinding.get( key ); - if ( description != null ) { - currentTable = description.denormalizedSupertable; - } - else { - currentTable = null; - } - } - while ( logical == null && currentTable != null ); - if ( logical == null ) { - throw new MappingException( - "Unable to find logical column name from physical name " - + physicalName + " in table " + table.getName() - ); - } - return logical; - } - - public void addSecondPass(SecondPass sp) { - addSecondPass( sp, false ); - } - - public void addSecondPass(SecondPass sp, boolean onTopOfTheQueue) { - if ( onTopOfTheQueue ) { - secondPasses.add( 0, sp ); - } - else { - secondPasses.add( sp ); - } - } - - @Override - public AttributeConverterDefinition locateAttributeConverter(Class converterClass) { - if ( attributeConverterDefinitionsByClass == null ) { - return null; - } - return attributeConverterDefinitionsByClass.get( converterClass ); - } - - @Override - public java.util.Collection getAttributeConverters() { - if ( attributeConverterDefinitionsByClass == null ) { - return Collections.emptyList(); - } - return attributeConverterDefinitionsByClass.values(); - } - - public void addPropertyReference(String referencedClass, String propertyName) { - propertyReferences.add( new PropertyReference( referencedClass, propertyName, false ) ); - } - - public void addUniquePropertyReference(String referencedClass, String propertyName) { - propertyReferences.add( new PropertyReference( referencedClass, propertyName, true ) ); - } - - public void addToExtendsQueue(ExtendsQueueEntry entry) { - extendsQueue.put( entry, null ); - } - - public MutableIdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return identifierGeneratorFactory; - } - - public void addMappedSuperclass(Class type, MappedSuperclass mappedSuperclass) { - mappedSuperClasses.put( type, mappedSuperclass ); - } - - public MappedSuperclass getMappedSuperclass(Class type) { - return mappedSuperClasses.get( type ); - } - - public ObjectNameNormalizer getObjectNameNormalizer() { - return normalizer; - } - - public Properties getConfigurationProperties() { - return properties; - } - - public void addDefaultGenerator(IdGenerator generator) { - this.addGenerator( generator ); - defaultNamedGenerators.add( generator.getName() ); - } - - public boolean isInSecondPass() { - return inSecondPass; - } - - public PropertyData getPropertyAnnotatedWithMapsId(XClass entityType, String propertyName) { - final Map map = propertiesAnnotatedWithMapsId.get( entityType ); - return map == null ? null : map.get( propertyName ); - } - - public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property) { - Map map = propertiesAnnotatedWithMapsId.get( entityType ); - if ( map == null ) { - map = new HashMap(); - propertiesAnnotatedWithMapsId.put( entityType, map ); - } - map.put( property.getProperty().getAnnotation( MapsId.class ).value(), property ); - } - - public boolean isSpecjProprietarySyntaxEnabled() { - return specjProprietarySyntaxEnabled; - } - - public void addPropertyAnnotatedWithMapsIdSpecj(XClass entityType, PropertyData property, String mapsIdValue) { - Map map = propertiesAnnotatedWithMapsId.get( entityType ); - if ( map == null ) { - map = new HashMap(); - propertiesAnnotatedWithMapsId.put( entityType, map ); - } - map.put( mapsIdValue, property ); - } - - public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName) { - final Map map = propertiesAnnotatedWithIdAndToOne.get( entityType ); - return map == null ? null : map.get( propertyName ); - } - - public void addToOneAndIdProperty(XClass entityType, PropertyData property) { - Map map = propertiesAnnotatedWithIdAndToOne.get( entityType ); - if ( map == null ) { - map = new HashMap(); - propertiesAnnotatedWithIdAndToOne.put( entityType, map ); - } - map.put( property.getPropertyName(), property ); - } - - private Boolean useNewGeneratorMappings; - - @Override - public boolean useNewGeneratorMappings() { - if ( useNewGeneratorMappings == null ) { - final String booleanName = getConfigurationProperties() - .getProperty( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS ); - useNewGeneratorMappings = Boolean.valueOf( booleanName ); - } - return useNewGeneratorMappings; - } - - - private Boolean implicitDiscriminatorColumnForJoinedInheritance; - - @Override - public boolean useImplicitDiscriminatorColumnForJoinedInheritance() { - if ( implicitDiscriminatorColumnForJoinedInheritance == null ) { - final String booleanName = getConfigurationProperties() - .getProperty( AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS ); - implicitDiscriminatorColumnForJoinedInheritance = Boolean.valueOf( booleanName ); - } - return implicitDiscriminatorColumnForJoinedInheritance; - } - - - private Boolean ignoreExplicitDiscriminatorColumnForJoinedInheritance; - - @Override - public boolean ignoreExplicitDiscriminatorColumnForJoinedInheritance() { - if ( ignoreExplicitDiscriminatorColumnForJoinedInheritance == null ) { - final String booleanName = getConfigurationProperties() - .getProperty( AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS ); - ignoreExplicitDiscriminatorColumnForJoinedInheritance = Boolean.valueOf( booleanName ); - } - return ignoreExplicitDiscriminatorColumnForJoinedInheritance; - } - - - private Boolean useNationalizedCharacterData; - - @Override - public boolean useNationalizedCharacterData() { - if ( useNationalizedCharacterData == null ) { - final String booleanName = getConfigurationProperties() - .getProperty( AvailableSettings.USE_NATIONALIZED_CHARACTER_DATA ); - useNationalizedCharacterData = Boolean.valueOf( booleanName ); - } - return useNationalizedCharacterData; - } - - private Boolean forceDiscriminatorInSelectsByDefault; - - @Override - public boolean forceDiscriminatorInSelectsByDefault() { - if ( forceDiscriminatorInSelectsByDefault == null ) { - final String booleanName = getConfigurationProperties() - .getProperty( AvailableSettings.FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT ); - forceDiscriminatorInSelectsByDefault = Boolean.valueOf( booleanName ); - } - return forceDiscriminatorInSelectsByDefault; - } - - public IdGenerator getGenerator(String name) { - return getGenerator( name, null ); - } - - public IdGenerator getGenerator(String name, Map localGenerators) { - if ( localGenerators != null ) { - IdGenerator result = localGenerators.get( name ); - if ( result != null ) { - return result; - } - } - return namedGenerators.get( name ); - } - - public void addGenerator(IdGenerator generator) { - if ( !defaultNamedGenerators.contains( generator.getName() ) ) { - IdGenerator old = namedGenerators.put( generator.getName(), generator ); - if ( old != null ) { - LOG.duplicateGeneratorName( old.getName() ); - } - } - } - - public void addGeneratorTable(String name, Properties params) { - Object old = generatorTables.put( name, params ); - if ( old != null ) { - LOG.duplicateGeneratorTable( name ); - } - } - - public Properties getGeneratorTableProperties(String name, Map localGeneratorTables) { - if ( localGeneratorTables != null ) { - Properties result = localGeneratorTables.get( name ); - if ( result != null ) { - return result; - } - } - return generatorTables.get( name ); - } - - public Map getJoins(String entityName) { - return joins.get( entityName ); - } - - public void addJoins(PersistentClass persistentClass, Map joins) { - Object old = Configuration.this.joins.put( persistentClass.getEntityName(), joins ); - if ( old != null ) { - LOG.duplicateJoins( persistentClass.getEntityName() ); - } - } - - public AnnotatedClassType getClassType(XClass clazz) { - AnnotatedClassType type = classTypes.get( clazz.getName() ); - if ( type == null ) { - return addClassType( clazz ); - } - else { - return type; - } - } - - //FIXME should be private but is part of the ExtendedMapping contract - - public AnnotatedClassType addClassType(XClass clazz) { - AnnotatedClassType type; - if ( clazz.isAnnotationPresent( Entity.class ) ) { - type = AnnotatedClassType.ENTITY; - } - else if ( clazz.isAnnotationPresent( Embeddable.class ) ) { - type = AnnotatedClassType.EMBEDDABLE; - } - else if ( clazz.isAnnotationPresent( javax.persistence.MappedSuperclass.class ) ) { - type = AnnotatedClassType.EMBEDDABLE_SUPERCLASS; - } - else { - type = AnnotatedClassType.NONE; - } - classTypes.put( clazz.getName(), type ); - return type; - } - - /** - * {@inheritDoc} - */ - public Map> getTableUniqueConstraints() { - final Map> deprecatedStructure = new HashMap>( - CollectionHelper.determineProperSizing( getUniqueConstraintHoldersByTable() ), - CollectionHelper.LOAD_FACTOR - ); - for ( Map.Entry> entry : getUniqueConstraintHoldersByTable().entrySet() ) { - List columnsPerConstraint = new ArrayList( - CollectionHelper.determineProperSizing( entry.getValue().size() ) - ); - deprecatedStructure.put( entry.getKey(), columnsPerConstraint ); - for ( UniqueConstraintHolder holder : entry.getValue() ) { - columnsPerConstraint.add( holder.getColumns() ); - } - } - return deprecatedStructure; - } - - public Map> getUniqueConstraintHoldersByTable() { - return uniqueConstraintHoldersByTable; - } - - @SuppressWarnings({ "unchecked" }) - public void addUniqueConstraints(Table table, List uniqueConstraints) { - List constraintHolders = new ArrayList( - CollectionHelper.determineProperSizing( uniqueConstraints.size() ) - ); - - int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders( table ); - for ( String[] columns : ( List ) uniqueConstraints ) { - final String keyName = "key" + keyNameBase++; - constraintHolders.add( - new UniqueConstraintHolder().setName( keyName ).setColumns( columns ) - ); - } - addUniqueConstraintHolders( table, constraintHolders ); - } - - private int determineCurrentNumberOfUniqueConstraintHolders(Table table) { - List currentHolders = getUniqueConstraintHoldersByTable().get( table ); - return currentHolders == null - ? 0 - : currentHolders.size(); - } - - public void addUniqueConstraintHolders(Table table, List uniqueConstraintHolders) { - List holderList = getUniqueConstraintHoldersByTable().get( table ); - if ( holderList == null ) { - holderList = new ArrayList(); - getUniqueConstraintHoldersByTable().put( table, holderList ); - } - holderList.addAll( uniqueConstraintHolders ); - } - - public void addJpaIndexHolders(Table table, List holders) { - List holderList = jpaIndexHoldersByTable.get( table ); - if ( holderList == null ) { - holderList = new ArrayList(); - jpaIndexHoldersByTable.put( table, holderList ); - } - holderList.addAll( holders ); - } - - public void addMappedBy(String entityName, String propertyName, String inversePropertyName) { - mappedByResolver.put( entityName + "." + propertyName, inversePropertyName ); - } - - public String getFromMappedBy(String entityName, String propertyName) { - return mappedByResolver.get( entityName + "." + propertyName ); - } - - public void addPropertyReferencedAssociation(String entityName, String propertyName, String propertyRef) { - propertyRefResolver.put( entityName + "." + propertyName, propertyRef ); - } - - public String getPropertyReferencedAssociation(String entityName, String propertyName) { - return propertyRefResolver.get( entityName + "." + propertyName ); - } - - public ReflectionManager getReflectionManager() { - return reflectionManager; - } - - public Map getClasses() { - return classes; - } - - public void addAnyMetaDef(AnyMetaDef defAnn) throws AnnotationException { - if ( anyMetaDefs.containsKey( defAnn.name() ) ) { - throw new AnnotationException( "Two @AnyMetaDef with the same name defined: " + defAnn.name() ); - } - anyMetaDefs.put( defAnn.name(), defAnn ); - } - - public AnyMetaDef getAnyMetaDef(String name) { - return anyMetaDefs.get( name ); - } - } - - final ObjectNameNormalizer normalizer = new ObjectNameNormalizerImpl(); - - final class ObjectNameNormalizerImpl extends ObjectNameNormalizer implements Serializable { - public boolean isUseQuotedIdentifiersGlobally() { - //Do not cache this value as we lazily set it in Hibernate Annotation (AnnotationConfiguration) - //TODO use a dedicated protected useQuotedIdentifier flag in Configuration (overriden by AnnotationConfiguration) - String setting = (String) properties.get( Environment.GLOBALLY_QUOTED_IDENTIFIERS ); - return setting != null && Boolean.valueOf( setting ); - } - - public NamingStrategy getNamingStrategy() { - return namingStrategy; - } - } - - protected class MetadataSourceQueue implements Serializable { - private LinkedHashMap> hbmMetadataToEntityNamesMap - = new LinkedHashMap>(); - private Map hbmMetadataByEntityNameXRef = new HashMap(); - - //XClass are not serializable by default - private transient List annotatedClasses = new ArrayList(); - //only used during the secondPhaseCompile pass, hence does not need to be serialized - private transient Map annotatedClassesByEntityNameMap = new HashMap(); - - private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - ois.defaultReadObject(); - annotatedClassesByEntityNameMap = new HashMap(); - - //build back annotatedClasses - @SuppressWarnings( "unchecked" ) - List serializableAnnotatedClasses = (List) ois.readObject(); - annotatedClasses = new ArrayList( serializableAnnotatedClasses.size() ); - for ( Class clazz : serializableAnnotatedClasses ) { - annotatedClasses.add( reflectionManager.toXClass( clazz ) ); - } - } - - private void writeObject(java.io.ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - List serializableAnnotatedClasses = new ArrayList( annotatedClasses.size() ); - for ( XClass xClass : annotatedClasses ) { - serializableAnnotatedClasses.add( reflectionManager.toClass( xClass ) ); - } - out.writeObject( serializableAnnotatedClasses ); - } - - public void add(XmlDocument metadataXml) { - final Document document = metadataXml.getDocumentTree(); - final Element hmNode = document.getRootElement(); - Attribute packNode = hmNode.attribute( "package" ); - String defaultPackage = packNode != null ? packNode.getValue() : ""; - Set entityNames = new HashSet(); - findClassNames( defaultPackage, hmNode, entityNames ); - for ( String entity : entityNames ) { - hbmMetadataByEntityNameXRef.put( entity, metadataXml ); - } - this.hbmMetadataToEntityNamesMap.put( metadataXml, entityNames ); - } - - private void findClassNames(String defaultPackage, Element startNode, Set names) { - // if we have some extends we need to check if those classes possibly could be inside the - // same hbm.xml file... - Iterator[] classes = new Iterator[4]; - classes[0] = startNode.elementIterator( "class" ); - classes[1] = startNode.elementIterator( "subclass" ); - classes[2] = startNode.elementIterator( "joined-subclass" ); - classes[3] = startNode.elementIterator( "union-subclass" ); - - Iterator classIterator = new JoinedIterator( classes ); - while ( classIterator.hasNext() ) { - Element element = ( Element ) classIterator.next(); - String entityName = element.attributeValue( "entity-name" ); - if ( entityName == null ) { - entityName = getClassName( element.attribute( "name" ), defaultPackage ); - } - names.add( entityName ); - findClassNames( defaultPackage, element, names ); - } - } - - private String getClassName(Attribute name, String defaultPackage) { - if ( name == null ) { - return null; - } - String unqualifiedName = name.getValue(); - if ( unqualifiedName == null ) { - return null; - } - if ( unqualifiedName.indexOf( '.' ) < 0 && defaultPackage != null ) { - return defaultPackage + '.' + unqualifiedName; - } - return unqualifiedName; - } - - public void add(XClass annotatedClass) { - annotatedClasses.add( annotatedClass ); - } - - protected void syncAnnotatedClasses() { - final Iterator itr = annotatedClasses.iterator(); - while ( itr.hasNext() ) { - final XClass annotatedClass = itr.next(); - if ( annotatedClass.isAnnotationPresent( Entity.class ) ) { - annotatedClassesByEntityNameMap.put( annotatedClass.getName(), annotatedClass ); - continue; - } - - if ( !annotatedClass.isAnnotationPresent( javax.persistence.MappedSuperclass.class ) ) { - itr.remove(); - } - } - } - - protected void processMetadata(List order) { - syncAnnotatedClasses(); - - for ( MetadataSourceType type : order ) { - if ( MetadataSourceType.HBM.equals( type ) ) { - processHbmXmlQueue(); - } - else if ( MetadataSourceType.CLASS.equals( type ) ) { - processAnnotatedClassesQueue(); - } - } - } - - private void processHbmXmlQueue() { - LOG.debug( "Processing hbm.xml files" ); - for ( Map.Entry> entry : hbmMetadataToEntityNamesMap.entrySet() ) { - // Unfortunately we have to create a Mappings instance for each iteration here - processHbmXml( entry.getKey(), entry.getValue() ); - } - hbmMetadataToEntityNamesMap.clear(); - hbmMetadataByEntityNameXRef.clear(); - } - - private void processHbmXml(XmlDocument metadataXml, Set entityNames) { - try { - HbmBinder.bindRoot( metadataXml, createMappings(), Collections.EMPTY_MAP, entityNames ); - } - catch ( MappingException me ) { - throw new InvalidMappingException( - metadataXml.getOrigin().getType(), - metadataXml.getOrigin().getName(), - me - ); - } - - for ( String entityName : entityNames ) { - if ( annotatedClassesByEntityNameMap.containsKey( entityName ) ) { - annotatedClasses.remove( annotatedClassesByEntityNameMap.get( entityName ) ); - annotatedClassesByEntityNameMap.remove( entityName ); - } - } - } - - private void processAnnotatedClassesQueue() { - LOG.debug( "Process annotated classes" ); - //bind classes in the correct order calculating some inheritance state - List orderedClasses = orderAndFillHierarchy( annotatedClasses ); - Mappings mappings = createMappings(); - Map inheritanceStatePerClass = AnnotationBinder.buildInheritanceStates( - orderedClasses, mappings - ); - - - for ( XClass clazz : orderedClasses ) { - AnnotationBinder.bindClass( clazz, inheritanceStatePerClass, mappings ); - - final String entityName = clazz.getName(); - if ( hbmMetadataByEntityNameXRef.containsKey( entityName ) ) { - hbmMetadataToEntityNamesMap.remove( hbmMetadataByEntityNameXRef.get( entityName ) ); - hbmMetadataByEntityNameXRef.remove( entityName ); - } - } - annotatedClasses.clear(); - annotatedClassesByEntityNameMap.clear(); - } - - private List orderAndFillHierarchy(List original) { - List copy = new ArrayList( original ); - insertMappedSuperclasses( original, copy ); - - // order the hierarchy - List workingCopy = new ArrayList( copy ); - List newList = new ArrayList( copy.size() ); - while ( workingCopy.size() > 0 ) { - XClass clazz = workingCopy.get( 0 ); - orderHierarchy( workingCopy, newList, copy, clazz ); - } - return newList; - } - - private void insertMappedSuperclasses(List original, List copy) { - for ( XClass clazz : original ) { - XClass superClass = clazz.getSuperclass(); - while ( superClass != null - && !reflectionManager.equals( superClass, Object.class ) - && !copy.contains( superClass ) ) { - if ( superClass.isAnnotationPresent( Entity.class ) - || superClass.isAnnotationPresent( javax.persistence.MappedSuperclass.class ) ) { - copy.add( superClass ); - } - superClass = superClass.getSuperclass(); - } - } - } - - private void orderHierarchy(List copy, List newList, List original, XClass clazz) { - if ( clazz == null || reflectionManager.equals( clazz, Object.class ) ) { - return; - } - //process superclass first - orderHierarchy( copy, newList, original, clazz.getSuperclass() ); - if ( original.contains( clazz ) ) { - if ( !newList.contains( clazz ) ) { - newList.add( clazz ); - } - copy.remove( clazz ); - } - } - - public boolean isEmpty() { - return hbmMetadataToEntityNamesMap.isEmpty() && annotatedClasses.isEmpty(); - } - - } - - - public static final MetadataSourceType[] DEFAULT_ARTEFACT_PROCESSING_ORDER = new MetadataSourceType[] { - MetadataSourceType.HBM, - MetadataSourceType.CLASS - }; - - private List metadataSourcePrecedence; - - private List determineMetadataSourcePrecedence() { - if ( metadataSourcePrecedence.isEmpty() - && StringHelper.isNotEmpty( getProperties().getProperty( ARTEFACT_PROCESSING_ORDER ) ) ) { - metadataSourcePrecedence = parsePrecedence( getProperties().getProperty( ARTEFACT_PROCESSING_ORDER ) ); - } - if ( metadataSourcePrecedence.isEmpty() ) { - metadataSourcePrecedence = Arrays.asList( DEFAULT_ARTEFACT_PROCESSING_ORDER ); - } - metadataSourcePrecedence = Collections.unmodifiableList( metadataSourcePrecedence ); - - return metadataSourcePrecedence; - } - - public void setPrecedence(String precedence) { - this.metadataSourcePrecedence = parsePrecedence( precedence ); - } - - private List parsePrecedence(String s) { - if ( StringHelper.isEmpty( s ) ) { - return Collections.emptyList(); - } - StringTokenizer precedences = new StringTokenizer( s, ",; ", false ); - List tmpPrecedences = new ArrayList(); - while ( precedences.hasMoreElements() ) { - tmpPrecedences.add( MetadataSourceType.parsePrecedence( ( String ) precedences.nextElement() ) ); - } - return tmpPrecedences; - } - - private static class CacheHolder { - public CacheHolder(String role, String usage, String region, boolean isClass, boolean cacheLazy) { - this.role = role; - this.usage = usage; - this.region = region; - this.isClass = isClass; - this.cacheLazy = cacheLazy; - } - - public String role; - public String usage; - public String region; - public boolean isClass; - public boolean cacheLazy; + @Deprecated + public void buildMappings() { } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java index a3922b0c560c..3211fc437234 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/DefaultNamingStrategy.java @@ -24,9 +24,12 @@ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.binder.HashedNameUtil; /** * The default NamingStrategy @@ -93,6 +96,22 @@ public String foreignKeyColumnName( if (header == null) throw new AssertionFailure("NammingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } /** * Return the column name or the unqualified property name diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java index 25d1c2bce25c..17a70d2a62e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/EJB3NamingStrategy.java @@ -23,9 +23,12 @@ */ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.binder.HashedNameUtil; /** * Naming strategy implementing the EJB3 standards @@ -76,6 +79,22 @@ public String foreignKeyColumnName( if ( header == null ) throw new AssertionFailure( "NamingStrategy not properly filled" ); return columnName( header + "_" + referencedColumnName ); } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } public String logicalColumnName(String columnName, String propertyName) { return StringHelper.isNotEmpty( columnName ) ? columnName : StringHelper.unqualify( propertyName ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java index a70e1ccaa114..6bc72c6bad75 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3Column.java @@ -30,7 +30,6 @@ import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.ColumnTransformer; import org.hibernate.annotations.ColumnTransformers; -import org.hibernate.annotations.Index; import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.cfg.annotations.Nullability; import org.hibernate.internal.CoreMessageLogger; @@ -40,7 +39,6 @@ import org.hibernate.mapping.Join; import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.Table; - import org.jboss.logging.Logger; /** @@ -647,12 +645,6 @@ public static void checkPropertyConsistency(Ejb3Column[] columns, String propert } - public void addIndex(Index index, boolean inSecondPass) { - if ( index == null ) return; - String indexName = index.name(); - addIndex( indexName, inSecondPass ); - } - void addIndex(String indexName, boolean inSecondPass) { IndexOrUniqueKeySecondPass secondPass = new IndexOrUniqueKeySecondPass( indexName, this, mappings, false ); if ( inSecondPass ) { diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java index dff27ebe2f88..d7f786e9ffa1 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java @@ -514,6 +514,10 @@ public void linkValueUsingAColumnCopy(Column column, SimpleValue value) { @Override protected void addColumnBinding(SimpleValue value) { if ( StringHelper.isEmpty( mappedBy ) ) { + // was the column explicitly quoted in the mapping/annotation + // TODO: in metamodel, we need to better split global quoting and explicit quoting w/ respect to logical names + boolean isLogicalColumnQuoted = StringHelper.isQuoted( getLogicalColumnName() ); + final ObjectNameNormalizer nameNormalizer = getMappings().getObjectNameNormalizer(); final String logicalColumnName = nameNormalizer.normalizeIdentifierQuoting( getLogicalColumnName() ); final String referencedColumn = nameNormalizer.normalizeIdentifierQuoting( getReferencedColumn() ); @@ -521,7 +525,8 @@ protected void addColumnBinding(SimpleValue value) { final String unquotedRefColumn = StringHelper.unquote( referencedColumn ); String logicalCollectionColumnName = getMappings().getNamingStrategy() .logicalCollectionColumnName( unquotedLogColName, getPropertyName(), unquotedRefColumn ); - if ( StringHelper.isQuoted( logicalColumnName ) || StringHelper.isQuoted( referencedColumn ) ) { + + if ( isLogicalColumnQuoted ) { logicalCollectionColumnName = StringHelper.quote( logicalCollectionColumnName ); } getMappings().addColumnBinding( logicalCollectionColumnName, getMappingColumn(), value.getTable() ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java index 949459ae0333..74c0ba5301fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/HbmBinder.java @@ -1724,8 +1724,8 @@ public static void bindOneToOne(Element node, OneToOne oneToOne, String path, bo oneToOne.setConstrained( constrained ); oneToOne.setForeignKeyType( constrained ? - ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ); + ForeignKeyDirection.FROM_PARENT : + ForeignKeyDirection.TO_PARENT ); initOuterJoinFetchSetting( node, oneToOne ); initLaziness( node, oneToOne, mappings, true ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java index b9be3483c7c5..ece37f603395 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ImprovedNamingStrategy.java @@ -24,9 +24,12 @@ package org.hibernate.cfg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.binder.HashedNameUtil; /** * An improved naming strategy that prefers embedded @@ -106,6 +109,22 @@ public String foreignKeyColumnName( if (header == null) throw new AssertionFailure("NamingStrategy not properly filled"); return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility } + + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames) { + List combinedColumnNames = new ArrayList(); + combinedColumnNames.addAll( sourceColumnNames ); + combinedColumnNames.addAll( targetColumnNames ); + return HashedNameUtil.generateName( "FK_", sourceTableName + "_" + targetTableName, combinedColumnNames ); + } + + public String uniqueKeyName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "UK_", tableName, columnNames ); + } + + public String indexName(String tableName, List columnNames) { + return HashedNameUtil.generateName( "IDX_", tableName, columnNames ); + } /** * Return the column name or the unqualified property name diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/IndexColumn.java b/hibernate-core/src/main/java/org/hibernate/cfg/IndexColumn.java index aaf82c375e92..a0fc14dc79ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/IndexColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/IndexColumn.java @@ -23,6 +23,7 @@ */ package org.hibernate.cfg; import java.util.Map; + import javax.persistence.OrderColumn; import org.hibernate.mapping.Join; @@ -119,39 +120,4 @@ public static IndexColumn buildColumnFromAnnotation( } return column; } - - /** - * Legacy {@link IndexColumn @IndexColumn} processing. - * - * @param ann The IndexColumn annotation instance - * @param propertyHolder Information about the property - * @param inferredData Yeah, right. Uh... - * @param mappings The mappings being built. - * - * @return The index column - */ - public static IndexColumn buildColumnFromAnnotation( - org.hibernate.annotations.IndexColumn ann, - PropertyHolder propertyHolder, - PropertyData inferredData, - Mappings mappings) { - final IndexColumn column; - if ( ann != null ) { - final String sqlType = BinderHelper.isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition(); - final String name = BinderHelper.isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() : ann.name(); - //TODO move it to a getter based system and remove the constructor - column = new IndexColumn( - false, sqlType, 0, 0, 0, name, ann.nullable(), - false, true, true, null, null, propertyHolder, mappings - ); - column.setBase( ann.base() ); - } - else { - column = new IndexColumn( - true, null, 0, 0, 0, null, true, - false, true, true, null, null, propertyHolder, mappings - ); - } - return column; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java index c78e0f2f031a..e4be023d9b4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/NamingStrategy.java @@ -23,6 +23,8 @@ */ package org.hibernate.cfg; +import java.util.List; + /** * A set of rules for determining the physical column @@ -37,6 +39,7 @@ * @see ImprovedNamingStrategy * @author Gavin King * @author Emmanuel Bernard + * @author Brett Meyer */ public interface NamingStrategy { /** @@ -93,6 +96,33 @@ public String collectionTableName( public String foreignKeyColumnName( String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName ); + /** + * Return a constraint name for foreign keys that are not explicitly named in the mappings/annotations. + * + * @param tableName The foreign key's source table + * @param columnNames The source columns within the foreign key + * @param tableName The foreign key's target table + * @param columnNames The target columns within the foreign key + * @return The generated foreign key constraint name + */ + public String foreignKeyName(String sourceTableName, List sourceColumnNames, + String targetTableName, List targetColumnNames); + /** + * Return a constraint name for unique keys that are not explicitly named in the mappings/annotations. + * + * @param tableName The unique key's table + * @param columnNames The columns within the unique key + * @return The generated unique key constraint name + */ + public String uniqueKeyName(String tableName, List columnNames); + /** + * Return a constraint name for indexes that are not explicitly named in the mappings/annotations. + * + * @param tableName The index's table + * @param columnNames The columns within the index + * @return The generated index constraint name + */ + public String indexName(String tableName, List columnNames); /** * Return the logical column name used to refer to a column in the metadata * (like index, unique constraints etc) diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java b/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java index d374505df2e2..ffe4cd18fb54 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ObjectNameNormalizer.java @@ -56,6 +56,10 @@ public static interface NamingStrategyHelper { public String handleExplicitName(NamingStrategy strategy, String name); } + public static interface LogicalNamingStrategyHelper extends NamingStrategyHelper{ + public String getLogicalName(NamingStrategy strategy); + } + /** * Performs the actual contract of normalizing a database name. * @@ -78,7 +82,6 @@ public String normalizeDatabaseIdentifier(final String explicitName, NamingStrat // handle any quoting for consistent handling in naming strategies objectName = normalizeIdentifierQuoting( explicitName ); objectName = helper.handleExplicitName( getNamingStrategy(), objectName ); - return normalizeIdentifierQuoting( objectName ); } // Conceivable that the naming strategy could return a quoted identifier, or // that user enabled @@ -108,6 +111,12 @@ public String normalizeIdentifierQuoting(String identifier) { return '`' + identifier.substring( 1, identifier.length() - 1 ) + '`'; } + // Convert SQLServer style quoting + // TODO: This really should be tied to Dialect#openQuote/closeQuote + if ( identifier.startsWith( "[" ) && identifier.endsWith( "]" ) ) { + return '`' + identifier.substring( 1, identifier.length() - 1 ) + '`'; + } + // If the user has requested "global" use of quoted identifiers, quote this identifier (using back ticks) // if not already if ( isUseQuotedIdentifiersGlobally() && ! ( identifier.startsWith( "`" ) && identifier.endsWith( "`" ) ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java index cf2a410d09f9..eb54f4d922d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java @@ -28,7 +28,6 @@ import org.hibernate.AnnotationException; import org.hibernate.MappingException; -import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.cfg.annotations.PropertyBinder; import org.hibernate.internal.util.StringHelper; @@ -106,8 +105,8 @@ public void doSecondPass(Map persistentClasses) throws MappingException { if ( !optional ) value.setConstrained( true ); value.setForeignKeyType( value.isConstrained() ? - ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT + ForeignKeyDirection.FROM_PARENT : + ForeignKeyDirection.TO_PARENT ); PropertyBinder binder = new PropertyBinder(); binder.setName( propertyName ); @@ -255,9 +254,6 @@ else if ( otherSideProperty.getValue() instanceof ManyToOne ) { ); } } - ForeignKey fk = inferredData.getProperty().getAnnotation( ForeignKey.class ); - String fkName = fk != null ? fk.name() : ""; - if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) value.setForeignKeyName( fkName ); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java b/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java index 66f39593187a..8e8a7027646b 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; + import javax.persistence.Access; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; @@ -39,7 +40,6 @@ import javax.persistence.Transient; import org.hibernate.AnnotationException; -import org.hibernate.MappingException; import org.hibernate.annotations.ManyToAny; import org.hibernate.annotations.Target; import org.hibernate.annotations.Type; @@ -47,7 +47,6 @@ import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; - import org.jboss.logging.Logger; /** @@ -207,35 +206,13 @@ private TreeMap initProperties(AccessType access) { } private AccessType determineClassDefinedAccessStrategy() { - AccessType classDefinedAccessType; - - AccessType hibernateDefinedAccessType = AccessType.DEFAULT; - AccessType jpaDefinedAccessType = AccessType.DEFAULT; - - org.hibernate.annotations.AccessType accessType = xClass.getAnnotation( org.hibernate.annotations.AccessType.class ); - if ( accessType != null ) { - hibernateDefinedAccessType = AccessType.getAccessStrategy( accessType.value() ); - } + AccessType classDefinedAccessType = null; Access access = xClass.getAnnotation( Access.class ); if ( access != null ) { - jpaDefinedAccessType = AccessType.getAccessStrategy( access.value() ); - } - - if ( hibernateDefinedAccessType != AccessType.DEFAULT - && jpaDefinedAccessType != AccessType.DEFAULT - && hibernateDefinedAccessType != jpaDefinedAccessType ) { - throw new MappingException( - "@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. " - ); - } - - if ( hibernateDefinedAccessType != AccessType.DEFAULT ) { - classDefinedAccessType = hibernateDefinedAccessType; - } - else { - classDefinedAccessType = jpaDefinedAccessType; + classDefinedAccessType = AccessType.getAccessStrategy( access.value() ); } + return classDefinedAccessType; } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/PropertyInferredData.java b/hibernate-core/src/main/java/org/hibernate/cfg/PropertyInferredData.java index b74a2dc3d928..63f151936dbb 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/PropertyInferredData.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/PropertyInferredData.java @@ -66,35 +66,14 @@ public PropertyInferredData(XClass declaringClass, XProperty property, String pr public AccessType getDefaultAccess() throws MappingException { AccessType accessType = defaultAccess; - AccessType hibernateAccessType = AccessType.DEFAULT; AccessType jpaAccessType = AccessType.DEFAULT; - org.hibernate.annotations.AccessType accessTypeAnnotation = property.getAnnotation( org.hibernate.annotations.AccessType.class ); - if ( accessTypeAnnotation != null ) { - hibernateAccessType = AccessType.getAccessStrategy( accessTypeAnnotation.value() ); - } - Access access = property.getAnnotation( Access.class ); if ( access != null ) { jpaAccessType = AccessType.getAccessStrategy( access.value() ); } - if ( hibernateAccessType != AccessType.DEFAULT - && jpaAccessType != AccessType.DEFAULT - && hibernateAccessType != jpaAccessType ) { - - StringBuilder builder = new StringBuilder(); - builder.append( property.toString() ); - builder.append( - " defines @AccessType and @Access with contradicting values. Use of @Access only is recommended." - ); - throw new MappingException( builder.toString() ); - } - - if ( hibernateAccessType != AccessType.DEFAULT ) { - accessType = hibernateAccessType; - } - else if ( jpaAccessType != AccessType.DEFAULT ) { + if ( jpaAccessType != AccessType.DEFAULT ) { accessType = jpaAccessType; } return accessType; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java b/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java index e02a9db459c0..6312b58da016 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java @@ -42,7 +42,7 @@ import org.hibernate.cache.spi.RegionFactory; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.engine.transaction.spi.TransactionFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java index 617d2c989be9..2b0b4fd19c54 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java @@ -23,11 +23,15 @@ */ package org.hibernate.cfg.annotations; +import static org.hibernate.cfg.BinderHelper.toAliasEntityMap; +import static org.hibernate.cfg.BinderHelper.toAliasTableMap; + import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; + import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.ElementCollection; @@ -53,7 +57,6 @@ import org.hibernate.annotations.FilterJoinTable; import org.hibernate.annotations.FilterJoinTables; import org.hibernate.annotations.Filters; -import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Immutable; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollectionOption; @@ -67,10 +70,8 @@ import org.hibernate.annotations.SQLDeleteAll; import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; -import org.hibernate.annotations.Sort; import org.hibernate.annotations.SortComparator; import org.hibernate.annotations.SortNatural; -import org.hibernate.annotations.SortType; import org.hibernate.annotations.Where; import org.hibernate.annotations.WhereJoinTable; import org.hibernate.annotations.common.AssertionFailure; @@ -111,12 +112,8 @@ import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.Table; import org.hibernate.mapping.TypeDef; - import org.jboss.logging.Logger; -import static org.hibernate.cfg.BinderHelper.toAliasEntityMap; -import static org.hibernate.cfg.BinderHelper.toAliasTableMap; - /** * Base class for binding different types of collections to Hibernate configuration objects. * @@ -164,7 +161,6 @@ public abstract class CollectionBinder { private boolean isSortedCollection; private javax.persistence.OrderBy jpaOrderBy; private OrderBy sqlOrderBy; - private Sort deprecatedSort; private SortNatural naturalSort; private SortComparator comparatorSort; @@ -233,10 +229,6 @@ public void setSqlOrderBy(OrderBy sqlOrderBy) { this.sqlOrderBy = sqlOrderBy; } - public void setSort(Sort deprecatedSort) { - this.deprecatedSort = deprecatedSort; - } - public void setNaturalSort(SortNatural naturalSort) { this.naturalSort = naturalSort; } @@ -552,21 +544,7 @@ private void applySortingAndOrdering(Collection collection) { Class comparatorClass = null; if ( jpaOrderBy == null && sqlOrderBy == null ) { - if ( deprecatedSort != null ) { - LOG.debug( "Encountered deprecated @Sort annotation; use @SortNatural or @SortComparator instead." ); - if ( naturalSort != null || comparatorSort != null ) { - throw buildIllegalSortCombination(); - } - hadExplicitSort = deprecatedSort.type() != SortType.UNSORTED; - if ( deprecatedSort.type() == SortType.NATURAL ) { - isSorted = true; - } - else if ( deprecatedSort.type() == SortType.COMPARATOR ) { - isSorted = true; - comparatorClass = deprecatedSort.comparator(); - } - } - else if ( naturalSort != null ) { + if ( naturalSort != null ) { if ( comparatorSort != null ) { throw buildIllegalSortCombination(); } @@ -629,7 +607,6 @@ private AnnotationException buildIllegalSortCombination() { String.format( "Illegal combination of annotations on %s. Only one of @%s, @%s and @%s can be used", safeCollectionRole(), - Sort.class.getName(), SortNatural.class.getName(), SortComparator.class.getName() ) @@ -1090,9 +1067,6 @@ private static SimpleValue buildCollectionKey( key.setUpdateable( joinColumns.length == 0 || joinColumns[0].isUpdatable() ); key.setCascadeDeleteEnabled( cascadeDeleteEnabled ); collValue.setKey( key ); - ForeignKey fk = property != null ? property.getAnnotation( ForeignKey.class ) : null; - String fkName = fk != null ? fk.name() : ""; - if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) key.setForeignKeyName( fkName ); return key; } @@ -1244,11 +1218,6 @@ else if ( anyAnn != null ) { buildOrderByClauseFromHql( hqlOrderBy, collectionEntity, collValue.getRole() ) ); } - final ForeignKey fk = property.getAnnotation( ForeignKey.class ); - String fkName = fk != null ? fk.inverseName() : ""; - if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) { - element.setForeignKeyName( fkName ); - } } else if ( anyAnn != null ) { //@ManyToAny @@ -1446,9 +1415,14 @@ private static void bindCollectionSecondPass( boolean cascadeDeleteEnabled, XProperty property, Mappings mappings) { - BinderHelper.createSyntheticPropertyReference( - joinColumns, collValue.getOwner(), collectionEntity, collValue, false, mappings - ); + try { + BinderHelper.createSyntheticPropertyReference( + joinColumns, collValue.getOwner(), collectionEntity, collValue, false, mappings + ); + } + catch (AnnotationException ex) { + throw new AnnotationException( "Unable to map collection " + collectionEntity.getClassName() + "." + property.getName(), ex ); + } SimpleValue key = buildCollectionKey( collValue, joinColumns, cascadeDeleteEnabled, property, mappings ); if ( property.isAnnotationPresent( ElementCollection.class ) && joinColumns.length > 0 ) { joinColumns[0].setJPA2ElementCollection( true ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java index 92a69b2e62cb..9bd4f0553414 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java @@ -23,10 +23,14 @@ */ package org.hibernate.cfg.annotations; +import static org.hibernate.cfg.BinderHelper.toAliasEntityMap; +import static org.hibernate.cfg.BinderHelper.toAliasTableMap; + import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; + import javax.persistence.Access; import javax.persistence.Entity; import javax.persistence.JoinColumn; @@ -39,22 +43,17 @@ import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; import org.hibernate.MappingException; import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.annotations.DynamicInsert; -import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Filter; import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Loader; import org.hibernate.annotations.NaturalIdCache; import org.hibernate.annotations.OptimisticLockType; -import org.hibernate.annotations.OptimisticLocking; import org.hibernate.annotations.Persister; -import org.hibernate.annotations.Polymorphism; import org.hibernate.annotations.PolymorphismType; import org.hibernate.annotations.Proxy; import org.hibernate.annotations.RowId; @@ -62,7 +61,6 @@ import org.hibernate.annotations.SQLDeleteAll; import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; -import org.hibernate.annotations.SelectBeforeUpdate; import org.hibernate.annotations.Subselect; import org.hibernate.annotations.Synchronize; import org.hibernate.annotations.Tables; @@ -86,7 +84,6 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.DependantValue; import org.hibernate.mapping.Join; @@ -96,12 +93,8 @@ import org.hibernate.mapping.Table; import org.hibernate.mapping.TableOwner; import org.hibernate.mapping.Value; - import org.jboss.logging.Logger; -import static org.hibernate.cfg.BinderHelper.toAliasEntityMap; -import static org.hibernate.cfg.BinderHelper.toAliasTableMap; - /** * Stateful holder and processor for binding Entity information @@ -154,7 +147,6 @@ public EntityBinder() { public EntityBinder( Entity ejb3Ann, - org.hibernate.annotations.Entity hibAnn, XClass annotatedClass, PersistentClass persistentClass, Mappings mappings) { @@ -162,52 +154,6 @@ public EntityBinder( this.persistentClass = persistentClass; this.annotatedClass = annotatedClass; bindEjb3Annotation( ejb3Ann ); - bindHibernateAnnotation( hibAnn ); - } - - - @SuppressWarnings("SimplifiableConditionalExpression") - private void bindHibernateAnnotation(org.hibernate.annotations.Entity hibAnn) { - { - final DynamicInsert dynamicInsertAnn = annotatedClass.getAnnotation( DynamicInsert.class ); - this.dynamicInsert = dynamicInsertAnn == null - ? ( hibAnn == null ? false : hibAnn.dynamicInsert() ) - : dynamicInsertAnn.value(); - } - - { - final DynamicUpdate dynamicUpdateAnn = annotatedClass.getAnnotation( DynamicUpdate.class ); - this.dynamicUpdate = dynamicUpdateAnn == null - ? ( hibAnn == null ? false : hibAnn.dynamicUpdate() ) - : dynamicUpdateAnn.value(); - } - - { - final SelectBeforeUpdate selectBeforeUpdateAnn = annotatedClass.getAnnotation( SelectBeforeUpdate.class ); - this.selectBeforeUpdate = selectBeforeUpdateAnn == null - ? ( hibAnn == null ? false : hibAnn.selectBeforeUpdate() ) - : selectBeforeUpdateAnn.value(); - } - - { - final OptimisticLocking optimisticLockingAnn = annotatedClass.getAnnotation( OptimisticLocking.class ); - this.optimisticLockType = optimisticLockingAnn == null - ? ( hibAnn == null ? OptimisticLockType.VERSION : hibAnn.optimisticLock() ) - : optimisticLockingAnn.type(); - } - - { - final Polymorphism polymorphismAnn = annotatedClass.getAnnotation( Polymorphism.class ); - this.polymorphismType = polymorphismAnn == null - ? ( hibAnn == null ? PolymorphismType.IMPLICIT : hibAnn.polymorphism() ) - : polymorphismAnn.type(); - } - - if ( hibAnn != null ) { - // used later in bind for logging - explicitHibernateEntityAnnotation = true; - //persister handled in bind - } } private void bindEjb3Annotation(Entity ejb3Ann) { @@ -260,13 +206,6 @@ public void bindEntity() { if ( annotatedClass.isAnnotationPresent( Immutable.class ) ) { mutable = false; } - else { - org.hibernate.annotations.Entity entityAnn = - annotatedClass.getAnnotation( org.hibernate.annotations.Entity.class ); - if ( entityAnn != null ) { - mutable = entityAnn.mutable(); - } - } rootClass.setMutable( mutable ); rootClass.setExplicitPolymorphism( isExplicitPolymorphism( polymorphismType ) ); if ( StringHelper.isNotEmpty( where ) ) rootClass.setWhere( where ); @@ -301,17 +240,6 @@ public void bindEntity() { if ( persisterAnn != null ) { persister = persisterAnn.impl(); } - else { - org.hibernate.annotations.Entity entityAnn = annotatedClass.getAnnotation( org.hibernate.annotations.Entity.class ); - if ( entityAnn != null && !BinderHelper.isEmptyAnnotationValue( entityAnn.persister() ) ) { - try { - persister = ReflectHelper.classForName( entityAnn.persister() ); - } - catch (ClassNotFoundException cnfe) { - throw new AnnotationException( "Could not find persister class: " + persister ); - } - } - } if ( persister != null ) { persistentClass.setEntityPersisterClass( persister ); } @@ -367,16 +295,12 @@ public void bindEntity() { //tuplizers if ( annotatedClass.isAnnotationPresent( Tuplizers.class ) ) { for (Tuplizer tuplizer : annotatedClass.getAnnotation( Tuplizers.class ).value()) { - EntityMode mode = EntityMode.parse( tuplizer.entityMode() ); - //todo tuplizer.entityModeType - persistentClass.addTuplizer( mode, tuplizer.impl().getName() ); + persistentClass.addTuplizer( tuplizer.entityModeType(), tuplizer.impl().getName() ); } } if ( annotatedClass.isAnnotationPresent( Tuplizer.class ) ) { Tuplizer tuplizer = annotatedClass.getAnnotation( Tuplizer.class ); - EntityMode mode = EntityMode.parse( tuplizer.entityMode() ); - //todo tuplizer.entityModeType - persistentClass.addTuplizer( mode, tuplizer.impl().getName() ); + persistentClass.addTuplizer( tuplizer.entityModeType(), tuplizer.impl().getName() ); } for ( Filter filter : filters ) { @@ -998,30 +922,9 @@ public AccessType getPropertyAccessor(XAnnotatedElement element) { public AccessType getExplicitAccessType(XAnnotatedElement element) { AccessType accessType = null; - AccessType hibernateAccessType = null; - AccessType jpaAccessType = null; - - org.hibernate.annotations.AccessType accessTypeAnnotation = element.getAnnotation( org.hibernate.annotations.AccessType.class ); - if ( accessTypeAnnotation != null ) { - hibernateAccessType = AccessType.getAccessStrategy( accessTypeAnnotation.value() ); - } - Access access = element.getAnnotation( Access.class ); if ( access != null ) { - jpaAccessType = AccessType.getAccessStrategy( access.value() ); - } - - if ( hibernateAccessType != null && jpaAccessType != null && hibernateAccessType != jpaAccessType ) { - throw new MappingException( - "Found @Access and @AccessType with conflicting values on a property in class " + annotatedClass.toString() - ); - } - - if ( hibernateAccessType != null ) { - accessType = hibernateAccessType; - } - else if ( jpaAccessType != null ) { - accessType = jpaAccessType; + accessType = AccessType.getAccessStrategy( access.value() ); } return accessType; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java index c79cc22a267e..b4e2f0adf1c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java @@ -28,7 +28,6 @@ import org.hibernate.AnnotationException; import org.hibernate.MappingException; import org.hibernate.annotations.OrderBy; -import org.hibernate.annotations.Sort; import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.cfg.CollectionSecondPass; @@ -46,7 +45,6 @@ import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.SimpleValue; - import org.jboss.logging.Logger; /** @@ -74,12 +72,6 @@ public void setSqlOrderBy(OrderBy orderByAnn) { LOG.orderByAnnotationIndexedCollection(); } - @Override - public void setSort(Sort sortAnn) { - if ( sortAnn != null ) - LOG.sortAnnotationIndexedCollection(); - } - @Override public SecondPass getSecondPass( final Ejb3JoinColumn[] fkJoinColumns, diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java index d3ddd8a71666..22149d2d8730 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java @@ -24,6 +24,7 @@ package org.hibernate.cfg.annotations; import java.util.HashMap; + import javax.persistence.NamedNativeQueries; import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; @@ -50,7 +51,6 @@ import org.hibernate.engine.spi.NamedSQLQueryDefinition; import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; import org.hibernate.internal.CoreMessageLogger; - import org.jboss.logging.Logger; /** @@ -279,9 +279,6 @@ private static FlushMode getFlushMode(FlushModeType flushModeType) { case COMMIT: flushMode = FlushMode.COMMIT; break; - case NEVER: - flushMode = FlushMode.MANUAL; - break; case MANUAL: flushMode = FlushMode.MANUAL; break; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java index 83041f6af89e..6e59709cf31e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java @@ -26,14 +26,14 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; + +import javax.persistence.Index; import javax.persistence.UniqueConstraint; import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; -import org.hibernate.annotations.Index; import org.hibernate.cfg.BinderHelper; import org.hibernate.cfg.Ejb3JoinColumn; -import org.hibernate.cfg.IndexOrUniqueKeySecondPass; import org.hibernate.cfg.JPAIndexHolder; import org.hibernate.cfg.Mappings; import org.hibernate.cfg.NamingStrategy; @@ -53,7 +53,6 @@ import org.hibernate.mapping.Table; import org.hibernate.mapping.ToOne; import org.hibernate.mapping.Value; - import org.jboss.logging.Logger; /** @@ -107,7 +106,7 @@ public void setUniqueConstraints(UniqueConstraint[] uniqueConstraints) { this.uniqueConstraints = TableBinder.buildUniqueConstraintHolders( uniqueConstraints ); } - public void setJpaIndex(javax.persistence.Index[] jpaIndex){ + public void setJpaIndex(Index[] jpaIndex){ this.jpaIndexHolders = buildJpaIndexHolder( jpaIndex ); } @@ -536,21 +535,12 @@ public static void createUniqueConstraint(Value value) { } public static void addIndexes(Table hibTable, Index[] indexes, Mappings mappings) { - for (Index index : indexes) { - //no need to handle inSecondPass here since it is only called from EntityBinder - mappings.addSecondPass( - new IndexOrUniqueKeySecondPass( hibTable, index.name(), index.columnNames(), mappings ) - ); - } - } - - public static void addIndexes(Table hibTable, javax.persistence.Index[] indexes, Mappings mappings) { mappings.addJpaIndexHolders( hibTable, buildJpaIndexHolder( indexes ) ); } - public static List buildJpaIndexHolder(javax.persistence.Index[] indexes){ + public static List buildJpaIndexHolder(Index[] indexes){ List holders = new ArrayList( indexes.length ); - for(javax.persistence.Index index : indexes){ + for(Index index : indexes){ holders.add( new JPAIndexHolder( index ) ); } return holders; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverriddenAnnotationReader.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverriddenAnnotationReader.java index a4791c36facb..bea60db6c284 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverriddenAnnotationReader.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverriddenAnnotationReader.java @@ -21,7 +21,6 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ - package org.hibernate.cfg.annotations.reflection; import java.beans.Introspector; @@ -51,6 +50,7 @@ import javax.persistence.ColumnResult; import javax.persistence.ConstructorResult; import javax.persistence.Convert; +import javax.persistence.Converts; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; @@ -137,14 +137,12 @@ import org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor; import org.hibernate.annotations.common.annotationfactory.AnnotationFactory; import org.hibernate.annotations.common.reflection.AnnotationReader; -import org.hibernate.annotations.common.reflection.Filter; import org.hibernate.annotations.common.reflection.ReflectionUtil; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; -import org.jboss.logging.Logger; - import org.dom4j.Attribute; import org.dom4j.Element; @@ -158,20 +156,18 @@ */ @SuppressWarnings("unchecked") public class JPAOverriddenAnnotationReader implements AnnotationReader { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JPAOverriddenAnnotationReader.class ); - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, - JPAOverriddenAnnotationReader.class.getName()); - private static final Map annotationToXml; private static final String SCHEMA_VALIDATION = "Activate schema validation for more information"; - private static final Filter FILTER = new Filter() { - public boolean returnStatic() { - return false; - } + private static final String WORD_SEPARATOR = "-"; - public boolean returnTransient() { - return false; - } - }; + private static enum PropertyType { + PROPERTY, + FIELD, + METHOD + } + + private static final Map annotationToXml; static { annotationToXml = new HashMap(); @@ -251,25 +247,19 @@ public boolean returnTransient() { annotationToXml.put( Index.class, "index" ); annotationToXml.put( ForeignKey.class, "foreign-key" ); annotationToXml.put( Convert.class, "convert" ); + annotationToXml.put( Converts.class, "convert" ); annotationToXml.put( ConstructorResult.class, "constructor-result" ); } private XMLContext xmlContext; + private final AnnotatedElement element; private String className; private String propertyName; private PropertyType propertyType; private transient Annotation[] annotations; private transient Map annotationsMap; - private static final String WORD_SEPARATOR = "-"; private transient List elementsForProperty; private AccessibleObject mirroredAttribute; - private final AnnotatedElement element; - - private enum PropertyType { - PROPERTY, - FIELD, - METHOD - } public JPAOverriddenAnnotationReader(AnnotatedElement el, XMLContext xmlContext) { this.element = el; @@ -297,11 +287,9 @@ else if ( el instanceof Method ) { Method method = (Method) el; className = method.getDeclaringClass().getName(); propertyName = method.getName(); - if ( ReflectionUtil.isProperty( - method, - null, //this is yukky!! we'd rather get the TypeEnvironment() - FILTER - ) ) { + + // YUCK! The null here is the 'boundType', we'd rather get the TypeEnvironment() + if ( ReflectionUtil.isProperty( method, null, PersistentAttributeFilter.INSTANCE ) ) { if ( propertyName.startsWith( "get" ) ) { propertyName = Introspector.decapitalize( propertyName.substring( "get".length() ) ); } @@ -354,7 +342,7 @@ private void initAnnotations() { if ( className != null && propertyName == null ) { //is a class Element tree = xmlContext.getXMLTree( className ); - Annotation[] annotations = getJavaAnnotations(); + Annotation[] annotations = getPhysicalAnnotations(); List annotationList = new ArrayList( annotations.length + 5 ); annotationsMap = new HashMap( annotations.length + 5 ); for ( Annotation annotation : annotations ) { @@ -387,6 +375,8 @@ private void initAnnotations() { addIfNotNull( annotationList, getAttributeOverrides( tree, defaults, true ) ); addIfNotNull( annotationList, getAssociationOverrides( tree, defaults, true ) ); addIfNotNull( annotationList, getEntityListeners( tree, defaults ) ); + addIfNotNull( annotationList, getConverts( tree, defaults ) ); + this.annotations = annotationList.toArray( new Annotation[annotationList.size()] ); for ( Annotation ann : this.annotations ) { annotationsMap.put( ann.annotationType(), ann ); @@ -395,7 +385,7 @@ private void initAnnotations() { } else if ( className != null ) { //&& propertyName != null ) { //always true but less confusing Element tree = xmlContext.getXMLTree( className ); - Annotation[] annotations = getJavaAnnotations(); + Annotation[] annotations = getPhysicalAnnotations(); List annotationList = new ArrayList( annotations.length + 5 ); annotationsMap = new HashMap( annotations.length + 5 ); for ( Annotation annotation : annotations ) { @@ -411,7 +401,7 @@ else if ( className != null ) { //&& propertyName != null ) { //always true but } else { if ( defaults.canUseJavaAnnotations() ) { - Annotation annotation = getJavaAnnotation( Access.class ); + Annotation annotation = getPhysicalAnnotation( Access.class ); addIfNotNull( annotationList, annotation ); } getId( annotationList, defaults ); @@ -428,6 +418,7 @@ else if ( className != null ) { //&& propertyName != null ) { //always true but getElementCollection( annotationList, defaults ); addIfNotNull( annotationList, getSequenceGenerator( elementsForProperty, defaults ) ); addIfNotNull( annotationList, getTableGenerator( elementsForProperty, defaults ) ); + addIfNotNull( annotationList, getConvertsForAttribute( elementsForProperty, defaults ) ); } processEventAnnotations( annotationList, defaults ); //FIXME use annotationsMap rather than annotationList this will be faster since the annotation type is usually known at put() time @@ -437,7 +428,7 @@ else if ( className != null ) { //&& propertyName != null ) { //always true but } } else { - this.annotations = getJavaAnnotations(); + this.annotations = getPhysicalAnnotations(); annotationsMap = new HashMap( annotations.length + 5 ); for ( Annotation ann : this.annotations ) { annotationsMap.put( ann.annotationType(), ann ); @@ -446,6 +437,146 @@ else if ( className != null ) { //&& propertyName != null ) { //always true but } } + private Annotation getConvertsForAttribute(List elementsForProperty, XMLContext.Default defaults) { + // NOTE : we use a map here to make sure that an xml and annotation referring to the same attribute + // properly overrides. Very sparse map, yes, but easy setup. + // todo : revisit this + // although bear in mind that this code is no longer used in 5.0... + + final Map convertAnnotationsMap = new HashMap(); + + for ( Element element : elementsForProperty ) { + final boolean isBasic = "basic".equals( element.getName() ); + final boolean isEmbedded = "embedded".equals( element.getName() ); + + // todo : can be collections too + + final boolean canHaveConverts = isBasic || isEmbedded; + + if ( !canHaveConverts ) { + continue; + } + + final String attributeNamePrefix = isBasic ? null : propertyName; + applyXmlDefinedConverts( element, defaults, attributeNamePrefix, convertAnnotationsMap ); + } + + // NOTE : per section 12.2.3.16 of the spec is additive, although only if "metadata-complete" is not + // specified in the XML + + if ( defaults.canUseJavaAnnotations() ) { + // todo : note sure how to best handle attributeNamePrefix here + applyPhysicalConvertAnnotations( propertyName, convertAnnotationsMap ); + } + + if ( !convertAnnotationsMap.isEmpty() ) { + final AnnotationDescriptor groupingDescriptor = new AnnotationDescriptor( Converts.class ); + groupingDescriptor.setValue( "value", convertAnnotationsMap.values().toArray( new Convert[convertAnnotationsMap.size()]) ); + return AnnotationFactory.create( groupingDescriptor ); + } + + return null; + } + + private Converts getConverts(Element tree, XMLContext.Default defaults) { + // NOTE : we use a map here to make sure that an xml and annotation referring to the same attribute + // properly overrides. Bit sparse, but easy... + final Map convertAnnotationsMap = new HashMap(); + + if ( tree != null ) { + applyXmlDefinedConverts( tree, defaults, null, convertAnnotationsMap ); + } + + // NOTE : per section 12.2.3.16 of the spec is additive, although only if "metadata-complete" is not + // specified in the XML + + if ( defaults.canUseJavaAnnotations() ) { + applyPhysicalConvertAnnotations( null, convertAnnotationsMap ); + } + + if ( !convertAnnotationsMap.isEmpty() ) { + final AnnotationDescriptor groupingDescriptor = new AnnotationDescriptor( Converts.class ); + groupingDescriptor.setValue( "value", convertAnnotationsMap.values().toArray( new Convert[convertAnnotationsMap.size()]) ); + return AnnotationFactory.create( groupingDescriptor ); + } + + return null; + } + + private void applyXmlDefinedConverts( + Element containingElement, + XMLContext.Default defaults, + String attributeNamePrefix, + Map convertAnnotationsMap) { + final List convertElements = containingElement.elements( "convert" ); + for ( Element convertElement : convertElements ) { + final AnnotationDescriptor convertAnnotationDescriptor = new AnnotationDescriptor( Convert.class ); + copyStringAttribute( convertAnnotationDescriptor, convertElement, "attribute-name", false ); + copyBooleanAttribute( convertAnnotationDescriptor, convertElement, "disable-conversion" ); + + final Attribute converterClassAttr = convertElement.attribute( "converter" ); + if ( converterClassAttr != null ) { + final String converterClassName = XMLContext.buildSafeClassName( + converterClassAttr.getValue(), + defaults + ); + try { + final Class converterClass = ReflectHelper.classForName( converterClassName, this.getClass() ); + convertAnnotationDescriptor.setValue( "converter", converterClass ); + } + catch (ClassNotFoundException e) { + throw new AnnotationException( "Unable to find specified converter class id-class: " + converterClassName, e ); + } + } + final Convert convertAnnotation = AnnotationFactory.create( convertAnnotationDescriptor ); + final String qualifiedAttributeName = qualifyConverterAttributeName( + attributeNamePrefix, + convertAnnotation.attributeName() + ); + convertAnnotationsMap.put( qualifiedAttributeName, convertAnnotation ); + } + + } + + private String qualifyConverterAttributeName(String attributeNamePrefix, String specifiedAttributeName) { + String qualifiedAttributeName; + if ( StringHelper.isNotEmpty( specifiedAttributeName ) ) { + if ( StringHelper.isNotEmpty( attributeNamePrefix ) ) { + qualifiedAttributeName = attributeNamePrefix + '.' + specifiedAttributeName; + } + else { + qualifiedAttributeName = specifiedAttributeName; + } + } + else { + qualifiedAttributeName = ""; + } + return qualifiedAttributeName; + } + + private void applyPhysicalConvertAnnotations( + String attributeNamePrefix, + Map convertAnnotationsMap) { + final Convert physicalAnnotation = getPhysicalAnnotation( Convert.class ); + if ( physicalAnnotation != null ) { + // only add if no XML element named a converter for this attribute + final String qualifiedAttributeName = qualifyConverterAttributeName( attributeNamePrefix, physicalAnnotation.attributeName() ); + if ( ! convertAnnotationsMap.containsKey( qualifiedAttributeName ) ) { + convertAnnotationsMap.put( qualifiedAttributeName, physicalAnnotation ); + } + } + final Converts physicalGroupingAnnotation = getPhysicalAnnotation( Converts.class ); + if ( physicalGroupingAnnotation != null ) { + for ( Convert convertAnnotation : physicalGroupingAnnotation.value() ) { + // again, only add if no XML element named a converter for this attribute + final String qualifiedAttributeName = qualifyConverterAttributeName( attributeNamePrefix, convertAnnotation.attributeName() ); + if ( ! convertAnnotationsMap.containsKey( qualifiedAttributeName ) ) { + convertAnnotationsMap.put( qualifiedAttributeName, convertAnnotation ); + } + } + } + } + private void checkForOrphanProperties(Element tree) { Class clazz; try { @@ -505,7 +636,7 @@ private Annotation getTableGenerator(List elementsForProperty, XMLConte } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( TableGenerator.class ); + return getPhysicalAnnotation( TableGenerator.class ); } else { return null; @@ -520,7 +651,7 @@ private Annotation getSequenceGenerator(List elementsForProperty, XMLCo } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( SequenceGenerator.class ); + return getPhysicalAnnotation( SequenceGenerator.class ); } else { return null; @@ -568,19 +699,19 @@ else if ( "post-load".equals( elementName ) ) { } } if ( !eventElement && defaults.canUseJavaAnnotations() ) { - Annotation ann = getJavaAnnotation( PrePersist.class ); + Annotation ann = getPhysicalAnnotation( PrePersist.class ); addIfNotNull( annotationList, ann ); - ann = getJavaAnnotation( PreRemove.class ); + ann = getPhysicalAnnotation( PreRemove.class ); addIfNotNull( annotationList, ann ); - ann = getJavaAnnotation( PreUpdate.class ); + ann = getPhysicalAnnotation( PreUpdate.class ); addIfNotNull( annotationList, ann ); - ann = getJavaAnnotation( PostPersist.class ); + ann = getPhysicalAnnotation( PostPersist.class ); addIfNotNull( annotationList, ann ); - ann = getJavaAnnotation( PostRemove.class ); + ann = getPhysicalAnnotation( PostRemove.class ); addIfNotNull( annotationList, ann ); - ann = getJavaAnnotation( PostUpdate.class ); + ann = getPhysicalAnnotation( PostUpdate.class ); addIfNotNull( annotationList, ann ); - ann = getJavaAnnotation( PostLoad.class ); + ann = getPhysicalAnnotation( PostLoad.class ); addIfNotNull( annotationList, ann ); } } @@ -610,7 +741,7 @@ private EntityListeners getEntityListeners(Element tree, XMLContext.Default defa return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( EntityListeners.class ); + return getPhysicalAnnotation( EntityListeners.class ); } else { return null; @@ -619,8 +750,8 @@ else if ( defaults.canUseJavaAnnotations() ) { private JoinTable overridesDefaultsInJoinTable(Annotation annotation, XMLContext.Default defaults) { //no element but might have some default or some annotation - boolean defaultToJoinTable = !( isJavaAnnotationPresent( JoinColumn.class ) - || isJavaAnnotationPresent( JoinColumns.class ) ); + boolean defaultToJoinTable = !( isPhysicalAnnotationPresent( JoinColumn.class ) + || isPhysicalAnnotationPresent( JoinColumns.class ) ); final Class annotationClass = annotation.annotationType(); defaultToJoinTable = defaultToJoinTable && ( ( annotationClass == ManyToMany.class && StringHelper.isEmpty( ( (ManyToMany) annotation ).mappedBy() ) ) @@ -633,7 +764,7 @@ private JoinTable overridesDefaultsInJoinTable(Annotation annotation, XMLContext || StringHelper.isNotEmpty( defaults.getSchema() ) ) ) { AnnotationDescriptor ad = new AnnotationDescriptor( annotationType ); if ( defaults.canUseJavaAnnotations() ) { - JoinTable table = getJavaAnnotation( annotationType ); + JoinTable table = getPhysicalAnnotation( annotationType ); if ( table != null ) { ad.setValue( "name", table.name() ); ad.setValue( "schema", table.schema() ); @@ -654,7 +785,7 @@ private JoinTable overridesDefaultsInJoinTable(Annotation annotation, XMLContext return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( annotationType ); + return getPhysicalAnnotation( annotationType ); } else { return null; @@ -737,96 +868,96 @@ private void getAssociation( } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - Annotation annotation = getJavaAnnotation( annotationType ); + Annotation annotation = getPhysicalAnnotation( annotationType ); if ( annotation != null ) { annotationList.add( annotation ); annotation = overridesDefaultsInJoinTable( annotation, defaults ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( JoinColumn.class ); + annotation = getPhysicalAnnotation( JoinColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( JoinColumns.class ); + annotation = getPhysicalAnnotation( JoinColumns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( PrimaryKeyJoinColumn.class ); + annotation = getPhysicalAnnotation( PrimaryKeyJoinColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( PrimaryKeyJoinColumns.class ); + annotation = getPhysicalAnnotation( PrimaryKeyJoinColumns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKey.class ); + annotation = getPhysicalAnnotation( MapKey.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( OrderBy.class ); + annotation = getPhysicalAnnotation( OrderBy.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverride.class ); + annotation = getPhysicalAnnotation( AttributeOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverrides.class ); + annotation = getPhysicalAnnotation( AttributeOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverride.class ); + annotation = getPhysicalAnnotation( AssociationOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverrides.class ); + annotation = getPhysicalAnnotation( AssociationOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Lob.class ); + annotation = getPhysicalAnnotation( Lob.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Enumerated.class ); + annotation = getPhysicalAnnotation( Enumerated.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Temporal.class ); + annotation = getPhysicalAnnotation( Temporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Column.class ); + annotation = getPhysicalAnnotation( Column.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Columns.class ); + annotation = getPhysicalAnnotation( Columns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyClass.class ); + annotation = getPhysicalAnnotation( MapKeyClass.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyTemporal.class ); + annotation = getPhysicalAnnotation( MapKeyTemporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyEnumerated.class ); + annotation = getPhysicalAnnotation( MapKeyEnumerated.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyColumn.class ); + annotation = getPhysicalAnnotation( MapKeyColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyJoinColumn.class ); + annotation = getPhysicalAnnotation( MapKeyJoinColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyJoinColumns.class ); + annotation = getPhysicalAnnotation( MapKeyJoinColumns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( OrderColumn.class ); + annotation = getPhysicalAnnotation( OrderColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Cascade.class ); + annotation = getPhysicalAnnotation( Cascade.class ); addIfNotNull( annotationList, annotation ); } - else if ( isJavaAnnotationPresent( ElementCollection.class ) ) { //JPA2 - annotation = overridesDefaultsInJoinTable( getJavaAnnotation( ElementCollection.class ), defaults ); + else if ( isPhysicalAnnotationPresent( ElementCollection.class ) ) { //JPA2 + annotation = overridesDefaultsInJoinTable( getPhysicalAnnotation( ElementCollection.class ), defaults ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKey.class ); + annotation = getPhysicalAnnotation( MapKey.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( OrderBy.class ); + annotation = getPhysicalAnnotation( OrderBy.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverride.class ); + annotation = getPhysicalAnnotation( AttributeOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverrides.class ); + annotation = getPhysicalAnnotation( AttributeOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverride.class ); + annotation = getPhysicalAnnotation( AssociationOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverrides.class ); + annotation = getPhysicalAnnotation( AssociationOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Lob.class ); + annotation = getPhysicalAnnotation( Lob.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Enumerated.class ); + annotation = getPhysicalAnnotation( Enumerated.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Temporal.class ); + annotation = getPhysicalAnnotation( Temporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Column.class ); + annotation = getPhysicalAnnotation( Column.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( OrderColumn.class ); + annotation = getPhysicalAnnotation( OrderColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyClass.class ); + annotation = getPhysicalAnnotation( MapKeyClass.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyTemporal.class ); + annotation = getPhysicalAnnotation( MapKeyTemporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyEnumerated.class ); + annotation = getPhysicalAnnotation( MapKeyEnumerated.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyColumn.class ); + annotation = getPhysicalAnnotation( MapKeyColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyJoinColumn.class ); + annotation = getPhysicalAnnotation( MapKeyJoinColumn.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( MapKeyJoinColumns.class ); + annotation = getPhysicalAnnotation( MapKeyJoinColumns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( CollectionTable.class ); + annotation = getPhysicalAnnotation( CollectionTable.class ); addIfNotNull( annotationList, annotation ); } } @@ -876,7 +1007,7 @@ private Cacheable getCacheable(Element element, XMLContext.Default defaults){ } } if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( Cacheable.class ); + return getPhysicalAnnotation( Cacheable.class ); } else { return null; @@ -1158,16 +1289,16 @@ private void getEmbedded(List annotationList, XMLContext.Default def } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - Annotation annotation = getJavaAnnotation( Embedded.class ); + Annotation annotation = getPhysicalAnnotation( Embedded.class ); if ( annotation != null ) { annotationList.add( annotation ); - annotation = getJavaAnnotation( AttributeOverride.class ); + annotation = getPhysicalAnnotation( AttributeOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverrides.class ); + annotation = getPhysicalAnnotation( AttributeOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverride.class ); + annotation = getPhysicalAnnotation( AssociationOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverrides.class ); + annotation = getPhysicalAnnotation( AssociationOverrides.class ); addIfNotNull( annotationList, annotation ); } } @@ -1181,7 +1312,7 @@ private Transient getTransient(XMLContext.Default defaults) { } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( Transient.class ); + return getPhysicalAnnotation( Transient.class ); } else { return null; @@ -1201,14 +1332,14 @@ private void getVersion(List annotationList, XMLContext.Default defa } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { //we have nothing, so Java annotations might occurs - Annotation annotation = getJavaAnnotation( Version.class ); + Annotation annotation = getPhysicalAnnotation( Version.class ); if ( annotation != null ) { annotationList.add( annotation ); - annotation = getJavaAnnotation( Column.class ); + annotation = getPhysicalAnnotation( Column.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Columns.class ); + annotation = getPhysicalAnnotation( Columns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Temporal.class ); + annotation = getPhysicalAnnotation( Temporal.class ); addIfNotNull( annotationList, annotation ); } } @@ -1231,25 +1362,25 @@ private void getBasic(List annotationList, XMLContext.Default defaul } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { //no annotation presence constraint, basic is the default - Annotation annotation = getJavaAnnotation( Basic.class ); + Annotation annotation = getPhysicalAnnotation( Basic.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Lob.class ); + annotation = getPhysicalAnnotation( Lob.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Enumerated.class ); + annotation = getPhysicalAnnotation( Enumerated.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Temporal.class ); + annotation = getPhysicalAnnotation( Temporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Column.class ); + annotation = getPhysicalAnnotation( Column.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Columns.class ); + annotation = getPhysicalAnnotation( Columns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverride.class ); + annotation = getPhysicalAnnotation( AttributeOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverrides.class ); + annotation = getPhysicalAnnotation( AttributeOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverride.class ); + annotation = getPhysicalAnnotation( AssociationOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverrides.class ); + annotation = getPhysicalAnnotation( AssociationOverrides.class ); addIfNotNull( annotationList, annotation ); } } @@ -1306,28 +1437,28 @@ private void getEmbeddedId(List annotationList, XMLContext.Default d } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - Annotation annotation = getJavaAnnotation( EmbeddedId.class ); + Annotation annotation = getPhysicalAnnotation( EmbeddedId.class ); if ( annotation != null ) { annotationList.add( annotation ); - annotation = getJavaAnnotation( Column.class ); + annotation = getPhysicalAnnotation( Column.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Columns.class ); + annotation = getPhysicalAnnotation( Columns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( GeneratedValue.class ); + annotation = getPhysicalAnnotation( GeneratedValue.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Temporal.class ); + annotation = getPhysicalAnnotation( Temporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( TableGenerator.class ); + annotation = getPhysicalAnnotation( TableGenerator.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( SequenceGenerator.class ); + annotation = getPhysicalAnnotation( SequenceGenerator.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverride.class ); + annotation = getPhysicalAnnotation( AttributeOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverrides.class ); + annotation = getPhysicalAnnotation( AttributeOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverride.class ); + annotation = getPhysicalAnnotation( AssociationOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverrides.class ); + annotation = getPhysicalAnnotation( AssociationOverrides.class ); addIfNotNull( annotationList, annotation ); } } @@ -1376,28 +1507,28 @@ private void getId(List annotationList, XMLContext.Default defaults) } } if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) { - Annotation annotation = getJavaAnnotation( Id.class ); + Annotation annotation = getPhysicalAnnotation( Id.class ); if ( annotation != null ) { annotationList.add( annotation ); - annotation = getJavaAnnotation( Column.class ); + annotation = getPhysicalAnnotation( Column.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Columns.class ); + annotation = getPhysicalAnnotation( Columns.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( GeneratedValue.class ); + annotation = getPhysicalAnnotation( GeneratedValue.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( Temporal.class ); + annotation = getPhysicalAnnotation( Temporal.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( TableGenerator.class ); + annotation = getPhysicalAnnotation( TableGenerator.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( SequenceGenerator.class ); + annotation = getPhysicalAnnotation( SequenceGenerator.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverride.class ); + annotation = getPhysicalAnnotation( AttributeOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AttributeOverrides.class ); + annotation = getPhysicalAnnotation( AttributeOverrides.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverride.class ); + annotation = getPhysicalAnnotation( AssociationOverride.class ); addIfNotNull( annotationList, annotation ); - annotation = getJavaAnnotation( AssociationOverrides.class ); + annotation = getPhysicalAnnotation( AssociationOverrides.class ); addIfNotNull( annotationList, annotation ); } } @@ -1410,7 +1541,7 @@ private boolean isProcessingId(XMLContext.Default defaults) { || ( PropertyType.FIELD.equals( propertyType ) && AccessType.FIELD .equals( defaults.getAccess() ) ); boolean hasId = defaults.canUseJavaAnnotations() - && ( isJavaAnnotationPresent( Id.class ) || isJavaAnnotationPresent( EmbeddedId.class ) ); + && ( isPhysicalAnnotationPresent( Id.class ) || isPhysicalAnnotationPresent( EmbeddedId.class ) ); //if ( properAccessOnMetadataComplete || properOverridingOnMetadataNonComplete ) { boolean mirrorAttributeIsId = defaults.canUseJavaAnnotations() && ( mirroredAttribute != null && @@ -1520,9 +1651,9 @@ private void getAccessType(List annotationList, Element element) { private AssociationOverrides getAssociationOverrides(Element tree, XMLContext.Default defaults, boolean mergeWithAnnotations) { List attributes = buildAssociationOverrides( tree, defaults ); if ( mergeWithAnnotations && defaults.canUseJavaAnnotations() ) { - AssociationOverride annotation = getJavaAnnotation( AssociationOverride.class ); + AssociationOverride annotation = getPhysicalAnnotation( AssociationOverride.class ); addAssociationOverrideIfNeeded( annotation, attributes ); - AssociationOverrides annotations = getJavaAnnotation( AssociationOverrides.class ); + AssociationOverrides annotations = getPhysicalAnnotation( AssociationOverrides.class ); if ( annotations != null ) { for ( AssociationOverride current : annotations.value() ) { addAssociationOverrideIfNeeded( current, attributes ); @@ -1614,9 +1745,9 @@ private AttributeOverrides getAttributeOverrides(Element tree, XMLContext.Defaul */ private AttributeOverrides mergeAttributeOverrides(XMLContext.Default defaults, List attributes, boolean mergeWithAnnotations) { if ( mergeWithAnnotations && defaults.canUseJavaAnnotations() ) { - AttributeOverride annotation = getJavaAnnotation( AttributeOverride.class ); + AttributeOverride annotation = getPhysicalAnnotation( AttributeOverride.class ); addAttributeOverrideIfNeeded( annotation, attributes ); - AttributeOverrides annotations = getJavaAnnotation( AttributeOverrides.class ); + AttributeOverrides annotations = getPhysicalAnnotation( AttributeOverrides.class ); if ( annotations != null ) { for ( AttributeOverride current : annotations.value() ) { addAttributeOverrideIfNeeded( current, attributes ); @@ -1709,8 +1840,8 @@ private Access getAccessType(Element tree, XMLContext.Default defaults) { ad.setValue( "value", type ); return AnnotationFactory.create( ad ); } - else if ( defaults.canUseJavaAnnotations() && isJavaAnnotationPresent( Access.class ) ) { - return getJavaAnnotation( Access.class ); + else if ( defaults.canUseJavaAnnotations() && isPhysicalAnnotationPresent( Access.class ) ) { + return getPhysicalAnnotation( Access.class ); } else if ( defaults.getAccess() != null ) { AnnotationDescriptor ad = new AnnotationDescriptor( Access.class ); @@ -1739,7 +1870,7 @@ private Annotation getMarkerAnnotation( } else if ( defaults.canUseJavaAnnotations() ) { //TODO wonder whether it should be excluded so that user can undone it - return getJavaAnnotation( clazz ); + return getPhysicalAnnotation( clazz ); } else { return null; @@ -1749,9 +1880,9 @@ else if ( defaults.canUseJavaAnnotations() ) { private SqlResultSetMappings getSqlResultSetMappings(Element tree, XMLContext.Default defaults) { List results = buildSqlResultsetMappings( tree, defaults ); if ( defaults.canUseJavaAnnotations() ) { - SqlResultSetMapping annotation = getJavaAnnotation( SqlResultSetMapping.class ); + SqlResultSetMapping annotation = getPhysicalAnnotation( SqlResultSetMapping.class ); addSqlResultsetMappingIfNeeded( annotation, results ); - SqlResultSetMappings annotations = getJavaAnnotation( SqlResultSetMappings.class ); + SqlResultSetMappings annotations = getPhysicalAnnotation( SqlResultSetMappings.class ); if ( annotations != null ) { for ( SqlResultSetMapping current : annotations.value() ) { addSqlResultsetMappingIfNeeded( current, results ); @@ -2088,9 +2219,9 @@ private NamedQueries getNamedQueries(Element tree, XMLContext.Default defaults) //TODO avoid the Proxy Creation (@NamedQueries) when possible List queries = (List) buildNamedQueries( tree, false, defaults ); if ( defaults.canUseJavaAnnotations() ) { - NamedQuery annotation = getJavaAnnotation( NamedQuery.class ); + NamedQuery annotation = getPhysicalAnnotation( NamedQuery.class ); addNamedQueryIfNeeded( annotation, queries ); - NamedQueries annotations = getJavaAnnotation( NamedQueries.class ); + NamedQueries annotations = getPhysicalAnnotation( NamedQueries.class ); if ( annotations != null ) { for ( NamedQuery current : annotations.value() ) { addNamedQueryIfNeeded( current, queries ); @@ -2126,9 +2257,9 @@ private void addNamedQueryIfNeeded(NamedQuery annotation, List queri private NamedEntityGraphs getNamedEntityGraphs(Element tree, XMLContext.Default defaults) { List queries = buildNamedEntityGraph( tree, defaults ); if ( defaults.canUseJavaAnnotations() ) { - NamedEntityGraph annotation = getJavaAnnotation( NamedEntityGraph.class ); + NamedEntityGraph annotation = getPhysicalAnnotation( NamedEntityGraph.class ); addNamedEntityGraphIfNeeded( annotation, queries ); - NamedEntityGraphs annotations = getJavaAnnotation( NamedEntityGraphs.class ); + NamedEntityGraphs annotations = getPhysicalAnnotation( NamedEntityGraphs.class ); if ( annotations != null ) { for ( NamedEntityGraph current : annotations.value() ) { addNamedEntityGraphIfNeeded( current, queries ); @@ -2165,9 +2296,9 @@ private void addNamedEntityGraphIfNeeded(NamedEntityGraph annotation, List queries = buildNamedStoreProcedureQueries( tree, defaults ); if ( defaults.canUseJavaAnnotations() ) { - NamedStoredProcedureQuery annotation = getJavaAnnotation( NamedStoredProcedureQuery.class ); + NamedStoredProcedureQuery annotation = getPhysicalAnnotation( NamedStoredProcedureQuery.class ); addNamedStoredProcedureQueryIfNeeded( annotation, queries ); - NamedStoredProcedureQueries annotations = getJavaAnnotation( NamedStoredProcedureQueries.class ); + NamedStoredProcedureQueries annotations = getPhysicalAnnotation( NamedStoredProcedureQueries.class ); if ( annotations != null ) { for ( NamedStoredProcedureQuery current : annotations.value() ) { addNamedStoredProcedureQueryIfNeeded( current, queries ); @@ -2204,9 +2335,9 @@ private void addNamedStoredProcedureQueryIfNeeded(NamedStoredProcedureQuery anno private NamedNativeQueries getNamedNativeQueries(Element tree, XMLContext.Default defaults) { List queries = (List) buildNamedQueries( tree, true, defaults ); if ( defaults.canUseJavaAnnotations() ) { - NamedNativeQuery annotation = getJavaAnnotation( NamedNativeQuery.class ); + NamedNativeQuery annotation = getPhysicalAnnotation( NamedNativeQuery.class ); addNamedNativeQueryIfNeeded( annotation, queries ); - NamedNativeQueries annotations = getJavaAnnotation( NamedNativeQueries.class ); + NamedNativeQueries annotations = getPhysicalAnnotation( NamedNativeQueries.class ); if ( annotations != null ) { for ( NamedNativeQuery current : annotations.value() ) { addNamedNativeQueryIfNeeded( current, queries ); @@ -2305,8 +2436,8 @@ private TableGenerator getTableGenerator(Element tree, XMLContext.Default defaul if ( element != null ) { return buildTableGeneratorAnnotation( element, defaults ); } - else if ( defaults.canUseJavaAnnotations() && isJavaAnnotationPresent( TableGenerator.class ) ) { - TableGenerator tableAnn = getJavaAnnotation( TableGenerator.class ); + else if ( defaults.canUseJavaAnnotations() && isPhysicalAnnotationPresent( TableGenerator.class ) ) { + TableGenerator tableAnn = getPhysicalAnnotation( TableGenerator.class ); if ( StringHelper.isNotEmpty( defaults.getSchema() ) || StringHelper.isNotEmpty( defaults.getCatalog() ) ) { AnnotationDescriptor annotation = new AnnotationDescriptor( TableGenerator.class ); @@ -2368,7 +2499,7 @@ private SequenceGenerator getSequenceGenerator(Element tree, XMLContext.Default return buildSequenceGeneratorAnnotation( element ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( SequenceGenerator.class ); + return getPhysicalAnnotation( SequenceGenerator.class ); } else { return null; @@ -2418,7 +2549,7 @@ else if ( "INTEGER".equals( value ) ) { return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( DiscriminatorColumn.class ); + return getPhysicalAnnotation( DiscriminatorColumn.class ); } else { return null; @@ -2433,7 +2564,7 @@ private DiscriminatorValue getDiscriminatorValue(Element tree, XMLContext.Defaul return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( DiscriminatorValue.class ); + return getPhysicalAnnotation( DiscriminatorValue.class ); } else { return null; @@ -2467,7 +2598,7 @@ else if ( "TABLE_PER_CLASS".equals( value ) ) { return AnnotationFactory.create( ad ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( Inheritance.class ); + return getPhysicalAnnotation( Inheritance.class ); } else { return null; @@ -2498,7 +2629,7 @@ private IdClass getIdClass(Element tree, XMLContext.Default defaults) { } } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( IdClass.class ); + return getPhysicalAnnotation( IdClass.class ); } else { return null; @@ -2515,12 +2646,12 @@ private PrimaryKeyJoinColumns getPrimaryKeyJoinColumns(Element element, XMLConte PrimaryKeyJoinColumn[] columns = buildPrimaryKeyJoinColumns( element ); if ( mergeWithAnnotations ) { if ( columns.length == 0 && defaults.canUseJavaAnnotations() ) { - PrimaryKeyJoinColumn annotation = getJavaAnnotation( PrimaryKeyJoinColumn.class ); + PrimaryKeyJoinColumn annotation = getPhysicalAnnotation( PrimaryKeyJoinColumn.class ); if ( annotation != null ) { columns = new PrimaryKeyJoinColumn[] { annotation }; } else { - PrimaryKeyJoinColumns annotations = getJavaAnnotation( PrimaryKeyJoinColumns.class ); + PrimaryKeyJoinColumns annotations = getPhysicalAnnotation( PrimaryKeyJoinColumns.class ); columns = annotations != null ? annotations.value() : columns; } } @@ -2537,7 +2668,7 @@ private PrimaryKeyJoinColumns getPrimaryKeyJoinColumns(Element element, XMLConte private Entity getEntity(Element tree, XMLContext.Default defaults) { if ( tree == null ) { - return defaults.canUseJavaAnnotations() ? getJavaAnnotation( Entity.class ) : null; + return defaults.canUseJavaAnnotations() ? getPhysicalAnnotation( Entity.class ) : null; } else { if ( "entity".equals( tree.getName() ) ) { @@ -2545,7 +2676,7 @@ private Entity getEntity(Element tree, XMLContext.Default defaults) { copyStringAttribute( entity, tree, "name", false ); if ( defaults.canUseJavaAnnotations() && StringHelper.isEmpty( (String) entity.valueOf( "name" ) ) ) { - Entity javaAnn = getJavaAnnotation( Entity.class ); + Entity javaAnn = getPhysicalAnnotation( Entity.class ); if ( javaAnn != null ) { entity.setValue( "name", javaAnn.name() ); } @@ -2560,7 +2691,7 @@ private Entity getEntity(Element tree, XMLContext.Default defaults) { private MappedSuperclass getMappedSuperclass(Element tree, XMLContext.Default defaults) { if ( tree == null ) { - return defaults.canUseJavaAnnotations() ? getJavaAnnotation( MappedSuperclass.class ) : null; + return defaults.canUseJavaAnnotations() ? getPhysicalAnnotation( MappedSuperclass.class ) : null; } else { if ( "mapped-superclass".equals( tree.getName() ) ) { @@ -2575,7 +2706,7 @@ private MappedSuperclass getMappedSuperclass(Element tree, XMLContext.Default de private Embeddable getEmbeddable(Element tree, XMLContext.Default defaults) { if ( tree == null ) { - return defaults.canUseJavaAnnotations() ? getJavaAnnotation( Embeddable.class ) : null; + return defaults.canUseJavaAnnotations() ? getPhysicalAnnotation( Embeddable.class ) : null; } else { if ( "embeddable".equals( tree.getName() ) ) { @@ -2596,7 +2727,7 @@ private Table getTable(Element tree, XMLContext.Default defaults) { || StringHelper.isNotEmpty( defaults.getSchema() ) ) { AnnotationDescriptor annotation = new AnnotationDescriptor( Table.class ); if ( defaults.canUseJavaAnnotations() ) { - Table table = getJavaAnnotation( Table.class ); + Table table = getPhysicalAnnotation( Table.class ); if ( table != null ) { annotation.setValue( "name", table.name() ); annotation.setValue( "schema", table.schema() ); @@ -2616,7 +2747,7 @@ private Table getTable(Element tree, XMLContext.Default defaults) { return AnnotationFactory.create( annotation ); } else if ( defaults.canUseJavaAnnotations() ) { - return getJavaAnnotation( Table.class ); + return getPhysicalAnnotation( Table.class ); } else { return null; @@ -2670,9 +2801,9 @@ private SecondaryTables getSecondaryTables(Element tree, XMLContext.Default defa * since there would be no way to "remove" a secondary table */ if ( secondaryTables.size() == 0 && defaults.canUseJavaAnnotations() ) { - SecondaryTable secTableAnn = getJavaAnnotation( SecondaryTable.class ); + SecondaryTable secTableAnn = getPhysicalAnnotation( SecondaryTable.class ); overridesDefaultInSecondaryTable( secTableAnn, defaults, secondaryTables ); - SecondaryTables secTablesAnn = getJavaAnnotation( SecondaryTables.class ); + SecondaryTables secTablesAnn = getPhysicalAnnotation( SecondaryTables.class ); if ( secTablesAnn != null ) { for ( SecondaryTable table : secTablesAnn.value() ) { overridesDefaultInSecondaryTable( table, defaults, secondaryTables ); @@ -2832,15 +2963,15 @@ private static void copyBooleanAttribute(AnnotationDescriptor descriptor, Elemen } } - private T getJavaAnnotation(Class annotationType) { + private T getPhysicalAnnotation(Class annotationType) { return element.getAnnotation( annotationType ); } - private boolean isJavaAnnotationPresent(Class annotationType) { + private boolean isPhysicalAnnotationPresent(Class annotationType) { return element.isAnnotationPresent( annotationType ); } - private Annotation[] getJavaAnnotations() { + private Annotation[] getPhysicalAnnotations() { return element.getAnnotations(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/PersistentAttributeFilter.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/PersistentAttributeFilter.java new file mode 100644 index 000000000000..08269637b89a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/PersistentAttributeFilter.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.cfg.annotations.reflection; + +import org.hibernate.annotations.common.reflection.Filter; + +/** + * @author Emmanuel Bernard + * @author Steve Ebersole + */ +public class PersistentAttributeFilter implements Filter { + /** + * Singleton access + */ + public static final PersistentAttributeFilter INSTANCE = new PersistentAttributeFilter(); + + @Override + public boolean returnStatic() { + return false; + } + + @Override + public boolean returnTransient() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java index 2e275fbfb850..5247d8269ebe 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java @@ -21,9 +21,6 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ - -// $Id$ - package org.hibernate.cfg.annotations.reflection; import java.io.Serializable; @@ -37,21 +34,23 @@ import org.hibernate.AnnotationException; import org.hibernate.cfg.AttributeConverterDefinition; import org.hibernate.cfg.Configuration; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; -import org.jboss.logging.Logger; - import org.dom4j.Document; import org.dom4j.Element; /** + * A helper for consuming orm.xml mappings. + * * @author Emmanuel Bernard * @author Brett Meyer */ public class XMLContext implements Serializable { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, XMLContext.class.getName()); + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( XMLContext.class ); + private Default globalDefaults; private Map classOverriding = new HashMap(); private Map defaultsOverriding = new HashMap(); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/package-info.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/package-info.java new file mode 100644 index 000000000000..496cd3d13a2b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/reflection/package-info.java @@ -0,0 +1,29 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +/** + * Defines the capability to merge mapping information from both annotations and orm.xml sources into a unified set of + * metadata in the Hibernate commons-annotations model. + */ +package org.hibernate.cfg.annotations.reflection; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ActivationContext.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ActivationContext.java index b80054e95f90..87334030c1f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ActivationContext.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ActivationContext.java @@ -23,10 +23,11 @@ */ package org.hibernate.cfg.beanvalidation; +import java.util.Map; import java.util.Set; -import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** @@ -48,11 +49,18 @@ public interface ActivationContext { public Set getValidationModes(); /** - * Access the Configuration + * Access the Metadata object (processed mapping information) * - * @return The Hibernate Configuration object + * @return The Hibernate Metadata object */ - public Configuration getConfiguration(); + public MetadataImplementor getMetadata(); + + /** + * Access to all settings + * + * @return The settings + */ + public Map getSettings(); /** * Access the SessionFactory being built to trigger this BV activation diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java index 0b7c04cc2f1f..cde935778667 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java @@ -24,6 +24,7 @@ package org.hibernate.cfg.beanvalidation; import java.util.HashSet; +import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -79,15 +80,14 @@ public BeanValidationEventListener() { * @param factory The {@code ValidatorFactory} to use to create {@code Validator} instance(s) * @param properties Configued properties */ - public BeanValidationEventListener(ValidatorFactory factory, Properties properties) { + public BeanValidationEventListener(ValidatorFactory factory, Map properties) { init( factory, properties ); } - public void initialize(Configuration cfg) { + public void initialize(Map settings) { if ( !initialized ) { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Properties props = cfg.getProperties(); - init( factory, props ); + init( factory, settings ); } } @@ -115,7 +115,7 @@ public boolean onPreDelete(PreDeleteEvent event) { return false; } - private void init(ValidatorFactory factory, Properties properties) { + private void init(ValidatorFactory factory, Map properties) { this.factory = factory; groupsPerOperation = new GroupsPerOperation( properties ); initialized = true; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java index e30cd765c24e..9df5ec55491c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java @@ -25,15 +25,17 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Configuration; +import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.jboss.logging.Logger; @@ -69,9 +71,7 @@ public static void validateFactory(Object object) { final Class activatorClass = BeanValidationIntegrator.class.getClassLoader().loadClass( ACTIVATOR_CLASS_NAME ); try { final Method validateMethod = activatorClass.getMethod( VALIDATE_SUPPLIED_FACTORY_METHOD_NAME, Object.class ); - if ( ! validateMethod.isAccessible() ) { - validateMethod.setAccessible( true ); - } + validateMethod.setAccessible( true ); try { validateMethod.invoke( null, object ); } @@ -105,8 +105,51 @@ public void integrate( final Configuration configuration, final SessionFactoryImplementor sessionFactory, final SessionFactoryServiceRegistry serviceRegistry) { + throw new HibernateException( "UGH!" ); + } + + private boolean isBeanValidationApiAvailable(ClassLoaderService classLoaderService) { + try { + classLoaderService.classForName( BV_CHECK_CLASS ); + return true; + } + catch (Exception e) { + return false; + } + } + + /** + * Used to validate the case when the Bean Validation API is not available. + * + * @param modes The requested validation modes. + */ + private void validateMissingBeanValidationApi(Set modes) { + if ( modes.contains( ValidationMode.CALLBACK ) ) { + throw new IntegrationException( "Bean Validation API was not available, but 'callback' validation was requested" ); + } + if ( modes.contains( ValidationMode.DDL ) ) { + throw new IntegrationException( "Bean Validation API was not available, but 'ddl' validation was requested" ); + } + } + + private Class loadTypeSafeActivatorClass(ClassLoaderService classLoaderService) { + try { + return classLoaderService.classForName( ACTIVATOR_CLASS_NAME ); + } + catch (Exception e) { + throw new HibernateException( "Unable to load TypeSafeActivator class", e ); + } + } + + @Override + public void integrate( + final MetadataImplementor metadata, + final SessionFactoryImplementor sessionFactory, + final SessionFactoryServiceRegistry serviceRegistry ) { + final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); + // IMPL NOTE : see the comments on ActivationContext.getValidationModes() as to why this is multi-valued... - final Set modes = ValidationMode.getModes( configuration.getProperties().get( MODE_PROPERTY ) ); + final Set modes = ValidationMode.getModes( configurationService.getSettings().get( MODE_PROPERTY ) ); if ( modes.size() > 1 ) { LOG.multipleValidationModes( ValidationMode.loggable( modes ) ); } @@ -131,8 +174,13 @@ public Set getValidationModes() { } @Override - public Configuration getConfiguration() { - return configuration; + public MetadataImplementor getMetadata() { + return metadata; + } + + @Override + public Map getSettings() { + return configurationService.getSettings(); } @Override @@ -170,48 +218,6 @@ public SessionFactoryServiceRegistry getServiceRegistry() { } } - private boolean isBeanValidationApiAvailable(ClassLoaderService classLoaderService) { - try { - classLoaderService.classForName( BV_CHECK_CLASS ); - return true; - } - catch (Exception e) { - return false; - } - } - - /** - * Used to validate the case when the Bean Validation API is not available. - * - * @param modes The requested validation modes. - */ - private void validateMissingBeanValidationApi(Set modes) { - if ( modes.contains( ValidationMode.CALLBACK ) ) { - throw new IntegrationException( "Bean Validation API was not available, but 'callback' validation was requested" ); - } - if ( modes.contains( ValidationMode.DDL ) ) { - throw new IntegrationException( "Bean Validation API was not available, but 'ddl' validation was requested" ); - } - } - - private Class loadTypeSafeActivatorClass(ClassLoaderService classLoaderService) { - try { - return classLoaderService.classForName( ACTIVATOR_CLASS_NAME ); - } - catch (Exception e) { - throw new HibernateException( "Unable to load TypeSafeActivator class", e ); - } - } - - - - @Override - public void integrate( - MetadataImplementor metadata, - SessionFactoryImplementor sessionFactory, - SessionFactoryServiceRegistry serviceRegistry ) { - } - @Override public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { // nothing to do here afaik diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java index 12a6b5acdcd2..0eb5360721fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java @@ -27,7 +27,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import javax.validation.groups.Default; import org.hibernate.HibernateException; @@ -45,14 +44,14 @@ public class GroupsPerOperation { private Map[]> groupsPerOperation = new HashMap[]>(4); - public GroupsPerOperation(Properties properties) { + public GroupsPerOperation(Map properties) { setGroupsForOperation( Operation.INSERT, properties ); setGroupsForOperation( Operation.UPDATE, properties ); setGroupsForOperation( Operation.DELETE, properties ); setGroupsForOperation( Operation.DDL, properties ); } - private void setGroupsForOperation(Operation operation, Properties properties) { + private void setGroupsForOperation(Operation operation, Map properties) { Object property = properties.get( operation.getGroupPropertyName() ); Class[] groups; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java index 92fa1841e790..7917f990801c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java @@ -24,12 +24,10 @@ package org.hibernate.cfg.beanvalidation; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; +import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import javax.validation.Validation; @@ -43,25 +41,28 @@ import javax.validation.metadata.ConstraintDescriptor; import javax.validation.metadata.PropertyDescriptor; -import org.hibernate.AssertionFailure; -import org.hibernate.MappingException; +import org.hibernate.EntityMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.spi.EventType; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.SingleTableSubclass; - -import org.jboss.logging.Logger; +import org.hibernate.metamodel.spi.binding.AbstractSingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.AbstractSingularAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; /** * @author Emmanuel Bernard @@ -69,19 +70,16 @@ * @author Steve Ebersole */ class TypeSafeActivator { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TypeSafeActivator.class.getName()); - - private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory"; + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( TypeSafeActivator.class ); /** * Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory. * * @param object The supplied ValidatorFactory instance. */ - @SuppressWarnings( {"UnusedDeclaration"}) + @SuppressWarnings({ "UnusedDeclaration" }) public static void validateSuppliedFactory(Object object) { - if ( ! ValidatorFactory.class.isInstance( object ) ) { + if ( !ValidatorFactory.class.isInstance( object ) ) { throw new IntegrationException( "Given object was not an instance of " + ValidatorFactory.class.getName() + "[" + object.getClass().getName() + "]" @@ -91,17 +89,23 @@ public static void validateSuppliedFactory(Object object) { @SuppressWarnings("UnusedDeclaration") public static void activate(ActivationContext activationContext) { - final Properties properties = activationContext.getConfiguration().getProperties(); + final Map properties = activationContext.getSettings(); final ValidatorFactory factory; try { - factory = getValidatorFactory( properties ); + factory = getValidatorFactory( activationContext ); } - catch (IntegrationException e) { + catch ( IntegrationException e ) { if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) { - throw new IntegrationException( "Bean Validation provider was not available, but 'callback' validation was requested", e ); + throw new IntegrationException( + "Bean Validation provider was not available, but 'callback' validation was requested", + e + ); } if ( activationContext.getValidationModes().contains( ValidationMode.DDL ) ) { - throw new IntegrationException( "Bean Validation provider was not available, but 'ddl' validation was requested", e ); + throw new IntegrationException( + "Bean Validation provider was not available, but 'ddl' validation was requested", + e + ); } LOG.debug( "Unable to acquire Bean Validation ValidatorFactory, skipping activation" ); @@ -113,22 +117,22 @@ public static void activate(ActivationContext activationContext) { applyCallbackListeners( factory, activationContext ); } - @SuppressWarnings( {"UnusedDeclaration"}) + @SuppressWarnings({ "UnusedDeclaration" }) public static void applyCallbackListeners(ValidatorFactory validatorFactory, ActivationContext activationContext) { final Set modes = activationContext.getValidationModes(); - if ( ! ( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) { + if ( !( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) { return; } // de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly // asks for it - if ( activationContext.getConfiguration().getProperty( Environment.CHECK_NULLABILITY ) == null ) { + if ( activationContext.getSettings().get( Environment.CHECK_NULLABILITY ) == null ) { activationContext.getSessionFactory().getSettings().setCheckNullability( false ); } final BeanValidationEventListener listener = new BeanValidationEventListener( validatorFactory, - activationContext.getConfiguration().getProperties() + activationContext.getSettings() ); final EventListenerRegistry listenerRegistry = activationContext.getServiceRegistry() @@ -140,57 +144,40 @@ public static void applyCallbackListeners(ValidatorFactory validatorFactory, Act listenerRegistry.appendListeners( EventType.PRE_UPDATE, listener ); listenerRegistry.appendListeners( EventType.PRE_DELETE, listener ); - listener.initialize( activationContext.getConfiguration() ); + listener.initialize( activationContext.getSettings() ); } - @SuppressWarnings({"unchecked", "UnusedParameters"}) private static void applyRelationalConstraints(ValidatorFactory factory, ActivationContext activationContext) { - final Properties properties = activationContext.getConfiguration().getProperties(); - if ( ! ConfigurationHelper.getBoolean( BeanValidationIntegrator.APPLY_CONSTRAINTS, properties, true ) ){ + final Map properties = activationContext.getSettings(); + if ( !ConfigurationHelper.getBoolean( BeanValidationIntegrator.APPLY_CONSTRAINTS, properties, true ) ) { LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" ); return; } final Set modes = activationContext.getValidationModes(); - if ( ! ( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) { + if ( !( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) { return; } - applyRelationalConstraints( - factory, - activationContext.getConfiguration().createMappings().getClasses().values(), - properties, - activationContext.getServiceRegistry().getService( JdbcServices.class ).getDialect() - ); - } + final Dialect dialect = activationContext.getServiceRegistry().getService( JdbcServices.class ).getDialect(); - @SuppressWarnings( {"UnusedDeclaration"}) - public static void applyRelationalConstraints( - ValidatorFactory factory, - Collection persistentClasses, - Properties properties, - Dialect dialect) { Class[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL ); Set> groups = new HashSet>( Arrays.asList( groupsArray ) ); - for ( PersistentClass persistentClass : persistentClasses ) { - final String className = persistentClass.getClassName(); + for ( EntityBinding entityBinding : activationContext.getMetadata().getEntityBindings() ) { + final String className = entityBinding.getEntity().getDescriptor().getName().toString(); - if ( className == null || className.length() == 0 ) { + if ( entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) { continue; } - Class clazz; - try { - clazz = ReflectHelper.classForName( className, TypeSafeActivator.class ); - } - catch ( ClassNotFoundException e ) { - throw new AssertionFailure( "Entity class not found", e ); - } + final ClassLoaderService classLoaderService = activationContext.getServiceRegistry() + .getService( ClassLoaderService.class ); + final Class clazz = classLoaderService.classForName( className ); try { - applyDDL( "", persistentClass, clazz, factory, groups, true, dialect ); + applyDDL( "", entityBinding, clazz, factory, groups, true, dialect, classLoaderService ); } - catch (Exception e) { + catch ( Exception e ) { LOG.unableToApplyConstraints( className, e ); } } @@ -198,47 +185,64 @@ public static void applyRelationalConstraints( private static void applyDDL( String prefix, - PersistentClass persistentClass, + EntityBinding entityBinding, Class clazz, ValidatorFactory factory, Set> groups, boolean activateNotNull, - Dialect dialect) { + Dialect dialect, ClassLoaderService classLoaderService) { final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass( clazz ); - //no bean level constraints can be applied, go to the properties - for ( PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties() ) { - Property property = findPropertyByName( persistentClass, prefix + propertyDesc.getPropertyName() ); + // no bean level constraints can be applied, just iterate the properties + for ( PropertyDescriptor propertyDescriptor : descriptor.getConstrainedProperties() ) { + AttributeBinding attributeBinding = findPropertyByName( + entityBinding, + prefix + propertyDescriptor.getPropertyName() + ); + if ( attributeBinding == null ) { + continue; + } + boolean hasNotNull; - if ( property != null ) { - hasNotNull = applyConstraints( - propertyDesc.getConstraintDescriptors(), property, propertyDesc, groups, activateNotNull, dialect - ); - if ( property.isComposite() && propertyDesc.isCascaded() ) { - Class componentClass = ( (Component) property.getValue() ).getComponentClass(); - - /* - * we can apply not null if the upper component let's us activate not null - * and if the property is not null. - * Otherwise, all sub columns should be left nullable - */ - final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull; - applyDDL( - prefix + propertyDesc.getPropertyName() + ".", - persistentClass, componentClass, factory, groups, - canSetNotNullOnColumns, - dialect - ); + hasNotNull = applyConstraints( + propertyDescriptor.getConstraintDescriptors(), + attributeBinding, + propertyDescriptor, + groups, + activateNotNull, + dialect + ); + + if ( propertyDescriptor.isCascaded() ) { + // if it is a composite, visit its attributes + final Attribute attribute = attributeBinding.getAttribute(); + if ( attribute.isSingular() ) { + final SingularAttribute singularAttribute = (SingularAttribute) attribute; + if ( singularAttribute.getSingularAttributeType().isAggregate() ) { + final Class componentClass = classLoaderService.classForName( + singularAttribute.getSingularAttributeType().getDescriptor().getName().toString() + ); + final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull; + applyDDL( + prefix + propertyDescriptor.getPropertyName() + ".", + entityBinding, + componentClass, + factory, + groups, + canSetNotNullOnColumns, + dialect, + classLoaderService + ); + } } - //FIXME add collection of components } } } private static boolean applyConstraints( Set> constraintDescriptors, - Property property, - PropertyDescriptor propertyDesc, + AttributeBinding attributeBinding, + PropertyDescriptor propertyDescriptor, Set> groups, boolean canApplyNotNull, Dialect dialect) { @@ -249,219 +253,233 @@ private static boolean applyConstraints( } if ( canApplyNotNull ) { - hasNotNull = hasNotNull || applyNotNull( property, descriptor ); + hasNotNull = hasNotNull || applyNotNull( attributeBinding, descriptor ); } // apply bean validation specific constraints - applyDigits( property, descriptor ); - applySize( property, descriptor, propertyDesc ); - applyMin( property, descriptor, dialect ); - applyMax( property, descriptor, dialect ); + applyDigits( attributeBinding, descriptor ); + applySize( attributeBinding, descriptor, propertyDescriptor ); + applyMin( attributeBinding, descriptor, dialect ); + applyMax( attributeBinding, descriptor, dialect ); // apply hibernate validator specific constraints - we cannot import any HV specific classes though! // no need to check explicitly for @Range. @Range is a composed constraint using @Min and @Max which // will be taken care later - applyLength( property, descriptor, propertyDesc ); + applyLength( attributeBinding, descriptor ); // pass an empty set as composing constraints inherit the main constraint and thus are matching already hasNotNull = hasNotNull || applyConstraints( descriptor.getComposingConstraints(), - property, propertyDesc, null, + attributeBinding, propertyDescriptor, null, canApplyNotNull, - dialect + dialect ); } return hasNotNull; } - private static void applyMin(Property property, ConstraintDescriptor descriptor, Dialect dialect) { - if ( Min.class.equals( descriptor.getAnnotation().annotationType() ) ) { - @SuppressWarnings("unchecked") - ConstraintDescriptor minConstraint = (ConstraintDescriptor) descriptor; - long min = minConstraint.getAnnotation().value(); - - Column col = (Column) property.getColumnIterator().next(); - String checkConstraint = col.getQuotedName(dialect) + ">=" + min; - applySQLCheck( col, checkConstraint ); + private static void applySQLCheck(Column column, String checkConstraint) { + String existingCheck = column.getCheckCondition(); + // need to check whether the new check is already part of the existing check, because applyDDL can be called + // multiple times + if ( StringHelper.isNotEmpty( existingCheck ) && !existingCheck.contains( checkConstraint ) ) { + checkConstraint = column.getCheckCondition() + " AND " + checkConstraint; } + column.setCheckCondition( checkConstraint ); } - private static void applyMax(Property property, ConstraintDescriptor descriptor, Dialect dialect) { - if ( Max.class.equals( descriptor.getAnnotation().annotationType() ) ) { - @SuppressWarnings("unchecked") - ConstraintDescriptor maxConstraint = (ConstraintDescriptor) descriptor; - long max = maxConstraint.getAnnotation().value(); - Column col = (Column) property.getColumnIterator().next(); - String checkConstraint = col.getQuotedName(dialect) + "<=" + max; - applySQLCheck( col, checkConstraint ); + private static boolean applyNotNull(AttributeBinding attributeBinding, ConstraintDescriptor descriptor) { + if ( !NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) { + return false; } - } - private static void applySQLCheck(Column col, String checkConstraint) { - String existingCheck = col.getCheckConstraint(); - // need to check whether the new check is already part of the existing check, because applyDDL can be called - // multiple times - if ( StringHelper.isNotEmpty( existingCheck ) && !existingCheck.contains( checkConstraint ) ) { - checkConstraint = col.getCheckConstraint() + " AND " + checkConstraint; + if ( InheritanceType.SINGLE_TABLE.equals( + attributeBinding.getContainer() + .seekEntityBinding() + .getHierarchyDetails() + .getInheritanceType() + ) ) { + return false; } - col.setCheckConstraint( checkConstraint ); - } - private static boolean applyNotNull(Property property, ConstraintDescriptor descriptor) { - boolean hasNotNull = false; - if ( NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) { - // single table inheritance should not be forced to null due to shared state - if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) { - //composite should not add not-null on all columns - if ( !property.isComposite() ) { - final Iterator iter = property.getColumnIterator(); - while ( iter.hasNext() ) { - final Selectable selectable = iter.next(); - if ( Column.class.isInstance( selectable ) ) { - Column.class.cast( selectable ).setNullable( false ); - } - else { - LOG.debugf( - "@NotNull was applied to attribute [%s] which is defined (at least partially) " + - "by formula(s); formula portions will be skipped", - property.getName() - ); - } - } - } + List relationalValueBindings = Collections.emptyList(); + if ( attributeBinding instanceof BasicAttributeBinding ) { + BasicAttributeBinding basicBinding = (BasicAttributeBinding) attributeBinding; + relationalValueBindings = basicBinding.getRelationalValueBindings(); + } + + if ( attributeBinding instanceof AbstractSingularAssociationAttributeBinding ) { + AbstractSingularAssociationAttributeBinding singularAttributeBinding = (AbstractSingularAssociationAttributeBinding) attributeBinding; + relationalValueBindings = singularAttributeBinding.getRelationalValueBindings(); + } + + if ( attributeBinding instanceof AbstractSingularAttributeBinding ) { + AbstractSingularAttributeBinding singularAttributeBinding = (AbstractSingularAttributeBinding) attributeBinding; + relationalValueBindings = singularAttributeBinding.getRelationalValueBindings(); + } + + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.getValue() instanceof Column ) { + Column column = (Column) relationalValueBinding.getValue(); + column.setNullable( false ); } - hasNotNull = true; } - return hasNotNull; + + return true; } - private static void applyDigits(Property property, ConstraintDescriptor descriptor) { - if ( Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) { - @SuppressWarnings("unchecked") - ConstraintDescriptor digitsConstraint = (ConstraintDescriptor) descriptor; - int integerDigits = digitsConstraint.getAnnotation().integer(); - int fractionalDigits = digitsConstraint.getAnnotation().fraction(); - Column col = (Column) property.getColumnIterator().next(); - col.setPrecision( integerDigits + fractionalDigits ); - col.setScale( fractionalDigits ); + private static void applyMin(AttributeBinding attributeBinding, ConstraintDescriptor descriptor, Dialect dialect) { + if ( !Min.class.equals( descriptor.getAnnotation().annotationType() ) ) { + return; } + + long min = (Long) descriptor.getAttributes().get( "value" ); + Column column = getSingleColumn( attributeBinding ); + String checkConstraint = column.getColumnName().getText( dialect ) + ">=" + min; + applySQLCheck( column, checkConstraint ); } - private static void applySize(Property property, ConstraintDescriptor descriptor, PropertyDescriptor propertyDescriptor) { - if ( Size.class.equals( descriptor.getAnnotation().annotationType() ) - && String.class.equals( propertyDescriptor.getElementClass() ) ) { - @SuppressWarnings("unchecked") - ConstraintDescriptor sizeConstraint = (ConstraintDescriptor) descriptor; - int max = sizeConstraint.getAnnotation().max(); - Column col = (Column) property.getColumnIterator().next(); - if ( max < Integer.MAX_VALUE ) { - col.setLength( max ); - } + private static void applyMax(AttributeBinding attributeBinding, ConstraintDescriptor descriptor, Dialect dialect) { + if ( !Max.class.equals( descriptor.getAnnotation().annotationType() ) ) { + return; } + + long max = (Long) descriptor.getAttributes().get( "value" ); + Column column = getSingleColumn( attributeBinding ); + String checkConstraint = column.getColumnName().getText( dialect ) + "<=" + max; + applySQLCheck( column, checkConstraint ); } - private static void applyLength(Property property, ConstraintDescriptor descriptor, PropertyDescriptor propertyDescriptor) { - if ( "org.hibernate.validator.constraints.Length".equals( + private static void applySize(AttributeBinding attributeBinding, ConstraintDescriptor descriptor, PropertyDescriptor propertyDescriptor) { + if ( !( Size.class.equals( descriptor.getAnnotation().annotationType() ) + && String.class.equals( propertyDescriptor.getElementClass() ) ) ) { + return; + } + + int max = (Integer) descriptor.getAttributes().get( "max" ); + Column column = getSingleColumn( attributeBinding ); + if ( max < Integer.MAX_VALUE ) { + column.setSize( org.hibernate.metamodel.spi.relational.Size.length( max ) ); + } + } + + private static void applyLength(AttributeBinding attributeBinding, ConstraintDescriptor descriptor) { + if ( !"org.hibernate.validator.constraints.Length".equals( descriptor.getAnnotation().annotationType().getName() - ) - && String.class.equals( propertyDescriptor.getElementClass() ) ) { - @SuppressWarnings("unchecked") - int max = (Integer) descriptor.getAttributes().get( "max" ); - Column col = (Column) property.getColumnIterator().next(); - if ( max < Integer.MAX_VALUE ) { - col.setLength( max ); - } + ) ) { + return; + } + + int max = (Integer) descriptor.getAttributes().get( "max" ); + Column column = getSingleColumn( attributeBinding ); + if ( max < Integer.MAX_VALUE ) { + column.setSize( org.hibernate.metamodel.spi.relational.Size.length( max ) ); + } + } + + private static void applyDigits(AttributeBinding attributeBinding, ConstraintDescriptor descriptor) { + if ( !Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) { + return; } + @SuppressWarnings("unchecked") + ConstraintDescriptor digitsConstraint = (ConstraintDescriptor) descriptor; + int integerDigits = digitsConstraint.getAnnotation().integer(); + int fractionalDigits = digitsConstraint.getAnnotation().fraction(); + + Column column = getSingleColumn( attributeBinding ); + org.hibernate.metamodel.spi.relational.Size size = org.hibernate.metamodel.spi.relational.Size.precision( + integerDigits + fractionalDigits, + fractionalDigits + ); + column.setSize( size ); } /** - * @param associatedClass - * @param propertyName - * @return the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is - * null. If propertyName is null or empty, the IdentifierProperty is returned + * Returns the {@code AttributeBinding} for the attribute/property specified by given path. + * + * @param entityBinding the root entity binding from which to start the search for the property + * @param propertyPath the property path + * + * @return Returns the {@code AttributeBinding} for the attribute/property specified by given path. If + * {@code propertyPath} is {@code null} or empty, the id attribute binding is returned. */ - private static Property findPropertyByName(PersistentClass associatedClass, String propertyName) { - Property property = null; - Property idProperty = associatedClass.getIdentifierProperty(); - String idName = idProperty != null ? idProperty.getName() : null; - try { - if ( propertyName == null - || propertyName.length() == 0 - || propertyName.equals( idName ) ) { - //default to id - property = idProperty; + private static AttributeBinding findPropertyByName(EntityBinding entityBinding, String propertyPath) { + final AttributeBinding idAttributeBinding = entityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding(); + final String idAttributeName = idAttributeBinding == null ? null : idAttributeBinding.getAttribute().getName(); + + if ( propertyPath == null || propertyPath.length() == 0 || propertyPath.equals( idAttributeName ) ) { + //default to id + return idAttributeBinding; + } + + AttributeBinding attributeBinding = null; + StringTokenizer tokenizer = new StringTokenizer( propertyPath, ".", false ); + while ( tokenizer.hasMoreElements() ) { + String element = (String) tokenizer.nextElement(); + if ( attributeBinding == null ) { + attributeBinding = entityBinding.locateAttributeBinding( element ); } else { - if ( propertyName.indexOf( idName + "." ) == 0 ) { - property = idProperty; - propertyName = propertyName.substring( idName.length() + 1 ); - } - StringTokenizer st = new StringTokenizer( propertyName, ".", false ); - while ( st.hasMoreElements() ) { - String element = (String) st.nextElement(); - if ( property == null ) { - property = associatedClass.getProperty( element ); - } - else { - if ( !property.isComposite() ) { - return null; - } - property = ( (Component) property.getValue() ).getProperty( element ); - } + if ( !isComposite( attributeBinding ) ) { + return null; } + EmbeddedAttributeBinding embeddedAttributeBinding = (EmbeddedAttributeBinding) attributeBinding; + attributeBinding = embeddedAttributeBinding.getEmbeddableBinding().locateAttributeBinding( element ); } } - catch ( MappingException e ) { + return attributeBinding; + } + + private static boolean isComposite(AttributeBinding property) { + if ( property.getAttribute().isSingular() ) { + final SingularAttribute singularAttribute = (SingularAttribute) property.getAttribute(); + return singularAttribute.getSingularAttributeType().isAggregate(); + } + + return false; + } + + private static ValidatorFactory getValidatorFactory(ActivationContext activationContext) { + // first look for an explicitly passed ValidatorFactory + final Object reference = activationContext.getSessionFactory() + .getSessionFactoryOptions() + .getValidatorFactoryReference(); + if ( reference != null ) { try { - //if we do not find it try to check the identifier mapper - if ( associatedClass.getIdentifierMapper() == null ) { - return null; - } - StringTokenizer st = new StringTokenizer( propertyName, ".", false ); - while ( st.hasMoreElements() ) { - String element = (String) st.nextElement(); - if ( property == null ) { - property = associatedClass.getIdentifierMapper().getProperty( element ); - } - else { - if ( !property.isComposite() ) { - return null; - } - property = ( (Component) property.getValue() ).getProperty( element ); - } - } + return ValidatorFactory.class.cast( reference ); } - catch ( MappingException ee ) { - return null; + catch ( ClassCastException e ) { + throw new IntegrationException( + "Passed ValidatorFactory was not of correct type; expected " + ValidatorFactory.class.getName() + + ", but found " + reference.getClass().getName() + ); } } - return property; + + try { + return Validation.buildDefaultValidatorFactory(); + } + catch ( Exception e ) { + throw new IntegrationException( "Unable to build the default ValidatorFactory", e ); + } } - private static ValidatorFactory getValidatorFactory(Map properties) { - ValidatorFactory factory = null; - if ( properties != null ) { - Object unsafeProperty = properties.get( FACTORY_PROPERTY ); - if ( unsafeProperty != null ) { - try { - factory = ValidatorFactory.class.cast( unsafeProperty ); - } - catch ( ClassCastException e ) { - throw new IntegrationException( - "Property " + FACTORY_PROPERTY - + " should contain an object of type " + ValidatorFactory.class.getName() - ); - } - } + private static Column getSingleColumn(AttributeBinding attributeBinding) { + BasicAttributeBinding basicBinding = (BasicAttributeBinding) attributeBinding; + List relationalValueBindings = basicBinding.getRelationalValueBindings(); + if ( relationalValueBindings.size() > 1 ) { + throw new IntegrationException( + "Unexpected number of relational columns for attribute " + + attributeBinding.getAttribute().getName() + ); } - if ( factory == null ) { - try { - factory = Validation.buildDefaultValidatorFactory(); - } - catch ( Exception e ) { - throw new IntegrationException( "Unable to build the default ValidatorFactory", e ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.getValue() instanceof Column ) { + return (Column) relationalValueBinding.getValue(); } } - return factory; + return null; } } diff --git a/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java b/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java index da873148abd7..2bb52f27bc7d 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java @@ -31,9 +31,11 @@ import java.util.Iterator; import java.util.List; import java.util.ListIterator; + import javax.naming.NamingException; import org.hibernate.AssertionFailure; +import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.LazyInitializationException; import org.hibernate.Session; @@ -52,8 +54,8 @@ import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.pretty.MessageHelper; +import org.hibernate.type.ComponentType; import org.hibernate.type.Type; - import org.jboss.logging.Logger; /** @@ -80,7 +82,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers private Serializable storedSnapshot; private String sessionFactoryUuid; - private boolean specjLazyLoad; + private boolean allowLoadOutsideTransaction; /** * Not called by Hibernate, but used by non-JDK serialization, @@ -204,7 +206,7 @@ private T withTemporarySessionIfNeeded(LazyInitializationWork lazyInitial boolean isJTA = false; if ( session == null ) { - if ( specjLazyLoad ) { + if ( allowLoadOutsideTransaction ) { session = openTemporarySessionForLoading(); isTempSession = true; } @@ -213,7 +215,7 @@ private T withTemporarySessionIfNeeded(LazyInitializationWork lazyInitial } } else if ( !session.isOpen() ) { - if ( specjLazyLoad ) { + if ( allowLoadOutsideTransaction ) { originalSession = session; session = openTemporarySessionForLoading(); isTempSession = true; @@ -223,7 +225,7 @@ else if ( !session.isOpen() ) { } } else if ( !session.isConnected() ) { - if ( specjLazyLoad ) { + if ( allowLoadOutsideTransaction ) { originalSession = session; session = openTemporarySessionForLoading(); isTempSession = true; @@ -234,8 +236,6 @@ else if ( !session.isConnected() ) { } if ( isTempSession ) { - // TODO: On the next major release, add an - // 'isJTA' or 'getTransactionFactory' method to Session. isJTA = session.getTransactionCoordinator() .getTransactionContext().getTransactionEnvironment() .getTransactionFactory() @@ -249,7 +249,7 @@ else if ( !session.isConnected() ) { // multiple transactions. ( (Session) session ).beginTransaction(); } - + session.getPersistenceContext().addUninitializedDetachedCollection( session.getFactory().getCollectionPersister( getRole() ), this @@ -283,7 +283,10 @@ private SessionImplementor openTemporarySessionForLoading() { final SessionFactoryImplementor sf = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid ); - return (SessionImplementor) sf.openSession(); + final SessionImplementor session = (SessionImplementor) sf.openSession(); + session.getPersistenceContext().setDefaultReadOnly( true ); + session.setFlushMode( FlushMode.MANUAL ); + return session; } protected Boolean readIndexExistence(final Object index) { @@ -592,7 +595,7 @@ public boolean isDirectlyAccessible() { @Override public final boolean unsetSession(SessionImplementor currentSession) { - prepareForPossibleSpecialSpecjInitialization(); + prepareForPossibleLoadingOutsideTransaction(); if ( currentSession == this.session ) { this.session = null; return true; @@ -602,11 +605,11 @@ public final boolean unsetSession(SessionImplementor currentSession) { } } - protected void prepareForPossibleSpecialSpecjInitialization() { + protected void prepareForPossibleLoadingOutsideTransaction() { if ( session != null ) { - specjLazyLoad = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled(); + allowLoadOutsideTransaction = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled(); - if ( specjLazyLoad && sessionFactoryUuid == null ) { + if ( allowLoadOutsideTransaction && sessionFactoryUuid == null ) { try { sessionFactoryUuid = (String) session.getFactory().getReference().get( "uuid" ).getContent(); } @@ -650,6 +653,18 @@ public final boolean setCurrentSession(SessionImplementor session) throws Hibern @Override public boolean needsRecreate(CollectionPersister persister) { + // Workaround for situations like HHH-7072. If the collection element is a component that consists entirely + // of nullable properties, we currently have to forcefully recreate the entire collection. See the use + // of hasNotNullableColumns in the AbstractCollectionPersister constructor for more info. In order to delete + // row-by-row, that would require SQL like "WHERE ( COL = ? OR ( COL is null AND ? is null ) )", rather than + // the current "WHERE COL = ?" (fails for null for most DBs). Note that + // the param would have to be bound twice. Until we eventually add "parameter bind points" concepts to the + // AST in ORM 5+, handling this type of condition is either extremely difficult or impossible. Forcing + // recreation isn't ideal, but not really any other option in ORM 4. + if (persister.getElementType() instanceof ComponentType) { + ComponentType componentType = (ComponentType) persister.getElementType(); + return !componentType.hasNotNullProperty(); + } return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/criterion/IlikeExpression.java b/hibernate-core/src/main/java/org/hibernate/criterion/IlikeExpression.java index 923890bcafc6..9df38c3a2f22 100644 --- a/hibernate-core/src/main/java/org/hibernate/criterion/IlikeExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/criterion/IlikeExpression.java @@ -28,7 +28,6 @@ import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.engine.spi.TypedValue; /** @@ -60,7 +59,7 @@ public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) { if ( columns.length != 1 ) { throw new HibernateException( "ilike may only be used with single-column properties" ); } - if ( dialect instanceof PostgreSQLDialect || dialect instanceof PostgreSQL81Dialect) { + if ( dialect instanceof PostgreSQL81Dialect) { return columns[0] + " ilike ?"; } else { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java index e55f772894f6..da5943b4476f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -41,9 +41,13 @@ import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; import org.hibernate.engine.jdbc.CharacterStream; import org.hibernate.engine.jdbc.ClobImplementer; import org.hibernate.engine.jdbc.NClobImplementer; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockTimeoutException; @@ -306,11 +310,6 @@ public AbstractHANADialect() { getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" ); } - @Override - public boolean bindLimitParametersInReverseOrder() { - return true; - } - @Override public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() { return new SQLExceptionConversionDelegate() { @@ -430,12 +429,6 @@ public String getForUpdateString(final String aliases, final LockOptions lockOpt return getForUpdateString( lockMode ) + " of " + aliases; } - @Override - public String getLimitString(final String sql, final boolean hasOffset) { - return new StringBuilder( sql.length() + 20 ).append( sql ) - .append( hasOffset ? " limit ? offset ?" : " limit ?" ).toString(); - } - @Override public String getNotExpression(final String expression) { return "not (" + expression + ")"; @@ -604,11 +597,6 @@ public boolean supportsExpectedLobUsagePattern() { return false; } - @Override - public boolean supportsLimit() { - return true; - } - @Override public boolean supportsPooledSequences() { return true; @@ -670,4 +658,26 @@ public String getAddForeignKeyConstraintString(final String constraintName, fina final String referencedTable, final String[] primaryKey, final boolean referencesPrimaryKey) { return super.getAddForeignKeyConstraintString(constraintName, foreignKey, referencedTable, primaryKey, referencesPrimaryKey) + " on update cascade"; } + + @Override + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + return new StringBuilder( sql.length() + 20 ).append( sql ) + .append( hasOffset ? " limit ? offset ?" : " limit ?" ).toString(); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + }; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java index b30013b6262b..5aac285cfcd6 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java @@ -206,7 +206,7 @@ public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map -1 ) { - final String lockHint = appendLockHint( lockMode, alias ); + final String lockHint = appendLockHint( new LockOptions( lockMode ), alias ); buffer.replace( start, end, lockHint ); correction += ( lockHint.length() - alias.length() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java index 747fe4b4e288..c3958d5e5761 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java @@ -46,6 +46,9 @@ import org.hibernate.dialect.lock.PessimisticWriteUpdateLockingStrategy; import org.hibernate.dialect.lock.SelectLockingStrategy; import org.hibernate.dialect.lock.UpdateLockingStrategy; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.TopLimitHandler; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.internal.CacheSQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; @@ -583,53 +586,9 @@ else if ( lockMode.greaterThan( LockMode.READ ) ) { // LIMIT support (ala TOP) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override - @SuppressWarnings("deprecation") - public boolean supportsLimit() { - return true; - } - - @Override - @SuppressWarnings("deprecation") - public boolean supportsLimitOffset() { - return false; - } - - @Override - @SuppressWarnings("deprecation") - public boolean supportsVariableLimit() { - return true; - } - - @Override - @SuppressWarnings("deprecation") - public boolean bindLimitParametersFirst() { - // Does the LIMIT clause come at the start of the SELECT statement, rather than at the end? - return true; - } - - @Override - @SuppressWarnings("deprecation") - public boolean useMaxForLimit() { - // Does the LIMIT clause take a "maximum" row number instead of a total number of returned rows? - return true; - } - - @Override - @SuppressWarnings("deprecation") - public String getLimitString(String sql, boolean hasOffset) { - if ( hasOffset ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - - // This does not support the Cache SQL 'DISTINCT BY (comma-list)' extensions, - // but this extension is not supported through Hibernate anyway. - final int insertionPoint = sql.startsWith( "select distinct" ) ? 15 : 6; - - return new StringBuilder( sql.length() + 8 ) - .append( sql ) - .insert( insertionPoint, " TOP ? " ) - .toString(); - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new TopLimitHandler(sql, selection, true, true); + } // callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2390Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2390Dialect.java index d4fdf523a090..f320ca894878 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2390Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2390Dialect.java @@ -23,6 +23,11 @@ */ package org.hibernate.dialect; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; + /** * An SQL dialect for DB2/390. This class provides support for @@ -42,35 +47,31 @@ public String getIdentitySelectString() { } @Override - public boolean supportsLimit() { - return true; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + if ( LimitHelper.hasFirstRow(selection) ) { + throw new UnsupportedOperationException( "query result offset is not supported" ); + } + return sql + " fetch first ? rows only"; + } - @Override - @SuppressWarnings("deprecation") - public boolean supportsLimitOffset() { - return false; - } + @Override + public boolean supportsLimit() { + return true; + } - @Override - public boolean useMaxForLimit() { - return true; - } + @Override + public boolean useMaxForLimit() { + return true; + } - @Override - public boolean supportsVariableLimit() { - return false; - } - - @Override - public String getLimitString(String sql, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - if ( limit == 0 ) { - return sql; - } - return sql + " fetch first " + limit + " rows only "; - } + @Override + public boolean supportsVariableLimit() { + return false; + } + }; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2400Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2400Dialect.java index 5aa87d9d7c93..cfdff08c7ed0 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2400Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2400Dialect.java @@ -23,6 +23,11 @@ */ package org.hibernate.dialect; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; + /** * An SQL dialect for DB2/400. This class provides support for DB2 Universal Database for iSeries, * also known as DB2/400. @@ -41,36 +46,32 @@ public String getIdentitySelectString() { } @Override - public boolean supportsLimit() { - return true; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + if ( LimitHelper.hasFirstRow(selection) ) { + throw new UnsupportedOperationException( "query result offset is not supported" ); + } + return sql + " fetch first ? rows only"; + } - @Override - @SuppressWarnings("deprecation") - public boolean supportsLimitOffset() { - return false; - } + @Override + public boolean supportsLimit() { + return true; + } - @Override - public boolean useMaxForLimit() { - return true; - } + @Override + public boolean useMaxForLimit() { + return true; + } - @Override - public boolean supportsVariableLimit() { - return false; - } - - @Override - public String getLimitString(String sql, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - if ( limit == 0 ) { - return sql; - } - return sql + " fetch first " + limit + " rows only "; - } + @Override + public boolean supportsVariableLimit() { + return false; + } + }; + } @Override public String getForUpdateString() { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index f70de1901524..782e23342679 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -30,16 +30,21 @@ import org.hibernate.JDBCException; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.constraint.DB2UniqueKeyExporter; import org.hibernate.dialect.function.AvgWithArgumentCastFunction; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; -import org.hibernate.dialect.unique.DB2UniqueDelegate; -import org.hibernate.dialect.unique.UniqueDelegate; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; @@ -50,7 +55,8 @@ * @author Gavin King */ public class DB2Dialect extends Dialect { - private final UniqueDelegate uniqueDelegate; + + private final DB2UniqueKeyExporter uniqueKeyExporter = new DB2UniqueKeyExporter( this ); /** * Constructs a DB2Dialect @@ -180,8 +186,6 @@ public DB2Dialect() { registerKeyword( "only" ); getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH ); - - uniqueDelegate = new DB2UniqueDelegate( this ); } @Override @@ -249,55 +253,12 @@ public String getQuerySequencesString() { return "select seqname from sysibm.syssequences"; } - @Override - @SuppressWarnings("deprecation") - public boolean supportsLimit() { - return true; - } - - @Override - @SuppressWarnings("deprecation") - public boolean supportsVariableLimit() { - return false; - } - - @Override - @SuppressWarnings("deprecation") - public String getLimitString(String sql, int offset, int limit) { - if ( offset == 0 ) { - return sql + " fetch first " + limit + " rows only"; - } - //nest the main query in an outer select - return "select * from ( select inner2_.*, rownumber() over(order by order of inner2_) as rownumber_ from ( " - + sql + " fetch first " + limit + " rows only ) as inner2_ ) as inner1_ where rownumber_ > " - + offset + " order by rownumber_"; - } - - /** - * {@inheritDoc} - *

    - * - * DB2 does have a one-based offset, however this was actually already handled in the limit string building - * (the '?+1' bit). To not mess up inheritors, I'll leave that part alone and not touch the offset here. - */ - @Override - @SuppressWarnings("deprecation") - public int convertToFirstRowValue(int zeroBasedFirstResult) { - return zeroBasedFirstResult; - } - @Override @SuppressWarnings("deprecation") public String getForUpdateString() { return " for read only with rs use and keep update locks"; } - @Override - @SuppressWarnings("deprecation") - public boolean useMaxForLimit() { - return true; - } - @Override public boolean supportsOuterJoinForUpdate() { return false; @@ -476,13 +437,44 @@ public JDBCException convert(SQLException sqlException, String message, String s } @Override - public UniqueDelegate getUniqueDelegate() { - return uniqueDelegate; + public Exporter getUniqueKeyExporter() { + return uniqueKeyExporter; } @Override public String getNotExpression( String expression ) { return "not (" + expression + ")"; } + + @Override + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + if ( LimitHelper.hasFirstRow(selection) ) { + //nest the main query in an outer select + return "select * from ( select inner2_.*, rownumber() over(order by order of inner2_) as rownumber_ from ( " + + sql + " fetch first ? rows only ) as inner2_ ) as inner1_ where rownumber_ > " + + "? order by rownumber_"; + } + return sql + " fetch first ? rows only"; + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + + @Override + public boolean supportsVariableLimit() { + return false; + } + }; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DataDirectOracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DataDirectOracle9Dialect.java index 90f9e3af80fd..9c4a62988f70 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DataDirectOracle9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DataDirectOracle9Dialect.java @@ -30,8 +30,7 @@ /** * A Dialect for accessing Oracle through DataDirect driver */ -@SuppressWarnings("deprecation") -public class DataDirectOracle9Dialect extends Oracle9Dialect { +public class DataDirectOracle9Dialect extends Oracle9iDialect { @Override public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException { return col; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java index a79822b2e5c2..f2a860f423ea 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -29,11 +29,14 @@ import org.hibernate.MappingException; import org.hibernate.dialect.function.AnsiTrimFunction; import org.hibernate.dialect.function.DerbyConcatFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DerbyCaseFragment; - import org.jboss.logging.Logger; /** @@ -43,11 +46,8 @@ * http://www.jroller.com/comments/kenlars99/Weblog/cloudscape_soon_to_be_derby * * @author Simon Johnston - * - * @deprecated HHH-6073 */ -@Deprecated -public class DerbyDialect extends DB2Dialect { +public abstract class DerbyDialect extends DB2Dialect { @SuppressWarnings("deprecation") private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, @@ -137,23 +137,12 @@ public String getSequenceNextValString(String sequenceName) { } } - @Override - public boolean supportsLimit() { - return isTenPointFiveReleaseOrNewer(); - } - @Override public boolean supportsCommentOn() { //HHH-4531 return false; } - @Override - @SuppressWarnings("deprecation") - public boolean supportsLimitOffset() { - return isTenPointFiveReleaseOrNewer(); - } - @Override public String getForUpdateString() { return " for update with rs"; @@ -169,61 +158,6 @@ public String getReadLockString(int timeout) { return " for read only with rs"; } - - /** - * {@inheritDoc} - *

    - * From Derby 10.5 Docs: - *

    -	 * Query
    -	 * [ORDER BY clause]
    -	 * [result offset clause]
    -	 * [fetch first clause]
    -	 * [FOR UPDATE clause]
    -	 * [WITH {RR|RS|CS|UR}]
    -	 * 
    - */ - @Override - public String getLimitString(String query, final int offset, final int limit) { - final StringBuilder sb = new StringBuilder(query.length() + 50); - final String normalizedSelect = query.toLowerCase().trim(); - final int forUpdateIndex = normalizedSelect.lastIndexOf( "for update") ; - - if ( hasForUpdateClause( forUpdateIndex ) ) { - sb.append( query.substring( 0, forUpdateIndex-1 ) ); - } - else if ( hasWithClause( normalizedSelect ) ) { - sb.append( query.substring( 0, getWithIndex( query ) - 1 ) ); - } - else { - sb.append( query ); - } - - if ( offset == 0 ) { - sb.append( " fetch first " ); - } - else { - sb.append( " offset " ).append( offset ).append( " rows fetch next " ); - } - - sb.append( limit ).append( " rows only" ); - - if ( hasForUpdateClause( forUpdateIndex ) ) { - sb.append( ' ' ); - sb.append( query.substring( forUpdateIndex ) ); - } - else if ( hasWithClause( normalizedSelect ) ) { - sb.append( ' ' ).append( query.substring( getWithIndex( query ) ) ); - } - return sb.toString(); - } - - @Override - public boolean supportsVariableLimit() { - // we bind the limit and offset values directly into the sql... - return false; - } - private boolean hasForUpdateClause(int forUpdateIndex) { return forUpdateIndex >= 0; } @@ -245,6 +179,75 @@ public String getQuerySequencesString() { return null ; } + @Override + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + /** + * {@inheritDoc} + *

    + * From Derby 10.5 Docs: + *

    +        	 * Query
    +        	 * [ORDER BY clause]
    +        	 * [result offset clause]
    +        	 * [fetch first clause]
    +        	 * [FOR UPDATE clause]
    +        	 * [WITH {RR|RS|CS|UR}]
    +        	 * 
    + */ + @Override + public String getProcessedSql() { + final StringBuilder sb = new StringBuilder(sql.length() + 50); + final String normalizedSelect = sql.toLowerCase().trim(); + final int forUpdateIndex = normalizedSelect.lastIndexOf( "for update") ; + + if ( hasForUpdateClause( forUpdateIndex ) ) { + sb.append( sql.substring( 0, forUpdateIndex-1 ) ); + } + else if ( hasWithClause( normalizedSelect ) ) { + sb.append( sql.substring( 0, getWithIndex( sql ) - 1 ) ); + } + else { + sb.append( sql ); + } + + if ( LimitHelper.hasFirstRow(selection) ) { + sb.append( " offset ? rows fetch next " ); + } + else { + sb.append( " fetch first " ); + } + + sb.append( "? rows only" ); + + if ( hasForUpdateClause( forUpdateIndex ) ) { + sb.append( ' ' ); + sb.append( sql.substring( forUpdateIndex ) ); + } + else if ( hasWithClause( normalizedSelect ) ) { + sb.append( ' ' ).append( sql.substring( getWithIndex( sql ) ) ); + } + return sb.toString(); + } + + @Override + public boolean supportsLimit() { + return isTenPointFiveReleaseOrNewer(); + } + + @Override + @SuppressWarnings("deprecation") + public boolean supportsLimitOffset() { + return isTenPointFiveReleaseOrNewer(); + } + + @Override + public boolean supportsVariableLimit() { + return false; + } + }; + } + // Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyTenFiveDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyTenFiveDialect.java index 8cfc26f40f20..3b6230e6fffe 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyTenFiveDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyTenFiveDialect.java @@ -36,7 +36,6 @@ * @author Simon Johnston * @author Scott Marlow */ -@SuppressWarnings("deprecation") public class DerbyTenFiveDialect extends DerbyDialect { /** * Constructs a DerbyTenFiveDialect @@ -51,14 +50,4 @@ public DerbyTenFiveDialect() { public boolean supportsSequences() { return false; } - - @Override - public boolean supportsLimit() { - return true; - } - - @Override - public boolean supportsLimitOffset() { - return true; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index febee6db3792..d1e7d522ffd5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -47,6 +47,7 @@ import org.hibernate.NullPrecedence; import org.hibernate.ScrollMode; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.constraint.ConstraintDelegate; import org.hibernate.dialect.function.CastFunction; import org.hibernate.dialect.function.SQLFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; @@ -61,9 +62,8 @@ import org.hibernate.dialect.lock.SelectLockingStrategy; import org.hibernate.dialect.pagination.LegacyLimitHandler; import org.hibernate.dialect.pagination.LimitHandler; -import org.hibernate.dialect.unique.DefaultUniqueDelegate; -import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.engine.jdbc.LobCreator; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.exception.spi.ConversionContext; @@ -78,8 +78,14 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.io.StreamCopier; -import org.hibernate.mapping.Column; import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.persister.entity.Lockable; import org.hibernate.procedure.internal.StandardCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; @@ -89,10 +95,17 @@ import org.hibernate.sql.CaseFragment; import org.hibernate.sql.ForUpdateFragment; import org.hibernate.sql.JoinFragment; +import org.hibernate.tool.schema.internal.StandardAuxiliaryDatabaseObjectExporter; +import org.hibernate.tool.schema.internal.StandardForeignKeyExporter; +import org.hibernate.tool.schema.internal.StandardIndexExporter; +import org.hibernate.tool.schema.internal.StandardSequenceExporter; +import org.hibernate.tool.schema.internal.StandardTableExporter; +import org.hibernate.tool.schema.internal.StandardUniqueKeyExporter; +import org.hibernate.tool.schema.internal.TemporaryTableExporter; +import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.ClobTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; - import org.jboss.logging.Logger; /** @@ -136,8 +149,6 @@ public abstract class Dialect implements ConversionContext { private final Map sqlFunctions = new HashMap(); private final Set sqlKeywords = new HashSet(); - private final UniqueDelegate uniqueDelegate; - // constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -225,8 +236,6 @@ protected Dialect() { registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() ); registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() ); registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() ); - - uniqueDelegate = new DefaultUniqueDelegate( this ); } /** @@ -897,19 +906,6 @@ public String getSelectSequenceNextValString(String sequenceName) throws Mapping throw new MappingException( getClass().getName() + " does not support sequences" ); } - /** - * The multiline script used to create a sequence. - * - * @param sequenceName The name of the sequence - * @return The sequence creation commands - * @throws MappingException If sequences are not supported. - * @deprecated Use {@link #getCreateSequenceString(String, int, int)} instead - */ - @Deprecated - public String[] getCreateSequenceStrings(String sequenceName) throws MappingException { - return new String[] { getCreateSequenceString( sequenceName ) }; - } - /** * An optional multi-line form for databases which {@link #supportsPooledSequences()}. * @@ -937,7 +933,7 @@ public String[] getCreateSequenceStrings(String sequenceName, int initialValue, * @return The sequence creation command * @throws MappingException If sequences are not supported. */ - protected String getCreateSequenceString(String sequenceName) throws MappingException { + public String getCreateSequenceString(String sequenceName) throws MappingException { throw new MappingException( getClass().getName() + " does not support sequences" ); } @@ -998,7 +994,6 @@ protected String getDropSequenceString(String sequenceName) throws MappingExcept * Get the select command used retrieve the names of all sequences. * * @return The select command; or null if sequences are not supported. - * @see org.hibernate.tool.hbm2ddl.SchemaUpdate */ public String getQuerySequencesString() { return null; @@ -1021,156 +1016,6 @@ public String getSelectGUIDString() { // limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - /** - * Does this dialect support some form of limiting query results - * via a SQL clause? - * - * @return True if this dialect supports some form of LIMIT. - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean supportsLimit() { - return false; - } - - /** - * Does this dialect's LIMIT support (if any) additionally - * support specifying an offset? - * - * @return True if the dialect supports an offset within the limit support. - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean supportsLimitOffset() { - return supportsLimit(); - } - - /** - * Does this dialect support bind variables (i.e., prepared statement - * parameters) for its limit/offset? - * - * @return True if bind variables can be used; false otherwise. - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean supportsVariableLimit() { - return supportsLimit(); - } - - /** - * ANSI SQL defines the LIMIT clause to be in the form LIMIT offset, limit. - * Does this dialect require us to bind the parameters in reverse order? - * - * @return true if the correct order is limit, offset - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean bindLimitParametersInReverseOrder() { - return false; - } - - /** - * Does the LIMIT clause come at the start of the - * SELECT statement, rather than at the end? - * - * @return true if limit parameters should come before other parameters - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean bindLimitParametersFirst() { - return false; - } - - /** - * Does the LIMIT clause take a "maximum" row number instead - * of a total number of returned rows? - *

    - * This is easiest understood via an example. Consider you have a table - * with 20 rows, but you only want to retrieve rows number 11 through 20. - * Generally, a limit with offset would say that the offset = 11 and the - * limit = 10 (we only want 10 rows at a time); this is specifying the - * total number of returned rows. Some dialects require that we instead - * specify offset = 11 and limit = 20, where 20 is the "last" row we want - * relative to offset (i.e. total number of rows = 20 - 11 = 9) - *

    - * So essentially, is limit relative from offset? Or is limit absolute? - * - * @return True if limit is relative from offset; false otherwise. - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean useMaxForLimit() { - return false; - } - - /** - * Generally, if there is no limit applied to a Hibernate query we do not apply any limits - * to the SQL query. This option forces that the limit be written to the SQL query. - * - * @return True to force limit into SQL query even if none specified in Hibernate query; false otherwise. - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public boolean forceLimitUsage() { - return false; - } - - /** - * Given a limit and an offset, apply the limit clause to the query. - * - * @param query The query to which to apply the limit. - * @param offset The offset of the limit - * @param limit The limit of the limit ;) - * @return The modified query statement with the limit applied. - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public String getLimitString(String query, int offset, int limit) { - return getLimitString( query, ( offset > 0 || forceLimitUsage() ) ); - } - - /** - * Apply s limit clause to the query. - *

    - * Typically dialects utilize {@link #supportsVariableLimit() variable} - * limit clauses when they support limits. Thus, when building the - * select command we do not actually need to know the limit or the offest - * since we will just be using placeholders. - *

    - * Here we do still pass along whether or not an offset was specified - * so that dialects not supporting offsets can generate proper exceptions. - * In general, dialects will override one or the other of this method and - * {@link #getLimitString(String, int, int)}. - * - * @param query The query to which to apply the limit. - * @param hasOffset Is the query requesting an offset? - * @return the modified SQL - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - protected String getLimitString(String query, boolean hasOffset) { - throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName()); - } - - /** - * Hibernate APIs explicitly state that setFirstResult() should be a zero-based offset. Here we allow the - * Dialect a chance to convert that value based on what the underlying db or driver will expect. - *

    - * NOTE: what gets passed into {@link #getLimitString(String,int,int)} is the zero-based offset. Dialects which - * do not {@link #supportsVariableLimit} should take care to perform any needed first-row-conversion calls prior - * to injecting the limit values into the SQL string. - * - * @param zeroBasedFirstResult The user-supplied, zero-based first row offset. - * @return The corresponding db/dialect specific offset. - * @see org.hibernate.Query#setFirstResult - * @see org.hibernate.Criteria#setFirstResult - * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. - */ - @Deprecated - public int convertToFirstRowValue(int zeroBasedFirstResult) { - return zeroBasedFirstResult; - } - /** * Build delegate managing LIMIT clause. * @@ -1415,21 +1260,6 @@ public String getForUpdateSkipLockedString(String aliases) { return getForUpdateString( aliases ); } - /** - * Some dialects support an alternative means to SELECT FOR UPDATE, - * whereby a "lock hint" is appends to the table name in the from clause. - *

    - * contributed by Helge Schulz - * - * @param mode The lock mode to apply - * @param tableName The name of the table to which to apply the lock hint. - * @return The table with any required lock hints. - * @deprecated use {@code appendLockHint(LockOptions,String)} instead - */ - @Deprecated - public String appendLockHint(LockMode mode, String tableName) { - return appendLockHint( new LockOptions( mode ), tableName ); - } /** * Some dialects support an alternative means to SELECT FOR UPDATE, * whereby a "lock hint" is appends to the table name in the from clause. @@ -1713,42 +1543,6 @@ public String getCurrentTimestampSQLFunctionName() { // SQLException support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - /** - * Build an instance of the SQLExceptionConverter preferred by this dialect for - * converting SQLExceptions into Hibernate's JDBCException hierarchy. - *

    - * The preferred method is to not override this method; if possible, - * {@link #buildSQLExceptionConversionDelegate()} should be overridden - * instead. - * - * If this method is not overridden, the default SQLExceptionConverter - * implementation executes 3 SQLException converter delegates: - *

      - *
    1. a "static" delegate based on the JDBC 4 defined SQLException hierarchy;
    2. - *
    3. the vendor-specific delegate returned by {@link #buildSQLExceptionConversionDelegate()}; - * (it is strongly recommended that specific Dialect implementations - * override {@link #buildSQLExceptionConversionDelegate()})
    4. - *
    5. a delegate that interprets SQLState codes for either X/Open or SQL-2003 codes, - * depending on java.sql.DatabaseMetaData#getSQLStateType
    6. - *
    - *

    - * If this method is overridden, it is strongly recommended that the - * returned {@link SQLExceptionConverter} interpret SQL errors based on - * vendor-specific error codes rather than the SQLState since the - * interpretation is more accurate when using vendor-specific ErrorCodes. - * - * @return The Dialect's preferred SQLExceptionConverter, or null to - * indicate that the default {@link SQLExceptionConverter} should be used. - * - * @see {@link #buildSQLExceptionConversionDelegate()} - * @deprecated {@link #buildSQLExceptionConversionDelegate()} should be - * overridden instead. - */ - @Deprecated - public SQLExceptionConverter buildSQLExceptionConverter() { - return null; - } - /** * Build an instance of a {@link SQLExceptionConversionDelegate} for * interpreting dialect-specific error or SQLState codes. @@ -1965,6 +1759,47 @@ public final String quote(String name) { // DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + private StandardTableExporter tableExporter = new StandardTableExporter( this ); + private StandardSequenceExporter sequenceExporter = new StandardSequenceExporter( this ); + private StandardIndexExporter indexExporter = new StandardIndexExporter( this ); + private StandardForeignKeyExporter foreignKeyExporter = new StandardForeignKeyExporter( this ); + private StandardUniqueKeyExporter uniqueKeyExporter = new StandardUniqueKeyExporter( this ); + private StandardAuxiliaryDatabaseObjectExporter auxiliaryObjectExporter = new StandardAuxiliaryDatabaseObjectExporter( this ); + private TemporaryTableExporter temporaryTableExporter = new TemporaryTableExporter( this ); + private ConstraintDelegate constraintDelegate = new ConstraintDelegate( this ); + + public Exporter

    getTableExporter() { + return tableExporter; + } + + public Exporter
    getTemporaryTableExporter() { + return temporaryTableExporter; + } + + public Exporter getSequenceExporter() { + return sequenceExporter; + } + + public Exporter getIndexExporter() { + return indexExporter; + } + + public Exporter getForeignKeyExporter() { + return foreignKeyExporter; + } + + public Exporter getUniqueKeyExporter() { + return uniqueKeyExporter; + } + + public Exporter getAuxiliaryDatabaseObjectExporter() { + return auxiliaryObjectExporter; + } + + protected ConstraintDelegate getConstraintDelegate() { + return constraintDelegate; + } + /** * Get the SQL command used to create the named schema * @@ -1987,6 +1822,15 @@ public String getDropSchemaCommand(String schemaName) { return "drop schema " + schemaName; } + /** + * Get the SQL command used to retrieve the current schema name + * + * @return The current schema retrieval SQL + */ + public String getCurrentSchemaCommand() { + return null; + } + /** * Does this dialect support the ALTER TABLE syntax? * @@ -2575,6 +2419,15 @@ public boolean supportsTupleDistinctCounts() { // oddly most database in fact seem to, so true is the default. return true; } + + /** + * If {@link #supportsTupleDistinctCounts()} is true, does the Dialect require the tuple to be wrapped with parens? + * + * @return boolean + */ + public boolean requiresParensForTupleDistinctCounts() { + return false; + } /** * Return the limit that the underlying database places on the number elements in an {@code IN} predicate. @@ -2619,63 +2472,13 @@ public boolean useFollowOnLocking() { public String getNotExpression(String expression) { return "not " + expression; } - - /** - * Get the UniqueDelegate supported by this dialect - * - * @return The UniqueDelegate - */ - public UniqueDelegate getUniqueDelegate() { - return uniqueDelegate; - } - - /** - * Does this dialect support the UNIQUE column syntax? - * - * @return boolean - * - * @deprecated {@link #getUniqueDelegate()} should be overridden instead. - */ - @Deprecated - public boolean supportsUnique() { - return true; - } - - /** - * Does this dialect support adding Unique constraints via create and alter table ? - * - * @return boolean - * - * @deprecated {@link #getUniqueDelegate()} should be overridden instead. - */ - @Deprecated - public boolean supportsUniqueConstraintInCreateAlterTable() { - return true; - } - - /** - * The syntax used to add a unique constraint to a table. - * - * @param constraintName The name of the unique constraint. - * @return The "add unique" fragment - * - * @deprecated {@link #getUniqueDelegate()} should be overridden instead. - */ - @Deprecated - public String getAddUniqueConstraintString(String constraintName) { - return " add constraint " + constraintName + " unique "; + + public String[] applyConstraints(Iterable
    tables, JdbcEnvironment jdbcEnvironment) { + return constraintDelegate.applyConstraints( tables, jdbcEnvironment ); } - - /** - * Is the combination of not-null and unique supported? - * - * @return deprecated - * - * @deprecated {@link #getUniqueDelegate()} should be overridden instead. - */ - @Deprecated - public boolean supportsNotNullUnique() { - return true; + + public String[] dropConstraints(Iterable
    tables, JdbcEnvironment jdbcEnvironment) { + return constraintDelegate.dropConstraints( tables, jdbcEnvironment ); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/FirebirdDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/FirebirdDialect.java index c45d30b5157d..6be4dba763b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/FirebirdDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/FirebirdDialect.java @@ -23,6 +23,11 @@ */ package org.hibernate.dialect; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; + /** * An SQL dialect for Firebird. * @@ -35,20 +40,31 @@ public String getDropSequenceString(String sequenceName) { } @Override - public String getLimitString(String sql, boolean hasOffset) { - return new StringBuilder( sql.length() + 20 ) + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + return new StringBuilder( sql.length() + 20 ) .append( sql ) .insert( 6, hasOffset ? " first ? skip ?" : " first ?" ) .toString(); - } + } - @Override - public boolean bindLimitParametersFirst() { - return true; - } + @Override + public boolean supportsLimit() { + return true; + } - @Override - public boolean bindLimitParametersInReverseOrder() { - return true; - } + @Override + public boolean bindLimitParametersFirst() { + return true; + } + + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + }; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index 5e105a1a0b48..f5256ae6f19e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -33,6 +33,10 @@ import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; @@ -42,7 +46,6 @@ import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.type.StandardBasicTypes; - import org.jboss.logging.Logger; /** @@ -232,24 +235,25 @@ public String getForUpdateString() { } @Override - public boolean supportsLimit() { - return true; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + return sql + (hasOffset ? " limit ? offset ?" : " limit ?"); + } - @Override - public String getLimitString(String sql, boolean hasOffset) { - return sql + (hasOffset ? " limit ? offset ?" : " limit ?"); - } + @Override + public boolean supportsLimit() { + return true; + } - @Override - public boolean bindLimitParametersInReverseOrder() { - return true; - } - - @Override - public boolean bindLimitParametersFirst() { - return false; - } + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + }; + } @Override public boolean supportsIfExistsAfterTableName() { @@ -413,8 +417,8 @@ public boolean supportsLobValueChangePropogation() { } @Override - public boolean supportsTupleDistinctCounts() { - return false; + public boolean requiresParensForTupleDistinctCounts() { + return true; } @Override @@ -427,4 +431,14 @@ public boolean doesReadCommittedCauseWritersToBlockReaders() { public boolean supportsTuplesInSubqueries() { return false; } + + @Override + public String getCurrentSchemaCommand() { + return "call schema()"; + } + + @Override + public boolean qualifyIndexName() { + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java index d4825129890c..0cd0e620f349 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -29,6 +29,7 @@ import org.hibernate.JDBCException; import org.hibernate.LockMode; +import org.hibernate.MappingException; import org.hibernate.StaleObjectStateException; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.AvgWithArgumentCastFunction; @@ -43,6 +44,10 @@ import org.hibernate.dialect.lock.PessimisticReadSelectLockingStrategy; import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy; import org.hibernate.dialect.lock.SelectLockingStrategy; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; @@ -51,7 +56,6 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.persister.entity.Lockable; import org.hibernate.type.StandardBasicTypes; - import org.jboss.logging.Logger; /** @@ -66,7 +70,6 @@ * @author Phillip Baird * @author Fred Toussi */ -@SuppressWarnings("deprecation") public class HSQLDialect extends Dialect { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, @@ -267,33 +270,47 @@ public String getForUpdateString() { } @Override - public boolean supportsLimit() { - return true; - } - - @Override - public String getLimitString(String sql, boolean hasOffset) { - if ( hsqldbVersion < 20 ) { - return new StringBuilder( sql.length() + 10 ) - .append( sql ) - .insert( - sql.toLowerCase().indexOf( "select" ) + 6, - hasOffset ? " limit ? ?" : " top ?" - ) - .toString(); - } - else { - return sql + (hasOffset ? " offset ? limit ?" : " limit ?"); - } - } - + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + if ( hsqldbVersion < 20 ) { + return new StringBuilder( sql.length() + 10 ) + .append( sql ) + .insert( + sql.toLowerCase().indexOf( "select" ) + 6, + hasOffset ? " limit ? ?" : " top ?" + ) + .toString(); + } + else { + return sql + (hasOffset ? " offset ? limit ?" : " limit ?"); + } + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean bindLimitParametersFirst() { + return hsqldbVersion < 20; + } + }; + } + + // Note : HSQLDB actually supports [IF EXISTS] before AND after the + // But as CASCADE has to be AFTER IF EXISTS in case it's after the tablename, + // We put the IF EXISTS before the tablename to be able to add CASCADE after. @Override - public boolean bindLimitParametersFirst() { - return hsqldbVersion < 20; + public boolean supportsIfExistsAfterTableName() { + return false; } @Override - public boolean supportsIfExistsAfterTableName() { + public boolean supportsIfExistsBeforeTableName() { return true; } @@ -312,9 +329,25 @@ public boolean supportsPooledSequences() { return true; } + /** + * HSQL will start with 0, by default. In order for Hibernate to know that this not transient, + * manually start with 1. + */ @Override - protected String getCreateSequenceString(String sequenceName) { - return "create sequence " + sequenceName; + public String getCreateSequenceString(String sequenceName) { + return "create sequence " + sequenceName + " start with 1"; + } + + /** + * Because of the overridden {@link #getCreateSequenceString(String)}, we must also override + * {@link #getCreateSequenceString(String, int, int)} to prevent 2 instances of "start with". + */ + @Override + protected String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize) throws MappingException { + if ( supportsPooledSequences() ) { + return "create sequence " + sequenceName + " start with " + initialValue + " increment by " + incrementSize; + } + throw new MappingException( getClass().getName() + " does not support pooled sequences" ); } @Override @@ -644,4 +677,20 @@ public String toBooleanValueString(boolean bool) { public boolean supportsTupleDistinctCounts() { return false; } + + // Do not drop constraints explicitly, just do this by cascading instead. + @Override + public boolean dropConstraints() { + return false; + } + + @Override + public String getCascadeConstraintsString() { + return " CASCADE "; + } + + @Override + public boolean qualifyIndexName() { + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java index 65d4b7287e32..6c6f8dbc821b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java @@ -27,13 +27,17 @@ import java.sql.Types; import org.hibernate.MappingException; +import org.hibernate.dialect.constraint.InformixUniqueKeyExporter; import org.hibernate.dialect.function.VarArgsSQLFunction; -import org.hibernate.dialect.unique.InformixUniqueDelegate; -import org.hibernate.dialect.unique.UniqueDelegate; +import org.hibernate.dialect.pagination.FirstLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; /** @@ -45,7 +49,7 @@ */ public class InformixDialect extends Dialect { - private final UniqueDelegate uniqueDelegate; + private final InformixUniqueKeyExporter uniqueKeyExporter = new InformixUniqueKeyExporter( this ); /** * Creates new InformixDialect instance. Sets up the JDBC / @@ -81,8 +85,6 @@ public InformixDialect() { registerColumnType( Types.VARCHAR, 32739, "lvarchar($l)" ); registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "(", "||", ")" ) ); - - uniqueDelegate = new InformixUniqueDelegate( this ); } @Override @@ -191,35 +193,9 @@ public String getQuerySequencesString() { } @Override - public boolean supportsLimit() { - return true; - } - - @Override - public boolean useMaxForLimit() { - return true; - } - - @Override - public boolean supportsLimitOffset() { - return false; - } - - @Override - public String getLimitString(String querySelect, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - return new StringBuilder( querySelect.length() + 8 ) - .append( querySelect ) - .insert( querySelect.toLowerCase().indexOf( "select" ) + 6, " first " + limit ) - .toString(); - } - - @Override - public boolean supportsVariableLimit() { - return false; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new FirstLimitHandler(sql, selection); + } @Override public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { @@ -294,7 +270,7 @@ public String getCreateTemporaryTablePostfix() { } @Override - public UniqueDelegate getUniqueDelegate() { - return uniqueDelegate; + public Exporter getUniqueKeyExporter() { + return uniqueKeyExporter; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java index b335bdf50e4c..737d716efbad 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java @@ -27,6 +27,10 @@ import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.type.StandardBasicTypes; /** @@ -153,32 +157,32 @@ public boolean doesRepeatableReadCauseReadersToBlockWriters() { // limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override - public boolean supportsLimitOffset() { - return true; - } - - @Override - public boolean supportsVariableLimit() { - return false; - } - - @Override - public boolean useMaxForLimit() { - return false; - } - - @Override - public String getLimitString(String querySelect, int offset, int limit) { - final StringBuilder soff = new StringBuilder( " offset " + offset ); - final StringBuilder slim = new StringBuilder( " fetch first " + limit + " rows only" ); - final StringBuilder sb = new StringBuilder( querySelect.length() + soff.length() + slim.length() ) - .append( querySelect ); - if ( offset > 0 ) { - sb.append( soff ); - } - if ( limit > 0 ) { - sb.append( slim ); - } - return sb.toString(); - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + final StringBuilder soff = new StringBuilder( " offset ?" ); + final StringBuilder slim = new StringBuilder( " fetch first ? rows only" ); + final StringBuilder sb = new StringBuilder( sql.length() + soff.length() + slim.length() ) + .append( sql ); + if ( LimitHelper.hasFirstRow(selection) ) { + sb.append( soff ); + } + if ( LimitHelper.hasMaxRows(selection) ) { + sb.append( slim ); + } + return sb.toString(); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean supportsVariableLimit() { + return false; + } + }; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java index c58c01ee25f1..840f50514b66 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java @@ -30,6 +30,9 @@ import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.FirstLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.type.StandardBasicTypes; /** @@ -56,7 +59,6 @@ * @author Max Rydahl Andersen * @author Raymond Fan */ -@SuppressWarnings("deprecation") public class IngresDialect extends Dialect { /** * Constructs a IngresDialect @@ -230,35 +232,9 @@ public String getLowercaseFunction() { } @Override - public boolean supportsLimit() { - return true; - } - - @Override - public boolean supportsLimitOffset() { - return false; - } - - @Override - public String getLimitString(String querySelect, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - return new StringBuilder( querySelect.length() + 16 ) - .append( querySelect ) - .insert( 6, " first " + limit ) - .toString(); - } - - @Override - public boolean supportsVariableLimit() { - return false; - } - - @Override - public boolean useMaxForLimit() { - return true; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new FirstLimitHandler(sql, selection); + } @Override public boolean supportsTemporaryTables() { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java index 746f42c17b67..7cd2e38891f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java @@ -27,6 +27,10 @@ import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.type.StandardBasicTypes; /** @@ -34,7 +38,6 @@ * * @author Gavin King */ -@SuppressWarnings("deprecation") public class InterbaseDialect extends Dialect { /** @@ -112,24 +115,20 @@ public boolean supportsSequences() { } @Override - public boolean supportsLimit() { - return true; - } - - @Override - public String getLimitString(String sql, boolean hasOffset) { - return hasOffset ? sql + " rows ? to ?" : sql + " rows ?"; - } - - @Override - public boolean bindLimitParametersFirst() { - return false; - } - - @Override - public boolean bindLimitParametersInReverseOrder() { - return false; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + final boolean hasOffset = LimitHelper.hasFirstRow(selection); + return hasOffset ? sql + " rows ? to ?" : sql + " rows ?"; + } + + @Override + public boolean supportsLimit() { + return true; + } + }; + } @Override public String getCurrentTimestampSelectString() { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java index f377fe727c9b..965a61d0a993 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java @@ -174,11 +174,6 @@ public String getDropSequenceString(String sequenceName) { return "drop sequence " + sequenceName + " restrict"; } - @Override - public boolean supportsLimit() { - return false; - } - @Override public String getCascadeConstraintsString() { return " cascade"; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java index f9802147f1c6..ecb2a6da11c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java @@ -49,6 +49,7 @@ public boolean supportsColumnCheck() { return false; } + @Override public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { return EXTRACTER; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java index a0ff52bd5566..e328a4e41715 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -31,13 +31,22 @@ import org.hibernate.JDBCException; import org.hibernate.NullPrecedence; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.constraint.MySQLIndexExporter; +import org.hibernate.dialect.constraint.MySQLUniqueKeyExporter; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; /** @@ -45,9 +54,11 @@ * * @author Gavin King */ -@SuppressWarnings("deprecation") public class MySQLDialect extends Dialect { + private final MySQLUniqueKeyExporter uniqueKeyExporter = new MySQLUniqueKeyExporter( this ); + private final MySQLIndexExporter indexExporter = new MySQLIndexExporter( this ); + /** * Constructs a MySQLDialect */ @@ -241,20 +252,26 @@ public String getAddForeignKeyConstraintString( ); } - @Override - public boolean supportsLimit() { - return true; - } - @Override public String getDropForeignKeyString() { return " drop foreign key "; } @Override - public String getLimitString(String sql, boolean hasOffset) { - return sql + (hasOffset ? " limit ?, ?" : " limit ?"); - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + final boolean hasOffset = LimitHelper.hasFirstRow(selection); + return sql + (hasOffset ? " limit ?, ?" : " limit ?"); + } + + @Override + public boolean supportsLimit() { + return true; + } + }; + } @Override public char closeQuote() { @@ -460,4 +477,14 @@ public JDBCException convert(SQLException sqlException, String message, String s public String getNotExpression(String expression) { return "not (" + expression + ")"; } + + @Override + public Exporter getUniqueKeyExporter() { + return uniqueKeyExporter; + } + + @Override + public Exporter getIndexExporter() { + return indexExporter; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle12cDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle12cDialect.java new file mode 100644 index 000000000000..f2066ad401a0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle12cDialect.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect; + +import org.hibernate.cfg.Environment; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler; +import org.hibernate.engine.spi.RowSelection; + +/** + * An SQL dialect for Oracle 12c. + * + * @author zhouyanming (zhouyanming@gmail.com) + */ +public class Oracle12cDialect extends Oracle10gDialect { + + public Oracle12cDialect() { + super(); + } + + @Override + protected void registerDefaultProperties() { + super.registerDefaultProperties(); + getDefaultProperties().setProperty( Environment.USE_GET_GENERATED_KEYS, "true" ); + } + + @Override + public boolean supportsIdentityColumns() { + return true; + } + + @Override + public boolean supportsInsertSelectIdentity() { + return true; + } + + @Override + public String getIdentityColumnString() { + return "generated as identity"; + } + + @Override + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new SQL2008StandardLimitHandler(sql, selection); + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java index 9720ce3ab92c..8f971e03ffdc 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java @@ -38,6 +38,10 @@ import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockTimeoutException; @@ -60,7 +64,6 @@ * * @author Steve Ebersole */ -@SuppressWarnings("deprecation") public class Oracle8iDialect extends Dialect { private static final int PARAM_LIST_SIZE_LIMIT = 1000; @@ -244,35 +247,56 @@ public CaseFragment createCaseFragment() { } @Override - public String getLimitString(String sql, boolean hasOffset) { - sql = sql.trim(); - boolean isForUpdate = false; - if ( sql.toLowerCase().endsWith( " for update" ) ) { - sql = sql.substring( 0, sql.length()-11 ); - isForUpdate = true; - } - - final StringBuilder pagingSelect = new StringBuilder( sql.length()+100 ); - if (hasOffset) { - pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); - } - else { - pagingSelect.append( "select * from ( " ); - } - pagingSelect.append( sql ); - if (hasOffset) { - pagingSelect.append( " ) row_ ) where rownum_ <= ? and rownum_ > ?" ); - } - else { - pagingSelect.append( " ) where rownum <= ?" ); - } - - if ( isForUpdate ) { - pagingSelect.append( " for update" ); - } - - return pagingSelect.toString(); - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + sql = sql.trim(); + boolean isForUpdate = false; + if ( sql.toLowerCase().endsWith( " for update" ) ) { + sql = sql.substring( 0, sql.length()-11 ); + isForUpdate = true; + } + + final StringBuilder pagingSelect = new StringBuilder( sql.length()+100 ); + if (hasOffset) { + pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); + } + else { + pagingSelect.append( "select * from ( " ); + } + pagingSelect.append( sql ); + if (hasOffset) { + pagingSelect.append( " ) row_ ) where rownum_ <= ? and rownum_ > ?" ); + } + else { + pagingSelect.append( " ) where rownum <= ?" ); + } + + if ( isForUpdate ) { + pagingSelect.append( " for update" ); + } + + return pagingSelect.toString(); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + }; + } /** * Allows access to the basic {@link Dialect#getSelectClauseNullString} @@ -364,11 +388,6 @@ public boolean supportsPooledSequences() { return true; } - @Override - public boolean supportsLimit() { - return true; - } - @Override public String getForUpdateString(String aliases) { return getForUpdateString() + " of " + aliases; @@ -379,16 +398,6 @@ public String getForUpdateNowaitString(String aliases) { return getForUpdateString() + " of " + aliases + " nowait"; } - @Override - public boolean bindLimitParametersInReverseOrder() { - return true; - } - - @Override - public boolean useMaxForLimit() { - return true; - } - @Override public boolean forUpdateOfColumns() { return true; @@ -620,4 +629,9 @@ public CallableStatementSupport getCallableStatementSupport() { // Oracle supports returning cursors return StandardCallableStatementSupport.REF_CURSOR_INSTANCE; } + + @Override + public String getCurrentSchemaCommand() { + return "select sys_context( 'userenv', 'current_schema' ) from dual"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java deleted file mode 100644 index cf04dbadb2a0..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.dialect; - -import java.sql.CallableStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; - -import org.hibernate.cfg.Environment; -import org.hibernate.dialect.function.NoArgSQLFunction; -import org.hibernate.dialect.function.NvlFunction; -import org.hibernate.dialect.function.SQLFunctionTemplate; -import org.hibernate.dialect.function.StandardSQLFunction; -import org.hibernate.dialect.function.VarArgsSQLFunction; -import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; -import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.JdbcExceptionHelper; -import org.hibernate.type.StandardBasicTypes; - -import org.jboss.logging.Logger; - -/** - * An SQL dialect for Oracle 9 (uses ANSI-style syntax where possible). - * - * @author Gavin King - * @author David Channon - * - * @deprecated Use either Oracle9iDialect or Oracle10gDialect instead - */ -@SuppressWarnings("deprecation") -@Deprecated -public class Oracle9Dialect extends Dialect { - - private static final int PARAM_LIST_SIZE_LIMIT = 1000; - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - Oracle9Dialect.class.getName() - ); - - /** - * Constructs a Oracle9Dialect - */ - public Oracle9Dialect() { - super(); - LOG.deprecatedOracle9Dialect(); - registerColumnType( Types.BIT, "number(1,0)" ); - registerColumnType( Types.BIGINT, "number(19,0)" ); - registerColumnType( Types.SMALLINT, "number(5,0)" ); - registerColumnType( Types.TINYINT, "number(3,0)" ); - registerColumnType( Types.INTEGER, "number(10,0)" ); - registerColumnType( Types.CHAR, "char(1 char)" ); - registerColumnType( Types.VARCHAR, 4000, "varchar2($l char)" ); - registerColumnType( Types.VARCHAR, "long" ); - registerColumnType( Types.FLOAT, "float" ); - registerColumnType( Types.DOUBLE, "double precision" ); - registerColumnType( Types.DATE, "date" ); - registerColumnType( Types.TIME, "date" ); - registerColumnType( Types.TIMESTAMP, "timestamp" ); - registerColumnType( Types.VARBINARY, 2000, "raw($l)" ); - registerColumnType( Types.VARBINARY, "long raw" ); - registerColumnType( Types.NUMERIC, "number($p,$s)" ); - registerColumnType( Types.DECIMAL, "number($p,$s)" ); - registerColumnType( Types.BLOB, "blob" ); - registerColumnType( Types.CLOB, "clob" ); - - // Oracle driver reports to support getGeneratedKeys(), but they only - // support the version taking an array of the names of the columns to - // be returned (via its RETURNING clause). No other driver seems to - // support this overloaded version. - getDefaultProperties().setProperty( Environment.USE_GET_GENERATED_KEYS, "false" ); - getDefaultProperties().setProperty( Environment.USE_STREAMS_FOR_BINARY, "true" ); - getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE ); - - registerFunction( "abs", new StandardSQLFunction( "abs" ) ); - registerFunction( "sign", new StandardSQLFunction( "sign", StandardBasicTypes.INTEGER ) ); - - registerFunction( "acos", new StandardSQLFunction( "acos", StandardBasicTypes.DOUBLE ) ); - registerFunction( "asin", new StandardSQLFunction( "asin", StandardBasicTypes.DOUBLE ) ); - registerFunction( "atan", new StandardSQLFunction( "atan", StandardBasicTypes.DOUBLE ) ); - registerFunction( "cos", new StandardSQLFunction( "cos", StandardBasicTypes.DOUBLE ) ); - registerFunction( "cosh", new StandardSQLFunction( "cosh", StandardBasicTypes.DOUBLE ) ); - registerFunction( "exp", new StandardSQLFunction( "exp", StandardBasicTypes.DOUBLE ) ); - registerFunction( "ln", new StandardSQLFunction( "ln", StandardBasicTypes.DOUBLE ) ); - registerFunction( "sin", new StandardSQLFunction( "sin", StandardBasicTypes.DOUBLE ) ); - registerFunction( "sinh", new StandardSQLFunction( "sinh", StandardBasicTypes.DOUBLE ) ); - registerFunction( "stddev", new StandardSQLFunction( "stddev", StandardBasicTypes.DOUBLE ) ); - registerFunction( "sqrt", new StandardSQLFunction( "sqrt", StandardBasicTypes.DOUBLE ) ); - registerFunction( "tan", new StandardSQLFunction( "tan", StandardBasicTypes.DOUBLE ) ); - registerFunction( "tanh", new StandardSQLFunction( "tanh", StandardBasicTypes.DOUBLE ) ); - registerFunction( "variance", new StandardSQLFunction( "variance", StandardBasicTypes.DOUBLE ) ); - - registerFunction( "round", new StandardSQLFunction( "round" ) ); - registerFunction( "trunc", new StandardSQLFunction( "trunc" ) ); - registerFunction( "ceil", new StandardSQLFunction( "ceil" ) ); - registerFunction( "floor", new StandardSQLFunction( "floor" ) ); - - registerFunction( "chr", new StandardSQLFunction( "chr", StandardBasicTypes.CHARACTER ) ); - registerFunction( "initcap", new StandardSQLFunction( "initcap" ) ); - registerFunction( "lower", new StandardSQLFunction( "lower" ) ); - registerFunction( "ltrim", new StandardSQLFunction( "ltrim" ) ); - registerFunction( "rtrim", new StandardSQLFunction( "rtrim" ) ); - registerFunction( "soundex", new StandardSQLFunction( "soundex" ) ); - registerFunction( "upper", new StandardSQLFunction( "upper" ) ); - registerFunction( "ascii", new StandardSQLFunction( "ascii", StandardBasicTypes.INTEGER ) ); - - registerFunction( "to_char", new StandardSQLFunction( "to_char", StandardBasicTypes.STRING ) ); - registerFunction( "to_date", new StandardSQLFunction( "to_date", StandardBasicTypes.TIMESTAMP ) ); - - registerFunction( "current_date", new NoArgSQLFunction( "current_date", StandardBasicTypes.DATE, false ) ); - registerFunction( "current_time", new NoArgSQLFunction( "current_timestamp", StandardBasicTypes.TIME, false ) ); - registerFunction( - "current_timestamp", new NoArgSQLFunction( - "current_timestamp", - StandardBasicTypes.TIMESTAMP, - false - ) - ); - - registerFunction( "last_day", new StandardSQLFunction( "last_day", StandardBasicTypes.DATE ) ); - registerFunction( "sysdate", new NoArgSQLFunction( "sysdate", StandardBasicTypes.DATE, false ) ); - registerFunction( "systimestamp", new NoArgSQLFunction( "systimestamp", StandardBasicTypes.TIMESTAMP, false ) ); - registerFunction( "uid", new NoArgSQLFunction( "uid", StandardBasicTypes.INTEGER, false ) ); - registerFunction( "user", new NoArgSQLFunction( "user", StandardBasicTypes.STRING, false ) ); - - registerFunction( "rowid", new NoArgSQLFunction( "rowid", StandardBasicTypes.LONG, false ) ); - registerFunction( "rownum", new NoArgSQLFunction( "rownum", StandardBasicTypes.LONG, false ) ); - - // Multi-param string dialect functions... - registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "", "||", "" ) ); - registerFunction( "instr", new StandardSQLFunction( "instr", StandardBasicTypes.INTEGER ) ); - registerFunction( "instrb", new StandardSQLFunction( "instrb", StandardBasicTypes.INTEGER ) ); - registerFunction( "lpad", new StandardSQLFunction( "lpad", StandardBasicTypes.STRING ) ); - registerFunction( "replace", new StandardSQLFunction( "replace", StandardBasicTypes.STRING ) ); - registerFunction( "rpad", new StandardSQLFunction( "rpad", StandardBasicTypes.STRING ) ); - registerFunction( "substr", new StandardSQLFunction( "substr", StandardBasicTypes.STRING ) ); - registerFunction( "substrb", new StandardSQLFunction( "substrb", StandardBasicTypes.STRING ) ); - registerFunction( "translate", new StandardSQLFunction( "translate", StandardBasicTypes.STRING ) ); - - registerFunction( "substring", new StandardSQLFunction( "substr", StandardBasicTypes.STRING ) ); - registerFunction( "locate", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "instr(?2,?1)" ) ); - registerFunction( "bit_length", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "vsize(?1)*8" ) ); - registerFunction( "coalesce", new NvlFunction() ); - - // Multi-param numeric dialect functions... - registerFunction( "atan2", new StandardSQLFunction( "atan2", StandardBasicTypes.FLOAT ) ); - registerFunction( "log", new StandardSQLFunction( "log", StandardBasicTypes.INTEGER ) ); - registerFunction( "mod", new StandardSQLFunction( "mod", StandardBasicTypes.INTEGER ) ); - registerFunction( "nvl", new StandardSQLFunction( "nvl" ) ); - registerFunction( "nvl2", new StandardSQLFunction( "nvl2" ) ); - registerFunction( "power", new StandardSQLFunction( "power", StandardBasicTypes.FLOAT ) ); - - // Multi-param date dialect functions... - registerFunction( "add_months", new StandardSQLFunction( "add_months", StandardBasicTypes.DATE ) ); - registerFunction( "months_between", new StandardSQLFunction( "months_between", StandardBasicTypes.FLOAT ) ); - registerFunction( "next_day", new StandardSQLFunction( "next_day", StandardBasicTypes.DATE ) ); - - registerFunction( "str", new StandardSQLFunction( "to_char", StandardBasicTypes.STRING ) ); - } - - @Override - public String getAddColumnString() { - return "add"; - } - - @Override - public String getSequenceNextValString(String sequenceName) { - return "select " + getSelectSequenceNextValString( sequenceName ) + " from dual"; - } - - @Override - public String getSelectSequenceNextValString(String sequenceName) { - return sequenceName + ".nextval"; - } - - @Override - public String getCreateSequenceString(String sequenceName) { - //starts with 1, implicitly - return "create sequence " + sequenceName; - } - - @Override - public String getDropSequenceString(String sequenceName) { - return "drop sequence " + sequenceName; - } - - @Override - public String getCascadeConstraintsString() { - return " cascade constraints"; - } - - @Override - public boolean dropConstraints() { - return false; - } - - @Override - public String getForUpdateNowaitString() { - return " for update nowait"; - } - - @Override - public boolean supportsSequences() { - return true; - } - - @Override - public boolean supportsPooledSequences() { - return true; - } - - @Override - public boolean supportsLimit() { - return true; - } - - @Override - public String getLimitString(String sql, boolean hasOffset) { - - sql = sql.trim(); - boolean isForUpdate = false; - if ( sql.toLowerCase().endsWith( " for update" ) ) { - sql = sql.substring( 0, sql.length() - 11 ); - isForUpdate = true; - } - - final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 ); - if ( hasOffset ) { - pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); - } - else { - pagingSelect.append( "select * from ( " ); - } - pagingSelect.append( sql ); - if ( hasOffset ) { - pagingSelect.append( " ) row_ where rownum <= ?) where rownum_ > ?" ); - } - else { - pagingSelect.append( " ) where rownum <= ?" ); - } - - if ( isForUpdate ) { - pagingSelect.append( " for update" ); - } - - return pagingSelect.toString(); - } - - @Override - public String getForUpdateString(String aliases) { - return getForUpdateString() + " of " + aliases; - } - - @Override - public String getForUpdateNowaitString(String aliases) { - return getForUpdateString() + " of " + aliases + " nowait"; - } - - @Override - public boolean bindLimitParametersInReverseOrder() { - return true; - } - - @Override - public boolean useMaxForLimit() { - return true; - } - - @Override - public boolean forUpdateOfColumns() { - return true; - } - - @Override - public String getQuerySequencesString() { - return "select sequence_name from user_sequences"; - } - - @Override - public String getSelectGUIDString() { - return "select rawtohex(sys_guid()) from dual"; - } - - @Override - public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { - return EXTRACTER; - } - - private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() { - @Override - public String extractConstraintName(SQLException sqle) { - final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle ); - if ( errorCode == 1 || errorCode == 2291 || errorCode == 2292 ) { - return extractUsingTemplate( "constraint (", ") violated", sqle.getMessage() ); - } - else if ( errorCode == 1400 ) { - // simple nullability constraint - return null; - } - else { - return null; - } - } - }; - - @Override - public int registerResultSetOutParameter(java.sql.CallableStatement statement, int col) throws SQLException { - // register the type of the out param - an Oracle specific type - statement.registerOutParameter( col, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() ); - col++; - return col; - } - - @Override - public ResultSet getResultSet(CallableStatement ps) throws SQLException { - ps.execute(); - return (ResultSet) ps.getObject( 1 ); - } - - @Override - public boolean supportsUnionAll() { - return true; - } - - @Override - public boolean supportsCommentOn() { - return true; - } - - @Override - public boolean supportsTemporaryTables() { - return true; - } - - @Override - public String generateTemporaryTableName(String baseTableName) { - final String name = super.generateTemporaryTableName( baseTableName ); - return name.length() > 30 ? name.substring( 1, 30 ) : name; - } - - @Override - public String getCreateTemporaryTableString() { - return "create global temporary table"; - } - - @Override - public String getCreateTemporaryTablePostfix() { - return "on commit delete rows"; - } - - @Override - public boolean dropTemporaryTableAfterUse() { - return false; - } - - @Override - public boolean supportsCurrentTimestampSelection() { - return true; - } - - @Override - public String getCurrentTimestampSelectString() { - return "select systimestamp from dual"; - } - - @Override - public boolean isCurrentTimestampSelectStringCallable() { - return false; - } - - @Override - public boolean supportsEmptyInList() { - return false; - } - - @Override - public boolean supportsExistsInSelect() { - return false; - } - - @Override - public int getInExpressionCountLimit() { - return PARAM_LIST_SIZE_LIMIT; - } - - @Override - public String getNotExpression(String expression) { - return "not (" + expression + ")"; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java index 687d23bdaa0a..4a8798c8d758 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java @@ -26,6 +26,10 @@ import java.sql.Types; import org.hibernate.LockOptions; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.sql.ANSICaseFragment; import org.hibernate.sql.CaseFragment; @@ -58,40 +62,61 @@ public CaseFragment createCaseFragment() { } @Override - public String getLimitString(String sql, boolean hasOffset) { - sql = sql.trim(); - String forUpdateClause = null; - boolean isForUpdate = false; - final int forUpdateIndex = sql.toLowerCase().lastIndexOf( "for update") ; - if ( forUpdateIndex > -1 ) { - // save 'for update ...' and then remove it - forUpdateClause = sql.substring( forUpdateIndex ); - sql = sql.substring( 0, forUpdateIndex-1 ); - isForUpdate = true; - } - - final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 ); - if (hasOffset) { - pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); - } - else { - pagingSelect.append( "select * from ( " ); - } - pagingSelect.append( sql ); - if (hasOffset) { - pagingSelect.append( " ) row_ where rownum <= ?) where rownum_ > ?" ); - } - else { - pagingSelect.append( " ) where rownum <= ?" ); - } - - if ( isForUpdate ) { - pagingSelect.append( " " ); - pagingSelect.append( forUpdateClause ); - } - - return pagingSelect.toString(); - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + sql = sql.trim(); + String forUpdateClause = null; + boolean isForUpdate = false; + final int forUpdateIndex = sql.toLowerCase().lastIndexOf( "for update") ; + if ( forUpdateIndex > -1 ) { + // save 'for update ...' and then remove it + forUpdateClause = sql.substring( forUpdateIndex ); + sql = sql.substring( 0, forUpdateIndex-1 ); + isForUpdate = true; + } + + final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 ); + if (hasOffset) { + pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); + } + else { + pagingSelect.append( "select * from ( " ); + } + pagingSelect.append( sql ); + if (hasOffset) { + pagingSelect.append( " ) row_ where rownum <= ?) where rownum_ > ?" ); + } + else { + pagingSelect.append( " ) where rownum <= ?" ); + } + + if ( isForUpdate ) { + pagingSelect.append( " " ); + pagingSelect.append( forUpdateClause ); + } + + return pagingSelect.toString(); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + }; + } @Override public String getSelectClauseNullString(int sqlType) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java deleted file mode 100644 index 639febfaf1cc..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.dialect; - -import java.sql.Types; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.sql.CaseFragment; -import org.hibernate.sql.DecodeCaseFragment; -import org.hibernate.sql.JoinFragment; -import org.hibernate.sql.OracleJoinFragment; - -import org.jboss.logging.Logger; - -/** - * An SQL dialect for Oracle, compatible with Oracle 8. - * - * @deprecated Use Oracle8iDialect instead. - * @author Gavin King - */ -@SuppressWarnings("deprecation") -@Deprecated -public class OracleDialect extends Oracle9Dialect { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - OracleDialect.class.getName() - ); - - /** - * Constructs a (DEPRECATED) Oracle9Dialect - */ - public OracleDialect() { - super(); - LOG.deprecatedOracleDialect(); - // Oracle8 and previous define only a "DATE" type which - // is used to represent all aspects of date/time - registerColumnType( Types.TIMESTAMP, "date" ); - registerColumnType( Types.CHAR, "char(1)" ); - registerColumnType( Types.VARCHAR, 4000, "varchar2($l)" ); - } - - @Override - public JoinFragment createOuterJoinFragment() { - return new OracleJoinFragment(); - } - - @Override - public CaseFragment createCaseFragment() { - return new DecodeCaseFragment(); - } - - @Override - public String getLimitString(String sql, boolean hasOffset) { - - sql = sql.trim(); - boolean isForUpdate = false; - if ( sql.toLowerCase().endsWith( " for update" ) ) { - sql = sql.substring( 0, sql.length()-11 ); - isForUpdate = true; - } - - final StringBuilder pagingSelect = new StringBuilder( sql.length()+100 ); - if (hasOffset) { - pagingSelect.append( "select * from ( select row_.*, rownum rownum_ from ( " ); - } - else { - pagingSelect.append( "select * from ( " ); - } - pagingSelect.append( sql ); - if (hasOffset) { - pagingSelect.append( " ) row_ ) where rownum_ <= ? and rownum_ > ?" ); - } - else { - pagingSelect.append( " ) where rownum <= ?" ); - } - - if ( isForUpdate ) { - pagingSelect.append( " for update" ); - } - - return pagingSelect.toString(); - } - - @Override - public String getSelectClauseNullString(int sqlType) { - switch(sqlType) { - case Types.VARCHAR: - case Types.CHAR: - return "to_char(null)"; - case Types.DATE: - case Types.TIMESTAMP: - case Types.TIME: - return "to_date(null)"; - default: - return "to_number(null)"; - } - } - - @Override - public String getCurrentTimestampSelectString() { - return "select sysdate from dual"; - } - - @Override - public String getCurrentTimestampSQLFunctionName() { - return "sysdate"; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java index f5344aa12792..41b02844525b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java @@ -37,6 +37,10 @@ import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; @@ -233,19 +237,25 @@ public String getQuerySequencesString() { } @Override - public boolean supportsLimit() { - return true; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + return sql + (hasOffset ? " limit ? offset ?" : " limit ?"); + } - @Override - public String getLimitString(String sql, boolean hasOffset) { - return sql + (hasOffset ? " limit ? offset ?" : " limit ?"); - } + @Override + public boolean supportsLimit() { + return true; + } - @Override - public boolean bindLimitParametersInReverseOrder() { - return true; - } + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + }; + } @Override public boolean supportsIdentityColumns() { @@ -361,8 +371,8 @@ public String getCurrentTimestampSelectString() { } @Override - public boolean supportsTupleDistinctCounts() { - return false; + public boolean requiresParensForTupleDistinctCounts() { + return true; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL9Dialect.java index d1908e96fb78..00f3d35db98f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL9Dialect.java @@ -28,7 +28,7 @@ * * @author edalquist */ -public class PostgreSQL9Dialect extends PostgreSQL81Dialect { +public class PostgreSQL9Dialect extends PostgreSQL82Dialect { @Override public boolean supportsIfExistsBeforeConstraintName() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java deleted file mode 100644 index bf70aa08f638..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.dialect; - -/** - * An SQL dialect for Postgres - *

    - * For discussion of BLOB support in Postgres, as of 8.4, have a peek at - * http://jdbc.postgresql.org/documentation/84/binary-data.html. - * For the effects in regards to Hibernate see http://in.relation.to/15492.lace - * - * @author Gavin King - * - * @deprecated use {@link PostgreSQL82Dialect} instead - */ -@Deprecated -public class PostgreSQLDialect extends PostgreSQL82Dialect { -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java index 60c2eeb13132..889af9a6ad97 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java @@ -37,8 +37,7 @@ * * @author Jim Mlodgenski */ -@SuppressWarnings("deprecation") -public class PostgresPlusDialect extends PostgreSQLDialect { +public class PostgresPlusDialect extends PostgreSQL81Dialect { /** * Constructs a PostgresPlusDialect */ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java index 3e13a521fe14..b2b8bd9985cf 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java @@ -37,12 +37,15 @@ import org.hibernate.dialect.lock.PessimisticWriteUpdateLockingStrategy; import org.hibernate.dialect.lock.SelectLockingStrategy; import org.hibernate.dialect.lock.UpdateLockingStrategy; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.persister.entity.Lockable; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.type.StandardBasicTypes; - import org.jboss.logging.Logger; /** @@ -57,7 +60,6 @@ * * @author Ploski and Hanson */ -@SuppressWarnings("deprecation") public class RDMSOS2200Dialect extends Dialect { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, @@ -329,27 +331,33 @@ public CaseFragment createCaseFragment() { } @Override - public boolean supportsLimit() { - return true; - } - - @Override - public boolean supportsLimitOffset() { - return false; - } - - @Override - public String getLimitString(String sql, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - return sql + " fetch first " + limit + " rows only "; - } - - @Override - public boolean supportsVariableLimit() { - return false; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new AbstractLimitHandler(sql, selection) { + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + if ( hasOffset ) { + throw new UnsupportedOperationException( "query result offset is not supported" ); + } + return sql + " fetch first ? rows only "; + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean supportsLimitOffset() { + return false; + } + + @Override + public boolean supportsVariableLimit() { + return false; + } + }; + } @Override public boolean supportsUnionAll() { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index c8dba6137c8f..bbb2154a1cec 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -30,6 +30,9 @@ import org.hibernate.dialect.function.AnsiTrimEmulationFunction; import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.TopLimitHandler; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; @@ -72,23 +75,6 @@ public String getNoColumnsInsertString() { return "default values"; } - static int getAfterSelectInsertPoint(String sql) { - final int selectIndex = sql.toLowerCase().indexOf( "select" ); - final int selectDistinctIndex = sql.toLowerCase().indexOf( "select distinct" ); - return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6); - } - - @Override - public String getLimitString(String querySelect, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - return new StringBuilder( querySelect.length() + 8 ) - .append( querySelect ) - .insert( getAfterSelectInsertPoint( querySelect ), " top " + limit ) - .toString(); - } - /** * Use insert table(...) values(...) select SCOPE_IDENTITY() *

    @@ -98,26 +84,11 @@ public String getLimitString(String querySelect, int offset, int limit) { public String appendIdentitySelectToInsert(String insertSQL) { return insertSQL + " select scope_identity()"; } - - @Override - public boolean supportsLimit() { - return true; - } - + @Override - public boolean useMaxForLimit() { - return true; - } - - @Override - public boolean supportsLimitOffset() { - return false; - } - - @Override - public boolean supportsVariableLimit() { - return false; - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new TopLimitHandler(sql, selection, false, false); + } @Override public char closeQuote() { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java index bbd6545dab21..06f3c8ff3668 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java @@ -37,6 +37,9 @@ import org.hibernate.dialect.lock.PessimisticWriteUpdateLockingStrategy; import org.hibernate.dialect.lock.SelectLockingStrategy; import org.hibernate.dialect.lock.UpdateLockingStrategy; +import org.hibernate.dialect.pagination.FirstLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.persister.entity.Lockable; import org.hibernate.sql.JoinFragment; import org.hibernate.sql.OracleJoinFragment; @@ -169,35 +172,9 @@ public boolean supportsTableCheck() { } @Override - public boolean supportsLimitOffset() { - return false; - } - - @Override - public boolean supportsVariableLimit() { - return false; - } - - @Override - public boolean supportsLimit() { - return true; - } - - @Override - public boolean useMaxForLimit() { - return true; - } - - @Override - public String getLimitString(String querySelect, int offset, int limit) { - if ( offset > 0 ) { - throw new UnsupportedOperationException( "query result offset is not supported" ); - } - return new StringBuilder( querySelect.length() + 8 ) - .append( querySelect ) - .insert( 6, " first " + limit ) - .toString(); - } + public LimitHandler buildLimitHandler(String sql, RowSelection selection) { + return new FirstLimitHandler(sql, selection); + } @Override public boolean supportsCurrentTimestampSelection() { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java new file mode 100644 index 000000000000..b1f73e28d6f5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java @@ -0,0 +1,229 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.dialect.constraint; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.UniqueConstraint; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AbstractConstraint; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.jboss.logging.Logger; + +/** + * Databases differ in the ways they handle indexes and unique constraints. Due to the somewhat complex rulesets, + * the constraints export is tied to the Dialect through this delegate. Through the list of {@link Table}s, + * we're able to handle permutations of: + *

      + *
    • unique columns (ex: {@link Column#unique()})
    • + *
    • {@link UniqueConstraint}
    • + *
    • {@link javax.persistence.Index} (including {@link javax.persistence.Index#unique()}
    • + *
    + * + * Each Dialect then determines the correct set of constraints to export based on the entire bucket of index and + * uniqueness concepts. This implementation attempts to cover *most* cases. However, if you require something specific, it can be easily + * extended and provided through a custom {@link Dialect}. + * + * Note that we introduce another layer of duplicate prevention (indexColumnListIds & uniqueColumnListIds). + * Some duplication is already prevented further up (ex: through {@link Index#getExportIdentifier()}), but that primarily + * prevents duplication caused by explicit mappings. + * + * @author Brett Meyer + */ +public class ConstraintDelegate { + + private static final Logger LOG = Logger.getLogger( ConstraintDelegate.class ); + + final protected Dialect dialect; + + public ConstraintDelegate(Dialect dialect) { + this.dialect = dialect; + } + + /** + * Generate the list of constraint-creating SQL strings from the given set of {@link Table}s. + * + * @param tables + * @param jdbcEnvironment + * @return String[] The list of constraint-creating SQL strings. + */ + public String[] applyConstraints(Iterable
    tables, JdbcEnvironment jdbcEnvironment) { + final List sqlStrings = new ArrayList(); + // List of "columnListIds" (hashes of column names), FIFO, used to prevent duplicate index creation. + final List indexColumnListIds = new ArrayList(); + // List of "columnListIds" (hashes of column names), alphabetical, used to prevent duplicate unique constraint creation. + final List uniqueColumnListIds = new ArrayList(); + + for ( Table table : tables ) { + if( !table.isPhysicalTable() ){ + continue; + } + + for ( Index index : table.getIndexes() ) { + createIndex( index, sqlStrings, indexColumnListIds, uniqueColumnListIds, jdbcEnvironment ); + } + + for ( UniqueKey uniqueKey : table.getUniqueKeys() ) { + createUnique( uniqueKey, sqlStrings, indexColumnListIds, uniqueColumnListIds, jdbcEnvironment ); + } + } + + return sqlStrings.toArray( new String[sqlStrings.size()] ); + } + + /** + * Create the SQL string for the given {@link Index}. By default, this creates a unique constraint if + * {@link Index#isUnique()} returns true. Otherwise, create the index. + * + * Note that an index for (col1, col2) is not the same as (col2, col1), so both should be created. However, + * only one single unique constraint should be created for (col1, col2) if {@link Index#isUnique()} returns true. + * + * @param index + * @param sqlStrings + * @param indexColumnListIds + * @param uniqueColumnListIds + * @param jdbcEnvironment + */ + protected void createIndex(Index index, List sqlStrings, List indexColumnListIds, + List uniqueColumnListIds, JdbcEnvironment jdbcEnvironment) { + if (index.isUnique()) { + createUnique( index, sqlStrings, indexColumnListIds, uniqueColumnListIds, jdbcEnvironment ); + } + else { + if (indexColumnListIds.contains( index.columnListId() )) { + LOG.warnf( "The mapping would have resulted in the creation of duplicate indexes for the following" + + " sequence of columns: %s", index.getColumnNames()); + } + else { + sqlStrings.addAll(Arrays.asList( dialect.getIndexExporter().getSqlCreateStrings( index, jdbcEnvironment ) ) ); + } + indexColumnListIds.add( index.columnListId() ); + } + } + + /** + * Create the unique constraint SQL string for the given {@link UniqueKey} or unique {@link Index}. + * + * @param constraint + * @param sqlStrings + * @param indexColumnListIds + * @param uniqueColumnListIds + * @param jdbcEnvironment + */ + protected void createUnique(AbstractConstraint constraint, List sqlStrings, + List indexColumnListIds, List uniqueColumnListIds, JdbcEnvironment jdbcEnvironment) { + // A unique Index may have already exported the unique constraint. + if (uniqueColumnListIds.contains( constraint.columnListAlphabeticalId() )) { + LOG.warnf( "The mapping would have resulted in the creation of duplicate unique constraints for the" + + " following sequence of columns. Note that Hibernate automatically creates a unique constraint" + + " for a unique index. %s", constraint.getColumnNames()); + } + else { + sqlStrings.addAll(Arrays.asList( dialect.getUniqueKeyExporter().getSqlCreateStrings( + constraint, jdbcEnvironment ) ) ); + } + uniqueColumnListIds.add( constraint.columnListAlphabeticalId() ); + } + + /** + * Generate the list of constraint-dropping SQL strings from the given set of {@link Table}s, if supported + * by {@link Dialect#dropConstraints()}. + * + * @param tables + * @param jdbcEnvironment + * @return String[] The list of constraint-dropping SQL strings. + */ + public String[] dropConstraints(Iterable
    tables, JdbcEnvironment jdbcEnvironment) { + final List sqlStrings = new ArrayList(); + // List of "columnListIds" (hashes of column names), FIFO, used to prevent duplicate index creation. + final List indexColumnListIds = new ArrayList(); + // List of "columnListIds" (hashes of column names), alphabetical, used to prevent duplicate unique constraint creation. + final List uniqueColumnListIds = new ArrayList(); + + if (dialect.dropConstraints()) { + for ( Table table : tables ) { + if( !table.isPhysicalTable() ){ + continue; + } + + for ( Index index : table.getIndexes() ) { + dropIndex( index, sqlStrings, indexColumnListIds, uniqueColumnListIds, jdbcEnvironment ); + } + + for ( UniqueKey uniqueKey : table.getUniqueKeys() ) { + dropUnique( uniqueKey, sqlStrings, indexColumnListIds, uniqueColumnListIds, jdbcEnvironment ); + } + } + } + + return sqlStrings.toArray( new String[sqlStrings.size()] ); + } + + /** + * See {@link #createIndex(Index, List, List, JdbcEnvironment)}. The concepts are the same, except + * this targets dropping. + * + * @param index + * @param sqlStrings + * @param indexColumnListIds + * @param uniqueColumnListIds + * @param jdbcEnvironment + */ + protected void dropIndex(Index index, List sqlStrings, List indexColumnListIds, + List uniqueColumnListIds, JdbcEnvironment jdbcEnvironment) { + if (index.isUnique()) { + dropUnique( index, sqlStrings, indexColumnListIds, uniqueColumnListIds, jdbcEnvironment ); + } + else { + if (! indexColumnListIds.contains( index.columnListId() )) { + sqlStrings.addAll(Arrays.asList( dialect.getIndexExporter().getSqlDropStrings( index, jdbcEnvironment ) ) ); + } + indexColumnListIds.add( index.columnListId() ); + } + } + + /** + * See {@link #createUnique(AbstractConstraint, List, List, JdbcEnvironment)}. The concepts are the same, except + * this targets dropping. + * + * @param constraint + * @param sqlStrings + * @param indexColumnListIds + * @param uniqueColumnListIds + * @param jdbcEnvironment + */ + protected void dropUnique(AbstractConstraint constraint, List sqlStrings, List indexColumnListIds, + List uniqueColumnListIds, JdbcEnvironment jdbcEnvironment) { + // A unique Index may have already exported the constraint. + if (! uniqueColumnListIds.contains( constraint.columnListAlphabeticalId() )) { + sqlStrings.addAll(Arrays.asList( dialect.getUniqueKeyExporter().getSqlDropStrings( + constraint, jdbcEnvironment ) ) ); + } + uniqueColumnListIds.add( constraint.columnListAlphabeticalId() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/DB2UniqueKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/DB2UniqueKeyExporter.java new file mode 100644 index 000000000000..80e58a36ea76 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/DB2UniqueKeyExporter.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.dialect.constraint; + +import java.util.Iterator; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.internal.StandardUniqueKeyExporter; + +/** + * DB2 does not allow unique constraints on nullable columns. Rather than + * forcing "not null", instead use unique indexes on nullables. + * + * @author Brett Meyer + */ +public class DB2UniqueKeyExporter extends StandardUniqueKeyExporter { + private final Dialect dialect; + + public DB2UniqueKeyExporter(Dialect dialect) { + super( dialect ); + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + if ( hasNullable( constraint ) ) { + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) constraint.getTable() ).getTableName() ); + StringBuilder sb = new StringBuilder() + .append( "create unique index " ) + .append( constraint.getName().getText( dialect ) ) + .append( " on " ) + .append( tableName ) + .append( " (" ); + final Iterator columnIterator = constraint.getColumns().iterator(); + while ( columnIterator.hasNext() ) { + Column column = (Column) columnIterator.next(); + sb.append( column.getColumnName().getText( dialect ) ); + if ( columnIterator.hasNext() ) { + sb.append( ", " ); + } + } + sb.append( ")" ); + return new String[] { sb.toString() }; + } + else { + return super.getSqlCreateStrings( constraint, jdbcEnvironment ); + } + } + + @Override + public String[] getSqlDropStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + if ( hasNullable( constraint ) ) { + return new String[] { "drop index " + constraint.getName().getText( dialect ) }; + } + else { + return super.getSqlDropStrings( constraint, jdbcEnvironment ); + } + } + + private boolean hasNullable(Constraint constraint) { + for ( Column column : constraint.getColumns() ) { + if ( column.isNullable() ) { + return true; + } + } + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/InformixUniqueKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/InformixUniqueKeyExporter.java new file mode 100644 index 000000000000..b030bd45a038 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/InformixUniqueKeyExporter.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect.constraint; + +import java.util.Iterator; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.internal.StandardUniqueKeyExporter; + +/** + * Informix requires the constraint name to come last on the alter table. + * + * @author Brett Meyer + */ +public class InformixUniqueKeyExporter extends StandardUniqueKeyExporter { + private final Dialect dialect; + + public InformixUniqueKeyExporter(Dialect dialect) { + super( dialect ); + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) constraint.getTable() ).getTableName() + ); + StringBuilder sb = new StringBuilder() + .append( "alter table " ) + .append( tableName ) + .append( " add constraint " ) + .append( " unique ( " ); + + final Iterator columnIterator = constraint.getColumns().iterator(); + while ( columnIterator.hasNext() ) { + Column column = (Column) columnIterator.next(); + sb.append( column.getColumnName().getText( dialect ) ); + if ( columnIterator.hasNext() ) { + sb.append( ", " ); + } + } + + sb.append( ")" ) + .append( " constraint " ) + .append( constraint.getName().getText( dialect ) ); + return new String[] { sb.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java new file mode 100644 index 000000000000..6fc849e0270e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect.constraint; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.internal.StandardIndexExporter; + +/** + * MySQL requires "ON table" at the end of a "DROP INDEX". + * + * TODO: If other Dialects need that as well, consider adding a "requiresOnTable" type of method on Dialect and + * work it into StandardIndexExporter itself. + * + * @author Brett Meyer + */ +public class MySQLIndexExporter extends StandardIndexExporter { + private final Dialect dialect; + + public MySQLIndexExporter(Dialect dialect) { + super(dialect); + this.dialect = dialect; + } + + @Override + public String[] getSqlDropStrings(Index index, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) index.getTable() ).getTableName() + ); + + StringBuilder sb = new StringBuilder(); + sb.append( "drop index " ); + sb.append( ( dialect.qualifyIndexName() + ? index.getName().getQualifiedText( tableName, dialect ) : index.getName() ) ); + sb.append( " on " + tableName ); + + return new String[] { sb.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java new file mode 100644 index 000000000000..b1ba5f4f47cc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect.constraint; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.internal.StandardUniqueKeyExporter; + +/** + * MySQL does not support "DROP CONSTRAINT". Must use "DROP INDEX" instead. + * + * @author Brett Meyer + */ +public class MySQLUniqueKeyExporter extends StandardUniqueKeyExporter { + private final Dialect dialect; + + public MySQLUniqueKeyExporter(Dialect dialect) { + super( dialect ); + this.dialect = dialect; + } + + @Override + public String[] getSqlDropStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) constraint.getTable() ).getTableName() + ); + final StringBuilder sb = new StringBuilder( "alter table " ); + sb.append( tableName ); + sb.append(" drop index " ); + if ( dialect.supportsIfExistsBeforeConstraintName() ) { + sb.append( "if exists " ); + } + sb.append( constraint.getName().getText( dialect ) ); + if ( dialect.supportsIfExistsAfterConstraintName() ) { + sb.append( " if exists" ); + } + return new String[] { sb.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java index d145854bc7c5..19f5c0c1996b 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastFunction.java @@ -36,6 +36,11 @@ * @author Gavin King */ public class CastFunction implements SQLFunction { + /** + * Singleton access + */ + public static final CastFunction INSTANCE = new CastFunction(); + @Override public boolean hasArguments() { return true; @@ -55,7 +60,7 @@ public Type getReturnType(Type columnType, Mapping mapping) throws QueryExceptio @Override public String render(Type columnType, List args, SessionFactoryImplementor factory) throws QueryException { if ( args.size()!=2 ) { - throw new QueryException("cast() requires two arguments"); + throw new QueryException( "cast() requires two arguments; found : " + args.size() ); } final String type = (String) args.get( 1 ); final int[] sqlTypeCodes = factory.getTypeResolver().heuristicType( type ).sqlTypes( factory ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/StandardAnsiSqlAggregationFunctions.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/StandardAnsiSqlAggregationFunctions.java index 862173fcba8f..a8fd8abb0fdd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/StandardAnsiSqlAggregationFunctions.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/StandardAnsiSqlAggregationFunctions.java @@ -30,6 +30,7 @@ import org.hibernate.MappingException; import org.hibernate.QueryException; +import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.type.StandardBasicTypes; @@ -58,15 +59,16 @@ protected CountFunction() { public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) { if ( arguments.size() > 1 ) { if ( "distinct".equalsIgnoreCase( arguments.get( 0 ).toString() ) ) { - return renderCountDistinct( arguments ); + return renderCountDistinct( arguments, factory.getDialect() ); } } return super.render( firstArgumentType, arguments, factory ); } - private String renderCountDistinct(List arguments) { + private String renderCountDistinct(List arguments, Dialect dialect) { final StringBuilder buffer = new StringBuilder(); buffer.append( "count(distinct " ); + if (dialect.requiresParensForTupleDistinctCounts()) buffer.append("("); String sep = ""; final Iterator itr = arguments.iterator(); // intentionally skip first @@ -75,6 +77,7 @@ private String renderCountDistinct(List arguments) { buffer.append( sep ).append( itr.next() ); sep = ", "; } + if (dialect.requiresParensForTupleDistinctCounts()) buffer.append(")"); return buffer.append( ")" ).toString(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/AbstractLimitHandler.java b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/AbstractLimitHandler.java index 8b80ea170b99..87248071c310 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/AbstractLimitHandler.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/AbstractLimitHandler.java @@ -11,7 +11,7 @@ * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ public abstract class AbstractLimitHandler implements LimitHandler { - protected final String sql; + protected String sql; protected final RowSelection selection; /** diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/FirstLimitHandler.java b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/FirstLimitHandler.java new file mode 100644 index 000000000000..a49d6d6d193a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/FirstLimitHandler.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.dialect.pagination; + +import org.hibernate.engine.spi.RowSelection; + + +/** + * @author Brett Meyer + */ +public class FirstLimitHandler extends AbstractLimitHandler { + + public FirstLimitHandler(String sql, RowSelection selection) { + super(sql, selection); + } + + @Override + public String getProcessedSql() { + boolean hasOffset = LimitHelper.hasFirstRow(selection); + if ( hasOffset ) { + throw new UnsupportedOperationException( "query result offset is not supported" ); + } + return new StringBuilder( sql.length() + 16 ) + .append( sql ) + .insert( sql.toLowerCase().indexOf( "select" ) + 6, " first ?" ) + .toString(); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + + @Override + public boolean supportsLimitOffset() { + return false; + } + + @Override + public boolean supportsVariableLimit() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/LegacyLimitHandler.java b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/LegacyLimitHandler.java index 9385e7ac6012..d81711e6b6d8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/LegacyLimitHandler.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/LegacyLimitHandler.java @@ -31,9 +31,7 @@ * * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ -@SuppressWarnings("deprecation") public class LegacyLimitHandler extends AbstractLimitHandler { - private final Dialect dialect; /** * Constructs a LegacyLimitHandler @@ -44,47 +42,46 @@ public class LegacyLimitHandler extends AbstractLimitHandler { */ public LegacyLimitHandler(Dialect dialect, String sql, RowSelection selection) { super( sql, selection ); - this.dialect = dialect; } @Override public boolean supportsLimit() { - return dialect.supportsLimit(); + return false; } @Override public boolean supportsLimitOffset() { - return dialect.supportsLimitOffset(); + return supportsLimit(); } @Override public boolean supportsVariableLimit() { - return dialect.supportsVariableLimit(); + return supportsLimit(); } @Override public boolean bindLimitParametersInReverseOrder() { - return dialect.bindLimitParametersInReverseOrder(); + return false; } @Override public boolean bindLimitParametersFirst() { - return dialect.bindLimitParametersFirst(); + return false; } @Override public boolean useMaxForLimit() { - return dialect.useMaxForLimit(); + return false; } @Override public boolean forceLimitUsage() { - return dialect.forceLimitUsage(); + return false; } @Override public int convertToFirstRowValue(int zeroBasedFirstResult) { - return dialect.convertToFirstRowValue( zeroBasedFirstResult ); + return zeroBasedFirstResult; } @Override @@ -93,10 +90,6 @@ public String getProcessedSql() { && supportsLimitOffset() && LimitHelper.hasFirstRow( selection ) && LimitHelper.hasMaxRows( selection ); - return dialect.getLimitString( - sql, - useLimitOffset ? LimitHelper.getFirstRow( selection ) : 0, - getMaxOrLimit() - ); + throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName()); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/SQL2008StandardLimitHandler.java b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/SQL2008StandardLimitHandler.java new file mode 100644 index 000000000000..20fed29e2c5b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/SQL2008StandardLimitHandler.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect.pagination; + +import org.hibernate.engine.spi.RowSelection; + +/** + * LIMIT clause handler compatible with ISO and ANSI SQL:2008 standard. + * + * @author zhouyanming (zhouyanming@gmail.com) + */ +public class SQL2008StandardLimitHandler extends AbstractLimitHandler { + + /** + * Constructs a SQL2008StandardLimitHandler + * + * @param sql + * The SQL + * @param selection + * The row selection options + */ + public SQL2008StandardLimitHandler(String sql, RowSelection selection) { + super(sql, selection); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public String getProcessedSql() { + if (LimitHelper.useLimit(this, selection)) { + return sql + (LimitHelper.hasFirstRow(selection) ? + " offset ? rows fetch next ? rows only" : " fetch first ? rows only"); + } else { + // or return unaltered SQL + return sql; + } + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/pagination/TopLimitHandler.java b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/TopLimitHandler.java new file mode 100644 index 000000000000..2515dce8226e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/pagination/TopLimitHandler.java @@ -0,0 +1,76 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.dialect.pagination; + +import org.hibernate.engine.spi.RowSelection; + + +/** + * @author Brett Meyer + */ +public class TopLimitHandler extends AbstractLimitHandler { + + private final boolean supportsVariableLimit; + + private final boolean bindLimitParametersFirst; + + public TopLimitHandler(String sql, RowSelection selection, + boolean supportsVariableLimit, boolean bindLimitParametersFirst) { + super(sql, selection); + this.supportsVariableLimit = supportsVariableLimit; + this.bindLimitParametersFirst = bindLimitParametersFirst; + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean useMaxForLimit() { + return true; + } + + @Override + public boolean supportsLimitOffset() { + return supportsVariableLimit; + } + + public boolean bindLimitParametersFirst() { + return bindLimitParametersFirst; + } + + @Override + public String getProcessedSql() { + if ( LimitHelper.hasFirstRow(selection) ) { + throw new UnsupportedOperationException( "query result offset is not supported" ); + } + + final int selectIndex = sql.toLowerCase().indexOf( "select" ); + final int selectDistinctIndex = sql.toLowerCase().indexOf( "select distinct" ); + final int insertionPoint = selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6); + + return new StringBuilder( sql.length() + 8 ) + .append( sql ) + .insert( insertionPoint, " TOP ? " ) + .toString(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java deleted file mode 100644 index 920e885a5e0d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DB2UniqueDelegate.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.dialect.unique; - -import java.util.Iterator; - -import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Index; -import org.hibernate.metamodel.relational.UniqueKey; - -/** - * DB2 does not allow unique constraints on nullable columns. Rather than - * forcing "not null", use unique *indexes* instead. - * - * @author Brett Meyer - */ -public class DB2UniqueDelegate extends DefaultUniqueDelegate { - /** - * Constructs a DB2UniqueDelegate - * - * @param dialect The dialect - */ - public DB2UniqueDelegate( Dialect dialect ) { - super( dialect ); - } - - @Override - public String getAlterTableToAddUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, - String defaultSchema) { - if ( hasNullable( uniqueKey ) ) { - return org.hibernate.mapping.Index.buildSqlCreateIndexString( - dialect, - uniqueKey.getName(), - uniqueKey.getTable(), - uniqueKey.columnIterator(), - uniqueKey.getColumnOrderMap(), - true, - defaultCatalog, - defaultSchema - ); - } - else { - return super.getAlterTableToAddUniqueKeyCommand( uniqueKey, defaultCatalog, defaultSchema ); - } - } - - @Override - public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) { - if ( hasNullable( uniqueKey ) ) { - return Index.buildSqlCreateIndexString( - dialect, - uniqueKey.getName(), - uniqueKey.getTable(), - uniqueKey.getColumns(), - true - ); - } - else { - return super.getAlterTableToAddUniqueKeyCommand( uniqueKey ); - } - } - - @Override - public String getAlterTableToDropUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, - String defaultSchema) { - if ( hasNullable( uniqueKey ) ) { - return org.hibernate.mapping.Index.buildSqlDropIndexString( - dialect, - uniqueKey.getTable(), - uniqueKey.getName(), - defaultCatalog, - defaultSchema - ); - } - else { - return super.getAlterTableToDropUniqueKeyCommand( - uniqueKey, defaultCatalog, defaultSchema - ); - } - } - - @Override - public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey) { - if ( hasNullable( uniqueKey ) ) { - return Index.buildSqlDropIndexString( dialect, uniqueKey.getTable(), uniqueKey.getName() ); - } - else { - return super.getAlterTableToDropUniqueKeyCommand( uniqueKey ); - } - } - - private boolean hasNullable(org.hibernate.mapping.UniqueKey uniqueKey) { - final Iterator iter = uniqueKey.columnIterator(); - while ( iter.hasNext() ) { - if ( iter.next().isNullable() ) { - return true; - } - } - return false; - } - - private boolean hasNullable(UniqueKey uniqueKey) { - for ( Column column : uniqueKey.getColumns() ) { - if ( column.isNullable() ) { - return true; - } - } - return false; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java deleted file mode 100644 index b65fa4e9bd5e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/DefaultUniqueDelegate.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.dialect.unique; - -import java.util.Iterator; - -import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.UniqueKey; - -/** - * The default UniqueDelegate implementation for most dialects. Uses - * separate create/alter statements to apply uniqueness to a column. - * - * @author Brett Meyer - */ -public class DefaultUniqueDelegate implements UniqueDelegate { - protected final Dialect dialect; - - /** - * Constructs DefaultUniqueDelegate - * - * @param dialect The dialect for which we are handling unique constraints - */ - public DefaultUniqueDelegate( Dialect dialect ) { - this.dialect = dialect; - } - - // legacy model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public String getColumnDefinitionUniquenessFragment(org.hibernate.mapping.Column column) { - return ""; - } - - @Override - public String getTableCreationUniqueConstraintsFragment(org.hibernate.mapping.Table table) { - return ""; - } - - @Override - public String getAlterTableToAddUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, - String defaultSchema) { - // Do this here, rather than allowing UniqueKey/Constraint to do it. - // We need full, simplified control over whether or not it happens. - final String tableName = uniqueKey.getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ); - final String constraintName = dialect.quote( uniqueKey.getName() ); - return "alter table " + tableName + " add constraint " + constraintName + " " + uniqueConstraintSql( uniqueKey ); - } - - protected String uniqueConstraintSql( org.hibernate.mapping.UniqueKey uniqueKey ) { - final StringBuilder sb = new StringBuilder(); - sb.append( " unique (" ); - final Iterator columnIterator = uniqueKey.columnIterator(); - while ( columnIterator.hasNext() ) { - final org.hibernate.mapping.Column column = columnIterator.next(); - sb.append( column.getQuotedName( dialect ) ); - if ( uniqueKey.getColumnOrderMap().containsKey( column ) ) { - sb.append( " " ).append( uniqueKey.getColumnOrderMap().get( column ) ); - } - if ( columnIterator.hasNext() ) { - sb.append( ", " ); - } - } - - return sb.append( ')' ).toString(); - } - - @Override - public String getAlterTableToDropUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, - String defaultSchema) { - // Do this here, rather than allowing UniqueKey/Constraint to do it. - // We need full, simplified control over whether or not it happens. - final StringBuilder buf = new StringBuilder( "alter table " ); - buf.append( uniqueKey.getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ) ); - buf.append(" drop constraint " ); - if ( dialect.supportsIfExistsBeforeConstraintName() ) { - buf.append( "if exists " ); - } - buf.append( dialect.quote( uniqueKey.getName() ) ); - if ( dialect.supportsIfExistsAfterConstraintName() ) { - buf.append( " if exists" ); - } - return buf.toString(); - } - - - // new model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public String getColumnDefinitionUniquenessFragment(Column column) { - return ""; - } - - @Override - public String getTableCreationUniqueConstraintsFragment(Table table) { - return ""; - } - - - @Override - public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) { - // Do this here, rather than allowing UniqueKey/Constraint to do it. - // We need full, simplified control over whether or not it happens. - final String tableName = uniqueKey.getTable().getQualifiedName( dialect ); - final String constraintName = dialect.quote( uniqueKey.getName() ); - - return "alter table " + tableName + " add constraint " + constraintName + uniqueConstraintSql( uniqueKey ); - } - - protected String uniqueConstraintSql( UniqueKey uniqueKey ) { - final StringBuilder sb = new StringBuilder( " unique (" ); - final Iterator columnIterator = uniqueKey.getColumns().iterator(); - while ( columnIterator.hasNext() ) { - final org.hibernate.mapping.Column column = (org.hibernate.mapping.Column) columnIterator.next(); - sb.append( column.getQuotedName( dialect ) ); - if ( columnIterator.hasNext() ) { - sb.append( ", " ); - } - } - - return sb.append( ')' ).toString(); - } - - @Override - public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey) { - // Do this here, rather than allowing UniqueKey/Constraint to do it. - // We need full, simplified control over whether or not it happens. - final String tableName = uniqueKey.getTable().getQualifiedName( dialect ); - final String constraintName = dialect.quote( uniqueKey.getName() ); - - return "alter table " + tableName + " drop constraint " + constraintName; - } - - -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java deleted file mode 100644 index 8a00c411dd43..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/InformixUniqueDelegate.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.dialect.unique; - -import org.hibernate.dialect.Dialect; -import org.hibernate.metamodel.relational.UniqueKey; - -/** - * Informix requires the constraint name to come last on the alter table. - * - * @author Brett Meyer - */ -public class InformixUniqueDelegate extends DefaultUniqueDelegate { - - public InformixUniqueDelegate( Dialect dialect ) { - super( dialect ); - } - - // legacy model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public String getAlterTableToAddUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, - String defaultSchema) { - // Do this here, rather than allowing UniqueKey/Constraint to do it. - // We need full, simplified control over whether or not it happens. - final String tableName = uniqueKey.getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ); - final String constraintName = dialect.quote( uniqueKey.getName() ); - return "alter table " + tableName + " add constraint " + uniqueConstraintSql( uniqueKey ) + " constraint " + constraintName; - } - - // new model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) { - // Do this here, rather than allowing UniqueKey/Constraint to do it. - // We need full, simplified control over whether or not it happens. - final String tableName = uniqueKey.getTable().getQualifiedName( dialect ); - final String constraintName = dialect.quote( uniqueKey.getName() ); - - return "alter table " + tableName + " add constraint " + uniqueConstraintSql( uniqueKey ) + " constraint " + constraintName; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java deleted file mode 100644 index 156ee1714454..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/UniqueDelegate.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.dialect.unique; - -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.UniqueKey; - -/** - * Dialect-level delegate in charge of applying "uniqueness" to a column. Uniqueness can be defined - * in 1 of 3 ways:
      - *
    1. - * Add a unique constraint via separate alter table statements. See {@link #getAlterTableToAddUniqueKeyCommand}. - * Also, see {@link #getAlterTableToDropUniqueKeyCommand} - *
    2. - *
    3. - * Add a unique constraint via dialect-specific syntax in table create statement. See - * {@link #getTableCreationUniqueConstraintsFragment} - *
    4. - *
    5. - * Add "unique" syntax to the column itself. See {@link #getColumnDefinitionUniquenessFragment} - *
    6. - *
    - * - * #1 & #2 are preferred, if possible; #3 should be solely a fall-back. - * - * See HHH-7797. - * - * @author Brett Meyer - */ -public interface UniqueDelegate { - /** - * Get the fragment that can be used to make a column unique as part of its column definition. - *

    - * This is intended for dialects which do not support unique constraints - * - * @param column The column to which to apply the unique - * - * @return The fragment (usually "unique"), empty string indicates the uniqueness will be indicated using a - * different approach - */ - public String getColumnDefinitionUniquenessFragment(org.hibernate.mapping.Column column); - - /** - * Get the fragment that can be used to make a column unique as part of its column definition. - *

    - * This is intended for dialects which do not support unique constraints - * - * @param column The column to which to apply the unique - * - * @return The fragment (usually "unique"), empty string indicates the uniqueness will be indicated using a - * different approach - */ - public String getColumnDefinitionUniquenessFragment(Column column); - - /** - * Get the fragment that can be used to apply unique constraints as part of table creation. The implementation - * should iterate over the {@link org.hibernate.mapping.UniqueKey} instances for the given table (see - * {@link org.hibernate.mapping.Table#getUniqueKeyIterator()} and generate the whole fragment for all - * unique keys - *

    - * Intended for Dialects which support unique constraint definitions, but just not in separate ALTER statements. - * - * @param table The table for which to generate the unique constraints fragment - * - * @return The fragment, typically in the form {@code ", unique(col1, col2), unique( col20)"}. NOTE: The leading - * comma is important! - */ - public String getTableCreationUniqueConstraintsFragment(org.hibernate.mapping.Table table); - - /** - * Get the fragment that can be used to apply unique constraints as part of table creation. The implementation - * should iterate over the {@link org.hibernate.mapping.UniqueKey} instances for the given table (see - * {@link org.hibernate.mapping.Table#getUniqueKeyIterator()} and generate the whole fragment for all - * unique keys - *

    - * Intended for Dialects which support unique constraint definitions, but just not in separate ALTER statements. - * - * @param table The table for which to generate the unique constraints fragment - * - * @return The fragment, typically in the form {@code ", unique(col1, col2), unique( col20)"}. NOTE: The leading - * comma is important! - */ - public String getTableCreationUniqueConstraintsFragment(Table table); - - /** - * Get the SQL ALTER TABLE command to be used to create the given UniqueKey. - * - * @param uniqueKey The UniqueKey instance. Contains all information about the columns - * @param defaultCatalog The default catalog - * @param defaultSchema The default schema - * - * @return The ALTER TABLE command - */ - public String getAlterTableToAddUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, - String defaultSchema); - - /** - * Get the SQL ALTER TABLE command to be used to create the given UniqueKey. - * - * @param uniqueKey The UniqueKey instance. Contains all information about the columns, as well as - * schema/catalog - * - * @return The ALTER TABLE command - */ - public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey); - - /** - * Get the SQL ALTER TABLE command to be used to drop the given UniqueKey. - * - * @param uniqueKey The UniqueKey instance. Contains all information about the columns - * @param defaultCatalog The default catalog - * @param defaultSchema The default schema - * - * @return The ALTER TABLE command - */ - public String getAlterTableToDropUniqueKeyCommand( - org.hibernate.mapping.UniqueKey uniqueKey, - String defaultCatalog, String defaultSchema); - - /** - * Get the SQL ALTER TABLE command to be used to drop the given UniqueKey. - * - * @param uniqueKey The UniqueKey instance. Contains all information about the columns, as well as - * schema/catalog - * - * @return The ALTER TABLE command - */ - public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey); -} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/unique/package-info.java b/hibernate-core/src/main/java/org/hibernate/dialect/unique/package-info.java deleted file mode 100644 index 231e7630e7f4..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/dialect/unique/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Support for Dialect-specific unique constraint definition - */ -package org.hibernate.dialect.unique; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java b/hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java new file mode 100644 index 000000000000..c7ac6ce85094 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/config/spi/StandardConverters.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.config.spi; + + +import static org.hibernate.engine.config.spi.ConfigurationService.Converter; + +/** + * Standard set of setting converters + * + * @author Steve Ebersole + */ +public class StandardConverters { + public static final Converter BOOLEAN = new Converter() { + @Override + public Boolean convert(Object value) { + if ( value == null ) { + throw new IllegalArgumentException( "Null value passed to convert" ); + } + + return Boolean.class.isInstance( value ) + ? Boolean.class.cast( value ) + : Boolean.parseBoolean( value.toString() ); + } + }; + + public static final Converter STRING = new Converter() { + @Override + public String convert(Object value) { + if ( value == null ) { + throw new IllegalArgumentException( "Null value passed to convert" ); + } + + return value.toString(); + } + }; + + /** + * Disallow direct instantiation + */ + private StandardConverters() { + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java index b208c74692c6..3ddc2cc31e2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java @@ -27,7 +27,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.Iterator; -import java.util.Stack; import org.hibernate.HibernateException; import org.hibernate.collection.spi.PersistentCollection; @@ -59,6 +58,7 @@ public final class Cascade { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( Cascade.class ); + private int componentPathStackDepth = 0; private final CascadingAction action; private final EventSource eventSource; private CascadePoint cascadePoint; @@ -183,7 +183,7 @@ else if ( type.isComponentType() ) { final EntityEntry entry = eventSource.getPersistenceContext().getEntry( parent ); if ( entry != null && entry.getStatus() != Status.SAVING ) { final Object loadedValue; - if ( componentPathStack.isEmpty() ) { + if ( componentPathStackDepth == 0 ) { // association defined on entity loadedValue = entry.getLoadedValue( propertyName ); } @@ -222,7 +222,7 @@ else if ( type.isComponentType() ) { } if (type.isAssociationType() && ((AssociationType)type).getForeignKeyDirection().equals( - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT )) { + ForeignKeyDirection.TO_PARENT )) { // If FK direction is to-parent, we must remove the orphan *before* the queued update(s) // occur. Otherwise, replacing the association on a managed entity, without manually // nulling and flushing, causes FK constraint violations. @@ -251,8 +251,6 @@ private boolean isLogicalOneToOne(Type type) { return type.isEntityType() && ( (EntityType) type ).isLogicalOneToOne(); } - private Stack componentPathStack = new Stack(); - private boolean cascadeAssociationNow(AssociationType associationType) { return associationType.getForeignKeyDirection().cascadeNow( cascadePoint ); } @@ -263,7 +261,7 @@ private void cascadeComponent( final CompositeType componentType, final String componentPropertyName, final Object anything) { - componentPathStack.push( componentPropertyName ); + componentPathStackDepth++; final Object[] children = componentType.getPropertyValues( child, eventSource ); final Type[] types = componentType.getSubtypes(); for ( int i=0; i T unwrap(Class unwrapType) { @Override public Connection getConnection() throws SQLException { - throw new UnsupportedOperationException( "The application must supply JDBC connections" ); + throw new UserSuppliedConnectionException(); } @Override public void closeConnection(Connection conn) throws SQLException { - throw new UnsupportedOperationException( "The application must supply JDBC connections" ); + throw new UserSuppliedConnectionException(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java new file mode 100644 index 000000000000..0b4493c8bca7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/JdbcConnectionAccess.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.connections.spi; + +import java.io.Serializable; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Provides centralized access to JDBC connections. Centralized to hide the complexity of accounting for contextual + * (multi-tenant) versus non-contextual access. + * + * @author Steve Ebersole + */ +public interface JdbcConnectionAccess extends Serializable { + /** + * Obtain a JDBC connection + * + * @return The obtained connection + * + * @throws SQLException Indicates a problem getting the connection + */ + public Connection obtainConnection() throws SQLException; + + /** + * Release a previously obtained connection + * + * @param connection The connection to release + * + * @throws SQLException Indicates a problem releasing the connection + */ + public void releaseConnection(Connection connection) throws SQLException; + + /** + * Does the underlying provider of connections support aggressive releasing of connections (and re-acquisition + * of those connections later, if need be) in JTA environments? + * + * @see org.hibernate.engine.jdbc.connections.spi.ConnectionProvider#supportsAggressiveRelease() + * @see org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider#supportsAggressiveRelease() + */ + public boolean supportsAggressiveRelease(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java index 242648f59651..5898923f1b34 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java @@ -42,6 +42,7 @@ import org.hibernate.dialect.MySQL5Dialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.Oracle10gDialect; +import org.hibernate.dialect.Oracle12cDialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.Oracle9iDialect; import org.hibernate.dialect.PostgreSQL81Dialect; @@ -131,7 +132,7 @@ else if ( majorVersion == 10 && minorVersion == 5 ) { return new DerbyTenFiveDialect(); } else { - return new DerbyDialect(); + return new DB2Dialect(); } } @@ -195,6 +196,8 @@ else if ( majorVersion == 10 && minorVersion == 5 ) { final int majorVersion = info.getDatabaseMajorVersion(); switch ( majorVersion ) { + case 12: + return new Oracle12cDialect(); case 11: return new Oracle10gDialect(); case 10: diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java new file mode 100644 index 000000000000..31af134bbb33 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; + +/** + * Default implementation + * + * @author Steve Ebersole + */ +public class DefaultSchemaNameResolver implements SchemaNameResolver { + public static final DefaultSchemaNameResolver INSTANCE = new DefaultSchemaNameResolver(); + + @Override + public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException { + Statement statement = connection.createStatement(); + try { + ResultSet resultSet = statement.executeQuery( dialect.getCurrentSchemaCommand() ); + try { + if ( ! resultSet.next() ) { + return null; + } + return resultSet.getString( 1 ); + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + } + finally { + try { + statement.close(); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java new file mode 100644 index 000000000000..d3041da95f2b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java @@ -0,0 +1,142 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.SQLStateType; + +/** + * Standard implementation of ExtractedDatabaseMetaData + * + * @author Steve Ebersole + */ +public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData { + private final JdbcEnvironment jdbcEnvironment; + + private final boolean supportsRefCursors; + private final boolean supportsNamedParameters; + private final boolean supportsScrollableResults; + private final boolean supportsGetGeneratedKeys; + private final boolean supportsBatchUpdates; + private final boolean supportsDataDefinitionInTransaction; + private final boolean doesDataDefinitionCauseTransactionCommit; + private final SQLStateType sqlStateType; + private final boolean lobLocatorUpdateCopy; + + /** + * Form used when {@link java.sql.DatabaseMetaData} is not available. + * + * @param jdbcEnvironment The JDBC environment containing this metadata. + */ + public ExtractedDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment) { + this.jdbcEnvironment = jdbcEnvironment; + + // if possible, set values that will allow things to still work.... + this.supportsRefCursors = false; // Java 8 feature, safest to say not. + this.supportsNamedParameters = false; + this.supportsScrollableResults = false; + this.supportsGetGeneratedKeys = false; + this.supportsBatchUpdates = false; + this.sqlStateType = SQLStateType.UNKNOWN; + this.lobLocatorUpdateCopy = false; + + // ugh my favorites... + this.supportsDataDefinitionInTransaction = true; + this.doesDataDefinitionCauseTransactionCommit = false; + } + + public ExtractedDatabaseMetaDataImpl( + JdbcEnvironmentImpl jdbcEnvironment, + boolean supportsRefCursors, + boolean supportsNamedParameters, + boolean supportsScrollableResults, + boolean supportsGetGeneratedKeys, + boolean supportsBatchUpdates, + boolean supportsDataDefinitionInTransaction, + boolean doesDataDefinitionCauseTransactionCommit, + SQLStateType sqlStateType, + boolean lobLocatorUpdateCopy) { + this.jdbcEnvironment = jdbcEnvironment; + this.supportsRefCursors = supportsRefCursors; + this.supportsNamedParameters = supportsNamedParameters; + this.supportsScrollableResults = supportsScrollableResults; + this.supportsGetGeneratedKeys = supportsGetGeneratedKeys; + this.supportsBatchUpdates = supportsBatchUpdates; + this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction; + this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit; + this.sqlStateType = sqlStateType; + this.lobLocatorUpdateCopy = lobLocatorUpdateCopy; + } + + @Override + public boolean supportsRefCursors() { + return supportsRefCursors; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } + + @Override + public boolean supportsNamedParameters() { + return supportsNamedParameters; + } + + @Override + public boolean supportsScrollableResults() { + return supportsScrollableResults; + } + + @Override + public boolean supportsGetGeneratedKeys() { + return supportsGetGeneratedKeys; + } + + @Override + public boolean supportsBatchUpdates() { + return supportsBatchUpdates; + } + + @Override + public boolean supportsDataDefinitionInTransaction() { + return supportsDataDefinitionInTransaction; + } + + @Override + public boolean doesDataDefinitionCauseTransactionCommit() { + return doesDataDefinitionCauseTransactionCommit; + } + + @Override + public SQLStateType getSqlStateType() { + return sqlStateType; + } + + @Override + public boolean doesLobLocatorUpdateCopy() { + return lobLocatorUpdateCopy; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java new file mode 100644 index 000000000000..eb826eaf8294 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java @@ -0,0 +1,334 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.lang.reflect.InvocationTargetException; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.hibernate.boot.registry.selector.spi.StrategySelectionException; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport; +import org.hibernate.engine.jdbc.env.spi.SQLStateType; +import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; +import org.hibernate.engine.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl; +import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; +import org.hibernate.engine.jdbc.spi.TypeInfo; +import org.hibernate.exception.internal.SQLExceptionTypeDelegate; +import org.hibernate.exception.internal.SQLStateConversionDelegate; +import org.hibernate.exception.internal.StandardSQLExceptionConverter; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.spi.ServiceRegistryImplementor; + +/** + * @author Steve Ebersole + */ +public class JdbcEnvironmentImpl implements JdbcEnvironment { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JdbcEnvironmentImpl.class ); + + private final ServiceRegistryImplementor serviceRegistry; + private final Dialect dialect; + + private final SqlExceptionHelper sqlExceptionHelper; + private final ExtractedDatabaseMetaData extractedMetaDataSupport; + private final Set reservedWords; + private final Identifier currentCatalog; + private final Identifier currentSchema; + private final IdentifierHelper identifierHelper; + private final QualifiedObjectNameSupport qualifiedObjectNameSupport; + private final LobCreatorBuilderImpl lobCreatorBuilder; + private final LinkedHashSet typeInfoSet = new LinkedHashSet(); + + /** + * Constructor form used when the JDBC {@link DatabaseMetaData} is not available. + * + * @param serviceRegistry The service registry + * @param dialect The resolved dialect. + */ + public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect) { + this.serviceRegistry = serviceRegistry; + this.dialect = dialect; + + this.sqlExceptionHelper = buildSqlExceptionHelper( dialect ); + this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( this ); + + // make sure reserved-words, current-catalog and current-schema happen before the identifier-helper! + this.reservedWords = dialect.getKeywords(); + this.currentCatalog = Identifier.toIdentifier( + serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING ) + ); + this.currentSchema = Identifier.toIdentifier( + serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING ) + ); + + final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false ); + + // a simple temporary impl that works on H2 + this.identifierHelper = new NormalizingIdentifierHelperImpl( + this, + globallyQuoteIdentifiers, + true, // storesMixedCaseQuotedIdentifiers + false, // storesLowerCaseQuotedIdentifiers + false, // storesUpperCaseQuotedIdentifiers + true, // storesUpperCaseIdentifiers + false // storesLowerCaseIdentifiers + ); + + // again, a simple temporary impl that works on H2 + this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl( + ".", + true, + dialect.openQuote(), + dialect.closeQuote() + ); + + this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(); + + } + + public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect, DatabaseMetaData dbmd) throws SQLException { + this.serviceRegistry = serviceRegistry; + this.dialect = dialect; + + this.sqlExceptionHelper = buildSqlExceptionHelper( dialect ); + + this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( + this, + StandardRefCursorSupport.supportsRefCursors( dbmd ), + dbmd.supportsNamedParameters(), + dbmd.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ), + dbmd.supportsGetGeneratedKeys(), + dbmd.supportsBatchUpdates(), + !dbmd.dataDefinitionIgnoredInTransactions(), + dbmd.dataDefinitionCausesTransactionCommit(), + parseSQLStateType( dbmd.getSQLStateType() ), + dbmd.locatorsUpdateCopy() + ); + + // make sure reserved-words happen before the identifier-helper! + this.reservedWords = buildMergedReservedWords( dialect, dbmd ); + + final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false ); + + this.identifierHelper = new NormalizingIdentifierHelperImpl( + this, + globallyQuoteIdentifiers, + dbmd.storesMixedCaseQuotedIdentifiers(), + dbmd.storesLowerCaseQuotedIdentifiers(), + dbmd.storesUpperCaseQuotedIdentifiers(), + dbmd.storesUpperCaseIdentifiers(), + dbmd.storesLowerCaseIdentifiers() + ); + + // and that current-catalog and current-schema happen after it + this.currentCatalog = determineCurrentCatalog( dbmd ); + this.currentSchema = determineCurrentSchema( dbmd ); + + this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl( + dbmd.getCatalogSeparator(), + dbmd.isCatalogAtStart(), + dialect.openQuote(), + dialect.closeQuote() + ); + + this.typeInfoSet.addAll( TypeInfo.extractTypeInfo( dbmd ) ); + + this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder( + serviceRegistry.getService( ConfigurationService.class ).getSettings(), + dbmd.getConnection() + ); + } + + private SQLStateType parseSQLStateType(int sqlStateType) { + switch ( sqlStateType ) { + case DatabaseMetaData.sqlStateSQL99 : { + return SQLStateType.SQL99; + } + case DatabaseMetaData.sqlStateXOpen : { + return SQLStateType.XOpen; + } + default : { + return SQLStateType.UNKNOWN; + } + } + } + + @SuppressWarnings("deprecation") + private SqlExceptionHelper buildSqlExceptionHelper(Dialect dialect) { + final StandardSQLExceptionConverter sqlExceptionConverter = new StandardSQLExceptionConverter(); + sqlExceptionConverter.addDelegate( dialect.buildSQLExceptionConversionDelegate() ); + sqlExceptionConverter.addDelegate( new SQLExceptionTypeDelegate( dialect ) ); + // todo : vary this based on extractedMetaDataSupport.getSqlStateType() + sqlExceptionConverter.addDelegate( new SQLStateConversionDelegate( dialect ) ); + return new SqlExceptionHelper( sqlExceptionConverter ); + } + + private Identifier determineCurrentCatalog(DatabaseMetaData dbmd) throws SQLException { + String currentCatalogName = dbmd.getConnection().getCatalog(); + if ( currentCatalogName != null ) { + // intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!! + return identifierHelper.fromMetaDataObjectName( currentCatalogName ); + } + else { + currentCatalogName = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING ); + return Identifier.toIdentifier( currentCatalogName ); + } + } + + private Identifier determineCurrentSchema(DatabaseMetaData dbmd) throws SQLException { + String currentSchemaName = locateSchemaNameResolver().resolveSchemaName( dbmd.getConnection(), dialect ); + if ( currentSchemaName != null ) { + // intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!! + return identifierHelper.fromMetaDataObjectName( currentSchemaName ); + } + else { + currentSchemaName = serviceRegistry.getService( ConfigurationService.class ) + .getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING ); + return Identifier.toIdentifier( currentSchemaName ); + } + } + + private SchemaNameResolver locateSchemaNameResolver() { + final Object setting = serviceRegistry.getService( ConfigurationService.class ) + .getSettings() + .get( AvailableSettings.SCHEMA_NAME_RESOLVER ); + try { + return serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy( + SchemaNameResolver.class, + setting, + DefaultSchemaNameResolver.INSTANCE + ); + } + catch ( StrategySelectionException e ) { + final Throwable cause = e.getCause(); + if ( ClassNotFoundException.class.isInstance( cause ) ) { + LOG.unableToLocateConfiguredSchemaNameResolver( + e.getImplementationClassName(), + cause.toString() + ); + } + else if ( InvocationTargetException.class.isInstance( cause ) ) { + LOG.unableToInstantiateConfiguredSchemaNameResolver( + e.getImplementationClassName(), + InvocationTargetException.class.cast( cause ).getTargetException().toString() ); + } + else { + LOG.unableToInstantiateConfiguredSchemaNameResolver( + e.getImplementationClassName(), + cause.toString() ); + } + return null; + } + } + + private Set buildMergedReservedWords(Dialect dialect, DatabaseMetaData dbmd) throws SQLException { + Set reservedWords = new HashSet(); + reservedWords.addAll( dialect.getKeywords() ); + // todo : do we need to explicitly handle SQL:2003 keywords? + reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) ); + return reservedWords; + } + + @Override + public Dialect getDialect() { + return dialect; + } + + @Override + public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() { + return extractedMetaDataSupport; + } + + @Override + public Identifier getCurrentCatalog() { + return currentCatalog; + } + + @Override + public Identifier getCurrentSchema() { + return currentSchema; + } + + @Override + public QualifiedObjectNameSupport getQualifiedObjectNameSupport() { + return qualifiedObjectNameSupport; + } + + @Override + public IdentifierHelper getIdentifierHelper() { + return identifierHelper; + } + + @Override + public Set getReservedWords() { + return reservedWords; + } + + @Override + public SqlExceptionHelper getSqlExceptionHelper() { + return sqlExceptionHelper; + } + + @Override + public LobCreatorBuilder getLobCreatorBuilder() { + return lobCreatorBuilder; + } + + @Override + public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) { + for ( TypeInfo typeInfo : typeInfoSet ) { + if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) { + return typeInfo; + } + } + return null; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java new file mode 100644 index 000000000000..35239903c771 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java @@ -0,0 +1,214 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.HibernateException; +import org.hibernate.MultiTenancyStrategy; +import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; +import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter; +import org.hibernate.engine.jdbc.dialect.spi.DialectFactory; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.service.spi.ServiceRegistryImplementor; + +/** + * @author Steve Ebersole + */ +public class JdbcEnvironmentInitiator implements StandardServiceInitiator { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + JdbcEnvironmentInitiator.class.getName() + ); + + public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator(); + + @Override + public Class getServiceInitiated() { + return JdbcEnvironment.class; + } + + @Override + public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + final DialectFactory dialectFactory = registry.getService( DialectFactory.class ); + + // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value. + // The need for it is intended to be alleviated with future development, thus it is + // not defined as an Environment constant... + // + // it is used to control whether we should consult the JDBC metadata to determine + // certain Settings default values; it is useful to *not* do this when the database + // may not be available (mainly in tools usage). + boolean useJdbcMetadata = ConfigurationHelper.getBoolean( + "hibernate.temp.use_jdbc_metadata_defaults", + configurationValues, + true + ); + + if ( useJdbcMetadata ) { + final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configurationValues, registry ); + try { + final Connection connection = jdbcConnectionAccess.obtainConnection(); + try { + final DatabaseMetaData dbmd = connection.getMetaData(); + if ( log.isDebugEnabled() ) { + log.debugf( + "Database ->\n" + + " name : %s\n" + + " version : %s\n" + + " major : %s\n" + + " minor : %s", + dbmd.getDatabaseProductName(), + dbmd.getDatabaseProductVersion(), + dbmd.getDatabaseMajorVersion(), + dbmd.getDatabaseMinorVersion() + ); + log.debugf( + "Driver ->\n" + + " name : %s\n" + + " version : %s\n" + + " major : %s\n" + + " minor : %s", + dbmd.getDriverName(), + dbmd.getDriverVersion(), + dbmd.getDriverMajorVersion(), + dbmd.getDriverMinorVersion() + ); + log.debugf( "JDBC version : %s.%s", dbmd.getJDBCMajorVersion(), dbmd.getJDBCMinorVersion() ); + } + + Dialect dialect = dialectFactory.buildDialect( + configurationValues, + new DialectResolutionInfoSource() { + @Override + public DialectResolutionInfo getDialectResolutionInfo() { + try { + return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() ); + } + catch ( SQLException sqlException ) { + throw new HibernateException( + "Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use", + sqlException + ); + } + } + } + ); + return new JdbcEnvironmentImpl( + registry, + dialect, + dbmd + ); + } + catch (SQLException e) { + log.unableToObtainConnectionMetadata( e.getMessage() ); + } + finally { + try { + jdbcConnectionAccess.releaseConnection( connection ); + } + catch (SQLException ignore) { + } + } + } + catch (Exception e) { + log.unableToObtainConnectionToQueryMetadata( e.getMessage() ); + } + } + + // if we get here, either we were asked to not use JDBC metadata or accessing the JDBC metadata failed. + return new JdbcEnvironmentImpl( registry, dialectFactory.buildDialect( configurationValues, null ) ); + } + + private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues, ServiceRegistryImplementor registry) { + final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues ); + if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) { + ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class ); + return new ConnectionProviderJdbcConnectionAccess( connectionProvider ); + } + else { + final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class ); + return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider ); + } + } + + private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { + private final ConnectionProvider connectionProvider; + + public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + } + + @Override + public Connection obtainConnection() throws SQLException { + return connectionProvider.getConnection(); + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + connectionProvider.closeConnection( connection ); + } + + @Override + public boolean supportsAggressiveRelease() { + return connectionProvider.supportsAggressiveRelease(); + } + } + + private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { + private final MultiTenantConnectionProvider connectionProvider; + + public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + } + + @Override + public Connection obtainConnection() throws SQLException { + return connectionProvider.getAnyConnection(); + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + connectionProvider.releaseAnyConnection( connection ); + } + + @Override + public boolean supportsAggressiveRelease() { + return connectionProvider.supportsAggressiveRelease(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/LobCreatorBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/LobCreatorBuilderImpl.java new file mode 100644 index 000000000000..e8d70d789659 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/LobCreatorBuilderImpl.java @@ -0,0 +1,163 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Map; + +import org.hibernate.cfg.Environment; +import org.hibernate.engine.jdbc.ContextualLobCreator; +import org.hibernate.engine.jdbc.LobCreationContext; +import org.hibernate.engine.jdbc.LobCreator; +import org.hibernate.engine.jdbc.NonContextualLobCreator; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.config.ConfigurationHelper; + +import org.jboss.logging.Logger; + +/** + * Builds {@link LobCreator} instances based on the capabilities of the environment. + * + * @author Steve Ebersole + */ +public class LobCreatorBuilderImpl implements LobCreatorBuilder { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + LobCreatorBuilderImpl.class.getName() + ); + + private final boolean useContextualLobCreation; + + private LobCreatorBuilderImpl(boolean useContextualLobCreation) { + this.useContextualLobCreation = useContextualLobCreation; + } + + // factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /** + * The public factory method for obtaining the appropriate LOB creator (according to given + * JDBC {@link java.sql.Connection}). + * + * @param configValues The map of settings + * @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support, + * specifically for creating LOB references. + */ + public static LobCreatorBuilderImpl makeLobCreatorBuilder(Map configValues, Connection jdbcConnection) { + return new LobCreatorBuilderImpl( useContextualLobCreation( configValues, jdbcConnection ) ); + } + + /** + * For used when JDBC Connection is not available. + * + * @return Appropriate LobCreatorBuilder + */ + public static LobCreatorBuilderImpl makeLobCreatorBuilder() { + LOG.disablingContextualLOBCreationSinceConnectionNull(); + return new LobCreatorBuilderImpl( false ); + } + + private static final Class[] NO_ARG_SIG = new Class[0]; + private static final Object[] NO_ARGS = new Object[0]; + + /** + * Basically here we are simply checking whether we can call the {@link Connection} methods for + * LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods, + * but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply + * throwing an exception). + * + * @param jdbcConnection The connection which can be used in level-of-support testing. + * + * @return True if the connection can be used to create LOBs; false otherwise. + */ + @SuppressWarnings("unchecked") + private static boolean useContextualLobCreation(Map configValues, Connection jdbcConnection) { + final boolean isNonContextualLobCreationRequired = + ConfigurationHelper.getBoolean( Environment.NON_CONTEXTUAL_LOB_CREATION, configValues ); + if ( isNonContextualLobCreationRequired ) { + LOG.disablingContextualLOBCreation( Environment.NON_CONTEXTUAL_LOB_CREATION ); + return false; + } + if ( jdbcConnection == null ) { + LOG.disablingContextualLOBCreationSinceConnectionNull(); + return false; + } + + try { + try { + final DatabaseMetaData meta = jdbcConnection.getMetaData(); + // if the jdbc driver version is less than 4, it shouldn't have createClob + if ( meta.getJDBCMajorVersion() < 4 ) { + LOG.disablingContextualLOBCreationSinceOldJdbcVersion( meta.getJDBCMajorVersion() ); + return false; + } + } + catch ( SQLException ignore ) { + // ignore exception and continue + } + + final Class connectionClass = Connection.class; + final Method createClobMethod = connectionClass.getMethod( "createClob", NO_ARG_SIG ); + if ( createClobMethod.getDeclaringClass().equals( Connection.class ) ) { + // If we get here we are running in a jdk 1.6 (jdbc 4) environment... + // Further check to make sure the driver actually implements the LOB creation methods. We + // check against createClob() as indicative of all; should we check against all 3 explicitly? + try { + final Object clob = createClobMethod.invoke( jdbcConnection, NO_ARGS ); + try { + final Method freeMethod = clob.getClass().getMethod( "free", NO_ARG_SIG ); + freeMethod.invoke( clob, NO_ARGS ); + } + catch ( Throwable ignore ) { + LOG.tracef( "Unable to free CLOB created to test createClob() implementation : %s", ignore ); + } + return true; + } + catch ( Throwable t ) { + LOG.disablingContextualLOBCreationSinceCreateClobFailed( t ); + } + } + } + catch ( NoSuchMethodException ignore ) { + } + + return false; + } + + /** + * Build a LobCreator using the given context + * + * @param lobCreationContext The LOB creation context + * + * @return The LobCreator + */ + public LobCreator buildLobCreator(LobCreationContext lobCreationContext) { + return useContextualLobCreation + ? new ContextualLobCreator( lobCreationContext ) + : NonContextualLobCreator.INSTANCE; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java new file mode 100644 index 000000000000..7cde16575097 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java @@ -0,0 +1,217 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.internal; + +import org.jboss.logging.Logger; + +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Identifier; + +/** +* @author Steve Ebersole +*/ +public class NormalizingIdentifierHelperImpl implements IdentifierHelper { + private static final Logger log = Logger.getLogger( NormalizingIdentifierHelperImpl.class ); + + private final JdbcEnvironment jdbcEnvironment; + + private final boolean globallyQuoteIdentifiers; + + private final boolean storesMixedCaseQuotedIdentifiers; + private final boolean storesLowerCaseQuotedIdentifiers; + private final boolean storesUpperCaseQuotedIdentifiers; + private final boolean storesUpperCaseIdentifiers; + private final boolean storesLowerCaseIdentifiers; + + public NormalizingIdentifierHelperImpl( + JdbcEnvironment jdbcEnvironment, + boolean globallyQuoteIdentifiers, + boolean storesMixedCaseQuotedIdentifiers, + boolean storesLowerCaseQuotedIdentifiers, + boolean storesUpperCaseQuotedIdentifiers, + boolean storesUpperCaseIdentifiers, + boolean storesLowerCaseIdentifiers) { + this.jdbcEnvironment = jdbcEnvironment; + this.globallyQuoteIdentifiers = globallyQuoteIdentifiers; + this.storesMixedCaseQuotedIdentifiers = storesMixedCaseQuotedIdentifiers; + this.storesLowerCaseQuotedIdentifiers = storesLowerCaseQuotedIdentifiers; + this.storesUpperCaseQuotedIdentifiers = storesUpperCaseQuotedIdentifiers; + this.storesUpperCaseIdentifiers = storesUpperCaseIdentifiers; + this.storesLowerCaseIdentifiers = storesLowerCaseIdentifiers; + + if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in mixed, upper and lower case" ); + } + else if ( storesMixedCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and upper case" ); + } + else if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and lower case" ); + } + + if ( storesUpperCaseIdentifiers && storesLowerCaseIdentifiers ) { + log.warn( "JDBC Driver reports it stores non-quoted identifiers in both upper and lower case" ); + } + + if ( storesUpperCaseIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in upper case" ); + } + + if ( storesLowerCaseIdentifiers && storesLowerCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in lower case" ); + } + } + + // In the DatabaseMetaData method params for catalog and schema name have the following meaning: + // 1) <""> means to match things "without a catalog/schema" + // 2) means to not limit results based on this field + // + // todo : not sure how "without a catalog/schema" is interpreted. Current? + + @Override + public String toMetaDataCatalogName(Identifier identifier) { + if ( identifier == null ) { + // todo : not sure if this is interpreted as <""> or + return jdbcEnvironment.getCurrentCatalog() == null ? null : jdbcEnvironment.getCurrentCatalog().getText(); + } + + return toText( identifier ); + } + + private String toText(Identifier identifier) { + if ( identifier == null ) { + throw new IllegalArgumentException( "Identifier cannot be null; bad usage" ); + } + + if ( identifier.isQuoted() && storesMixedCaseQuotedIdentifiers ) { + return identifier.getText(); + } + else if ( ( identifier.isQuoted() && storesUpperCaseQuotedIdentifiers ) + || ( !identifier.isQuoted() && storesUpperCaseIdentifiers ) ) { + return StringHelper.toUpperCase( identifier.getText() ); + } + else if ( ( identifier.isQuoted() && storesLowerCaseQuotedIdentifiers ) + || ( !identifier.isQuoted() && storesLowerCaseIdentifiers ) ) { + return StringHelper.toLowerCase( identifier.getText() ); + } + return identifier.getText(); + } + + @Override + public String toMetaDataSchemaName(Identifier identifier) { + if ( identifier == null ) { + // todo : not sure if this is interpreted as <""> or + return jdbcEnvironment.getCurrentSchema() == null ? null : jdbcEnvironment.getCurrentSchema().getText(); + } + + return toText( identifier ); + } + + @Override + public String toMetaDataObjectName(Identifier identifier) { + if ( identifier == null ) { + // if this method was called, the value is needed + throw new IllegalArgumentException( ); + } + return toText( identifier ); + } + + @Override + public Identifier fromMetaDataCatalogName(String catalogName) { + if ( catalogName == null ) { + return null; + } + + if ( jdbcEnvironment.getCurrentCatalog() == null + || catalogName.equals( jdbcEnvironment.getCurrentCatalog().getText() ) ) { + return null; + } + + return toIdentifier( catalogName ); + // note really sure the best way to know (can you?) whether the identifier is quoted + + } + + public Identifier toIdentifier(String text) { + if ( globallyQuoteIdentifiers ) { + return Identifier.toIdentifier( text, true ); + } + + // lovely decipher of whether the incoming value represents a quoted identifier... + final boolean isUpperCase = text.toUpperCase().equals( text ); + final boolean isLowerCase = text.toLowerCase().equals( text ); + final boolean isMixedCase = ! isLowerCase && ! isUpperCase; + + if ( jdbcEnvironment.getReservedWords().contains( text ) ) { + // unequivocally it needs to be quoted... + return Identifier.toIdentifier( text, true ); + } + + if ( storesMixedCaseQuotedIdentifiers && isMixedCase ) { + return Identifier.toIdentifier( text, true ); + } + + if ( storesLowerCaseQuotedIdentifiers && isLowerCase ) { + return Identifier.toIdentifier( text, true ); + } + + if ( storesUpperCaseQuotedIdentifiers && isUpperCase ) { + return Identifier.toIdentifier( text, true ); + } + + return Identifier.toIdentifier( text ); + } + + @Override + public Identifier toIdentifier(String text, boolean quoted) { + return globallyQuoteIdentifiers + ? Identifier.toIdentifier( text, true ) + : Identifier.toIdentifier( text, quoted ); + } + + @Override + public Identifier fromMetaDataSchemaName(String schemaName) { + if ( schemaName == null ) { + return null; + } + + if ( jdbcEnvironment.getCurrentSchema() == null + || schemaName.equals( jdbcEnvironment.getCurrentSchema().getText() ) ) { + return null; + } + + return toIdentifier( schemaName ); + } + + @Override + public Identifier fromMetaDataObjectName(String objectName) { + if ( objectName == null ) { + return null; + } + + return toIdentifier( objectName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ExtractedDatabaseMetaData.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ExtractedDatabaseMetaData.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java index f33c096e1395..ad8af7f3896c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ExtractedDatabaseMetaData.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java @@ -21,11 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.engine.jdbc.spi; +package org.hibernate.engine.jdbc.env.spi; import java.util.LinkedHashSet; import java.util.Set; +import org.hibernate.engine.jdbc.spi.TypeInfo; + /** * Information extracted from {@link java.sql.DatabaseMetaData} regarding what the JDBC driver reports as * being supported or not. Obviously {@link java.sql.DatabaseMetaData} reports many things, these are a few in @@ -36,22 +38,11 @@ @SuppressWarnings( {"UnusedDeclaration"}) public interface ExtractedDatabaseMetaData { /** - * Which specification do the reported SQLState codes follow? + * Obtain the JDBC Environment from which this metadata came. + * + * @return The JDBC environment */ - public enum SQLStateType { - /** - * The reported codes follow the X/Open spec - */ - XOpen, - /** - * The reported codes follow the SQL spec - */ - SQL99, - /** - * It is unknown. Might follow another spec completely, or be a mixture. - */ - UNKOWN - } + public JdbcEnvironment getJdbcEnvironment(); /** * Does the driver report supporting named parameters? @@ -116,15 +107,6 @@ public enum SQLStateType { */ public boolean doesDataDefinitionCauseTransactionCommit(); - /** - * Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver. - * - * @return The extra keywords used by this database. - * - * @see java.sql.DatabaseMetaData#getSQLKeywords() - */ - public Set getExtraKeywords(); - /** * Retrieve the type of codes the driver says it uses for {@code SQLState}. They might follow either * the X/Open standard or the SQL92 standard. @@ -143,27 +125,4 @@ public enum SQLStateType { * @see java.sql.DatabaseMetaData#locatorsUpdateCopy() */ public boolean doesLobLocatorUpdateCopy(); - - /** - * Retrieve the name of the schema in effect when we connected to the database. - * - * @return The schema name - */ - public String getConnectionSchemaName(); - - /** - * Retrieve the name of the catalog in effect when we connected to the database. - * - * @return The catalog name - */ - public String getConnectionCatalogName(); - - /** - * Set of type info reported by the driver. - * - * @return The type information obtained from the driver. - * - * @see java.sql.DatabaseMetaData#getTypeInfo() - */ - public LinkedHashSet getTypeInfoSet(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java new file mode 100644 index 000000000000..11a3de36b245 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Helper for handling {@link Identifier} instances. + * + * @author Steve Ebersole + */ +public interface IdentifierHelper { + /** + * Generate an {@link Identifier} instance from its simple name + * + * @param text The text + * + * @return The identifier form of the name. + */ + public Identifier toIdentifier(String text); + + /** + * Generate an {@link Identifier} instance from its simple name and explicitly whether it is quoted or not + * (although note that 'globally quoted identifiers' setting can still cause returned Identifiers to be quoted + * even if {@code false} is passed in here). + * + * @param text The name + * @param quoted Is the identifier to be quoted explicitly. + * + * @return The identifier form of the name. + */ + public Identifier toIdentifier(String text, boolean quoted); + + public String toMetaDataCatalogName(Identifier identifier); + public String toMetaDataSchemaName(Identifier identifier); + public String toMetaDataObjectName(Identifier identifier); + public Identifier fromMetaDataCatalogName(String catalogName); + public Identifier fromMetaDataSchemaName(String schemaName); + public Identifier fromMetaDataObjectName(String objectName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java new file mode 100644 index 000000000000..5e4e4e9c67e1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java @@ -0,0 +1,124 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; +import org.hibernate.engine.jdbc.spi.TypeInfo; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.Service; +import org.hibernate.service.ServiceRegistry; + +/** + * Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData} + * and {@link org.hibernate.dialect.Dialect} + * + * @author Steve Ebersole + */ +public interface JdbcEnvironment extends Service { + /** + * Get the dialect for this environment. + * + * @return The dialect. + */ + public Dialect getDialect(); + + /** + * Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get + * "interpreted" into the helpers/delegates available here). + * + * @return The values extracted from JDBC DatabaseMetaData + */ + public ExtractedDatabaseMetaData getExtractedDatabaseMetaData(); + + /** + * Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()} + * or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}. + * + * @return The current catalog. + */ + public Identifier getCurrentCatalog(); + + /** + * Get the current database catalog. Typically will come from either + * {@link SchemaNameResolver#resolveSchemaName(java.sql.Connection, org.hibernate.dialect.Dialect)} or + * {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}. + * + * @return The current schema + */ + public Identifier getCurrentSchema(); + + /** + * Obtain support for reading and writing qualified object names. + * + * @return Qualified name support. + */ + public QualifiedObjectNameSupport getQualifiedObjectNameSupport(); + + /** + * Obtain the helper for dealing with identifiers in this environment. + * + * @return The identifier helper. + */ + public IdentifierHelper getIdentifierHelper(); + + /** + * Get the complete set of reserved words for this environment. These are significant because they represent + * the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting + * in the metamodel based on these terms. + * + * Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for + * auto-quoting :) yaay! + * + * @return Reserved words + */ + public Set getReservedWords(); + + /** + * Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults. + * + * @return This environment's helper. + */ + public SqlExceptionHelper getSqlExceptionHelper(); + + /** + * Retrieve the delegate for building {@link org.hibernate.engine.jdbc.LobCreator} instances. + * + * @return The LobCreator builder. + */ + public LobCreatorBuilder getLobCreatorBuilder(); + + /** + * Find type information for the type identified by the given "JDBC type code". + * + * @param jdbcTypeCode The JDBC type code. + * + * @return The corresponding type info. + */ + public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode); + + public ServiceRegistry getServiceRegistry(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java new file mode 100644 index 000000000000..4f4c9df7833b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/LobCreatorBuilder.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import org.hibernate.engine.jdbc.LobCreationContext; +import org.hibernate.engine.jdbc.LobCreator; + +/** + * @author Steve Ebersole + */ +public interface LobCreatorBuilder { + LobCreator buildLobCreator(LobCreationContext lobCreationContext); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java new file mode 100644 index 000000000000..8bdbb69f9013 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/QualifiedObjectNameSupport.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Defines support for reading and writing qualified object names to and from the database. Generally speaking + * Hibernate itself only uses {@link #formatName}. Most times when it is "parsing" object names it is coming from + * mappings, in which case we expect simple dot-separated syntax and apply {@link ObjectName#parse} + * + * @author Steve Ebersole + */ +public interface QualifiedObjectNameSupport { + /** + * Performs formatting of an ObjectName to its String representation + * + * @param objectName The object name to be formatted. + * + * @return The dialect specific string form of the name. + */ + public String formatName(ObjectName objectName); + + /** + * Parse a String representation of an Object name to its ObjectName. Note that this specifically + * attempts to parse the text as if coming from the database. Mapping forms always use + * the form {@code ..}, parsing such names should just use {@link ObjectName#parse} + * + * @param text The object name text + * + * @return The parsed ObjectName + */ + public ObjectName parseName(String text); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java new file mode 100644 index 000000000000..7cfcd7517bc8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SQLStateType.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +/** + * Enum interpretation of the valid values from {@link java.sql.DatabaseMetaData#getSQLStateType()} + * + * @author Steve Ebersole + */ +public enum SQLStateType { + /** + * The reported codes follow the X/Open spec + */ + XOpen, + /** + * The reported codes follow the SQL spec + */ + SQL99, + /** + * It is unknown. Might follow another spec completely, or be a mixture. + */ + UNKNOWN +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java new file mode 100644 index 000000000000..c9da81ee97ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.hibernate.dialect.Dialect; + +/** + * Contract for resolving the schema of a {@link Connection}. + * + * @author Steve Ebersole + */ +public interface SchemaNameResolver { + /** + * Given a JDBC {@link Connection}, resolve the name of the schema (if one) to which it connects. + * + * @param connection The JDBC connection + * @param dialect The Dialect + * + * @return The name of the schema (may be null). + */ + public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java new file mode 100644 index 000000000000..b8953979e2ea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardQualifiedObjectNameSupportImpl.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.jdbc.env.spi; + +import java.util.regex.Pattern; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.IllegalIdentifierException; +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * @author Steve Ebersole + */ +public class StandardQualifiedObjectNameSupportImpl implements QualifiedObjectNameSupport { + public static final char DEFAULT_QUOTE_START = '\''; + public static final char DEFAULT_QUOTE_END = '\''; + public static final String DEFAULT_CATALOG_SEPARATOR = "."; + + private final String catalogSeparator; + private final boolean catalogAfterName; + private final char quotedStart; + private final char quotedEnd; + + private final Pattern splitPattern; + + public StandardQualifiedObjectNameSupportImpl( + String catalogSeparator, + boolean catalogAfterName, + char quotedStart, + char quotedEnd) { + this.catalogSeparator = catalogSeparator; + this.catalogAfterName = catalogAfterName; + this.quotedStart = quotedStart; + this.quotedEnd = quotedEnd; + + splitPattern = ".".equals( catalogSeparator ) + ? Pattern.compile( Pattern.quote( "." ) ) + : Pattern.compile( "[\\." + catalogSeparator + "]" ); + } + + public StandardQualifiedObjectNameSupportImpl() { + this( DEFAULT_CATALOG_SEPARATOR, false, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END ); + } + + public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) { + this( catalogSeparator, catalogAfterName, dialect.openQuote(), dialect.closeQuote() ); + } + + public StandardQualifiedObjectNameSupportImpl(Dialect dialect) { + this( DEFAULT_CATALOG_SEPARATOR, false, dialect ); + } + + public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName) { + this( catalogSeparator, catalogAfterName, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END ); + } + + + @Override + public String formatName(ObjectName objectName) { + StringBuilder buffer = new StringBuilder(); + if ( ! catalogAfterName ) { + if ( objectName.getCatalog() != null ) { + buffer.append( objectName.getCatalog().getText( quotedStart, quotedEnd ) ) + .append( catalogSeparator ); + } + } + + if ( objectName.getSchema() != null ) { + buffer.append( objectName.getSchema().getText( quotedStart, quotedEnd ) ).append( '.' ); + } + buffer.append( objectName.getName().getText( quotedStart, quotedEnd ) ); + + if ( catalogAfterName ) { + if ( objectName.getCatalog() != null ) { + buffer.append( catalogSeparator ) + .append( objectName.getCatalog().getText( quotedStart, quotedEnd ) ); + } + } + + return buffer.toString(); + } + + @Override + public ObjectName parseName(String text) { + if ( text == null ) { + throw new IllegalIdentifierException( "Object name must be specified" ); + } + + String catalogName = null; + String schemaName = null; + String localObjectName; + + final String[] tokens = splitPattern.split( text ); + if ( tokens.length == 0 || tokens.length == 1 ) { + // we have just a local name... + localObjectName = text; + } + else if ( tokens.length == 2 ) { + // we have 'something.name', no real way to know if something is a catalog or schema + // but thats ok based on the way we implement Database... so assume schema + schemaName = tokens[0]; + localObjectName = tokens[1]; + } + else if ( tokens.length == 3 ) { + if ( catalogAfterName ) { + schemaName = tokens[0]; + localObjectName = tokens[1]; + catalogName = tokens[2]; + } + else { + catalogName = tokens[0]; + schemaName = tokens[1]; + localObjectName = tokens[2]; + } + } + else { + throw new HibernateException( "Unable to parse object name: " + text ); + } + + return new ObjectName( catalogName, schemaName, localObjectName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java index fd8a7c17b340..63e21fb63381 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java @@ -30,6 +30,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -58,7 +59,6 @@ import org.hibernate.jdbc.WorkExecutorVisitable; import org.jboss.logging.Logger; -import org.jboss.logging.Logger.Level; /** * Standard Hibernate implementation of {@link JdbcCoordinator} @@ -67,6 +67,7 @@ * * @author Steve Ebersole * @author Brett Meyer + * @author Sanne Grinovero */ public class JdbcCoordinatorImpl implements JdbcCoordinator { private static final CoreMessageLogger LOG = Logger.getMessageLogger( @@ -81,6 +82,14 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator { private transient long transactionTimeOutInstant = -1; + /** + * This is a marker value to insert instead of null values for when a Statement gets registered in xref + * but has no associated ResultSets registered. This is useful to efficiently check against duplicate + * registration but you'll have to check against instance equality rather than null before attempting + * to add elements to this set. + */ + private static final Set EMPTY_RESULTSET = Collections.emptySet(); + private final HashMap> xref = new HashMap>(); private final Set unassociatedResultSets = new HashSet(); private final transient SqlExceptionHelper exceptionHelper; @@ -360,10 +369,15 @@ public void afterDeserialize(TransactionCoordinatorImpl transactionCoordinator) @Override public void register(Statement statement) { LOG.tracev( "Registering statement [{0}]", statement ); - if ( xref.containsKey( statement ) ) { + // Benchmarking has shown this to be a big hotspot. Originally, most usages would call both + // #containsKey and #put. Instead, we optimize for the most common path (no previous Statement was + // registered) by calling #put only once, but still handling the unlikely conflict and resulting exception. + final Set previousValue = xref.put( statement, EMPTY_RESULTSET ); + if ( previousValue != null ) { + // Put the previous value back to undo the put + xref.put( statement, previousValue ); throw new HibernateException( "statement already registered with JDBCContainer" ); } - xref.put( statement, null ); } @Override @@ -411,7 +425,6 @@ public void release(Statement statement) { @Override public void register(ResultSet resultSet, Statement statement) { - LOG.tracev( "Registering result set [{0}]", resultSet ); if ( statement == null ) { try { statement = resultSet.getStatement(); @@ -421,13 +434,12 @@ public void register(ResultSet resultSet, Statement statement) { } } if ( statement != null ) { - // Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a - // proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210. - if ( LOG.isEnabled( Level.DEBUG ) && !xref.containsKey( statement ) ) { - LOG.unregisteredStatement(); - } + LOG.tracev( "Registering result set [{0}]", resultSet ); Set resultSets = xref.get( statement ); if ( resultSets == null ) { + LOG.unregisteredStatement(); + } + if ( resultSets == null || resultSets == EMPTY_RESULTSET ) { resultSets = new HashSet(); xref.put( statement, resultSets ); } @@ -450,13 +462,11 @@ public void release(ResultSet resultSet, Statement statement) { } } if ( statement != null ) { - // Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a - // proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210. - if ( LOG.isEnabled( Level.DEBUG ) && !xref.containsKey( statement ) ) { + final Set resultSets = xref.get( statement ); + if ( resultSets == null ) { LOG.unregisteredStatement(); } - final Set resultSets = xref.get( statement ); - if ( resultSets != null ) { + else { resultSets.remove( resultSet ); if ( resultSets.isEmpty() ) { xref.remove( statement ); @@ -495,9 +505,7 @@ public void disableReleases() { private void cleanup() { for ( Map.Entry> entry : xref.entrySet() ) { - if ( entry.getValue() != null ) { - closeAll( entry.getValue() ); - } + closeAll( entry.getValue() ); close( entry.getKey() ); } xref.clear(); @@ -515,6 +523,10 @@ protected void closeAll(Set resultSets) { @SuppressWarnings({ "unchecked" }) protected void close(Statement statement) { LOG.tracev( "Closing prepared statement [{0}]", statement ); + + // Important for Statement caching -- some DBs (especially Sybase) log warnings on every Statement under + // certain situations. + sqlExceptionHelper().logAndClearWarnings( statement ); if ( statement instanceof InvalidatableWrapper ) { final InvalidatableWrapper wrapper = (InvalidatableWrapper) statement; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java index fc5e45f818f0..885bc4d45412 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java @@ -23,45 +23,22 @@ */ package org.hibernate.engine.jdbc.internal; -import java.lang.reflect.InvocationTargetException; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; -import org.hibernate.HibernateException; import org.hibernate.MultiTenancyStrategy; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; -import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; -import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport; -import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter; -import org.hibernate.engine.jdbc.dialect.spi.DialectFactory; -import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; -import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; -import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.ResultSetWrapper; -import org.hibernate.engine.jdbc.spi.SchemaNameResolver; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; -import org.hibernate.engine.jdbc.spi.TypeInfo; -import org.hibernate.exception.internal.SQLExceptionTypeDelegate; -import org.hibernate.exception.internal.SQLStateConversionDelegate; -import org.hibernate.exception.internal.StandardSQLExceptionConverter; -import org.hibernate.exception.spi.SQLExceptionConverter; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.ServiceRegistryAwareService; @@ -76,13 +53,10 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JdbcServicesImpl.class ); private ServiceRegistryImplementor serviceRegistry; + private JdbcEnvironment jdbcEnvironment; - private Dialect dialect; private ConnectionProvider connectionProvider; private SqlStatementLogger sqlStatementLogger; - private SqlExceptionHelper sqlExceptionHelper; - private ExtractedDatabaseMetaData extractedMetaDataSupport; - private LobCreatorBuilder lobCreatorBuilder; @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { @@ -91,389 +65,17 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) { @Override public void configure(Map configValues) { - final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configValues ); - final DialectFactory dialectFactory = serviceRegistry.getService( DialectFactory.class ); + this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class ); - Dialect dialect = null; - LobCreatorBuilder lobCreatorBuilder = null; - - boolean metaSupportsRefCursors = false; - boolean metaSupportsNamedParams = false; - boolean metaSupportsScrollable = false; - boolean metaSupportsGetGeneratedKeys = false; - boolean metaSupportsBatchUpdates = false; - boolean metaReportsDDLCausesTxnCommit = false; - boolean metaReportsDDLInTxnSupported = true; - String extraKeywordsString = ""; - int sqlStateType = -1; - boolean lobLocatorUpdateCopy = false; - String catalogName = null; - String schemaName = null; - final LinkedHashSet typeInfoSet = new LinkedHashSet(); - - // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value. - // The need for it is intended to be alleviated with future development, thus it is - // not defined as an Environment constant... - // - // it is used to control whether we should consult the JDBC metadata to determine - // certain Settings default values; it is useful to *not* do this when the database - // may not be available (mainly in tools usage). - final boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true ); - if ( useJdbcMetadata ) { - try { - final Connection connection = jdbcConnectionAccess.obtainConnection(); - try { - final DatabaseMetaData meta = connection.getMetaData(); - if ( LOG.isDebugEnabled() ) { - LOG.debugf( - "Database ->\n" - + " name : %s\n" - + " version : %s\n" - + " major : %s\n" - + " minor : %s", - meta.getDatabaseProductName(), - meta.getDatabaseProductVersion(), - meta.getDatabaseMajorVersion(), - meta.getDatabaseMinorVersion() - ); - LOG.debugf( - "Driver ->\n" - + " name : %s\n" - + " version : %s\n" - + " major : %s\n" - + " minor : %s", - meta.getDriverName(), - meta.getDriverVersion(), - meta.getDriverMajorVersion(), - meta.getDriverMinorVersion() - ); - LOG.debugf( "JDBC version : %s.%s", meta.getJDBCMajorVersion(), meta.getJDBCMinorVersion() ); - } - - metaSupportsRefCursors = StandardRefCursorSupport.supportsRefCursors( meta ); - metaSupportsNamedParams = meta.supportsNamedParameters(); - metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ); - metaSupportsBatchUpdates = meta.supportsBatchUpdates(); - metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit(); - metaReportsDDLInTxnSupported = !meta.dataDefinitionIgnoredInTransactions(); - metaSupportsGetGeneratedKeys = meta.supportsGetGeneratedKeys(); - extraKeywordsString = meta.getSQLKeywords(); - sqlStateType = meta.getSQLStateType(); - lobLocatorUpdateCopy = meta.locatorsUpdateCopy(); - typeInfoSet.addAll( TypeInfo.extractTypeInfo( meta ) ); - - dialect = dialectFactory.buildDialect( - configValues, - new DialectResolutionInfoSource() { - @Override - public DialectResolutionInfo getDialectResolutionInfo() { - try { - return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() ); - } - catch ( SQLException sqlException ) { - throw new HibernateException( - "Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use", - sqlException - ); - } - } - } - ); - - catalogName = connection.getCatalog(); - final SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues ); - if ( schemaNameResolver == null ) { -// todo : add dialect method -// schemaNameResolver = dialect.getSchemaNameResolver(); - } - if ( schemaNameResolver != null ) { - schemaName = schemaNameResolver.resolveSchemaName( connection ); - } - lobCreatorBuilder = new LobCreatorBuilder( configValues, connection ); - } - catch ( SQLException sqle ) { - LOG.unableToObtainConnectionMetadata( sqle.getMessage() ); - } - finally { - if ( connection != null ) { - jdbcConnectionAccess.releaseConnection( connection ); - } - } - } - catch ( SQLException sqle ) { - LOG.unableToObtainConnectionToQueryMetadata( sqle.getMessage() ); - dialect = dialectFactory.buildDialect( configValues, null ); - } - catch ( UnsupportedOperationException uoe ) { - // user supplied JDBC connections - dialect = dialectFactory.buildDialect( configValues, null ); - } - } - else { - dialect = dialectFactory.buildDialect( configValues, null ); - } + final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues ); + this.connectionProvider = MultiTenancyStrategy.NONE == multiTenancyStrategy ? + serviceRegistry.getService( ConnectionProvider.class ) : + null; final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false ); final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false ); - this.dialect = dialect; - this.lobCreatorBuilder = ( - lobCreatorBuilder == null ? - new LobCreatorBuilder( configValues, null ) : - lobCreatorBuilder - ); - this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL ); - - this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( - metaSupportsRefCursors, - metaSupportsNamedParams, - metaSupportsScrollable, - metaSupportsGetGeneratedKeys, - metaSupportsBatchUpdates, - metaReportsDDLInTxnSupported, - metaReportsDDLCausesTxnCommit, - parseKeywords( extraKeywordsString ), - parseSQLStateType( sqlStateType ), - lobLocatorUpdateCopy, - schemaName, - catalogName, - typeInfoSet - ); - - SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter(); - if ( sqlExceptionConverter == null ) { - final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter(); - sqlExceptionConverter = converter; - converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() ); - converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) ); - // todo : vary this based on extractedMetaDataSupport.getSqlStateType() - converter.addDelegate( new SQLStateConversionDelegate( dialect ) ); - } - this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter ); - } - - private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues) { - final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues ); - - if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) { - connectionProvider = serviceRegistry.getService( ConnectionProvider.class ); - return new ConnectionProviderJdbcConnectionAccess( connectionProvider ); - } - else { - connectionProvider = null; - final MultiTenantConnectionProvider multiTenantConnectionProvider = serviceRegistry.getService( MultiTenantConnectionProvider.class ); - return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider ); - } - } - - private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { - private final ConnectionProvider connectionProvider; - - public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) { - this.connectionProvider = connectionProvider; - } - - @Override - public Connection obtainConnection() throws SQLException { - return connectionProvider.getConnection(); - } - - @Override - public void releaseConnection(Connection connection) throws SQLException { - connectionProvider.closeConnection( connection ); - } - - @Override - public boolean supportsAggressiveRelease() { - return connectionProvider.supportsAggressiveRelease(); - } - } - - private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { - private final MultiTenantConnectionProvider connectionProvider; - - public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) { - this.connectionProvider = connectionProvider; - } - - @Override - public Connection obtainConnection() throws SQLException { - return connectionProvider.getAnyConnection(); - } - - @Override - public void releaseConnection(Connection connection) throws SQLException { - connectionProvider.releaseAnyConnection( connection ); - } - - @Override - public boolean supportsAggressiveRelease() { - return connectionProvider.supportsAggressiveRelease(); - } - } - - - /** - * A constant naming the setting used to identify the {@link SchemaNameResolver} to use - *

    - * TODO : add to Environment - */ - public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver"; - - private SchemaNameResolver determineExplicitSchemaNameResolver(Map configValues) { - final Object setting = configValues.get( SCHEMA_NAME_RESOLVER ); - if ( SchemaNameResolver.class.isInstance( setting ) ) { - return (SchemaNameResolver) setting; - } - - final String resolverClassName = (String) setting; - if ( resolverClassName != null ) { - try { - final Class resolverClass = ReflectHelper.classForName( resolverClassName, getClass() ); - return (SchemaNameResolver) ReflectHelper.getDefaultConstructor( resolverClass ).newInstance(); - } - catch ( ClassNotFoundException e ) { - LOG.unableToLocateConfiguredSchemaNameResolver( resolverClassName, e.toString() ); - } - catch ( InvocationTargetException e ) { - LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.getTargetException().toString() ); - } - catch ( Exception e ) { - LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.toString() ); - } - } - return null; - } - - private Set parseKeywords(String extraKeywordsString) { - final Set keywordSet = new HashSet(); - keywordSet.addAll( Arrays.asList( extraKeywordsString.split( "," ) ) ); - return keywordSet; - } - - private ExtractedDatabaseMetaData.SQLStateType parseSQLStateType(int sqlStateType) { - switch ( sqlStateType ) { - case DatabaseMetaData.sqlStateSQL99 : { - return ExtractedDatabaseMetaData.SQLStateType.SQL99; - } - case DatabaseMetaData.sqlStateXOpen : { - return ExtractedDatabaseMetaData.SQLStateType.XOpen; - } - default : { - return ExtractedDatabaseMetaData.SQLStateType.UNKOWN; - } - } - } - - private static class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData { - private final boolean supportsRefCursors; - private final boolean supportsNamedParameters; - private final boolean supportsScrollableResults; - private final boolean supportsGetGeneratedKeys; - private final boolean supportsBatchUpdates; - private final boolean supportsDataDefinitionInTransaction; - private final boolean doesDataDefinitionCauseTransactionCommit; - private final Set extraKeywords; - private final SQLStateType sqlStateType; - private final boolean lobLocatorUpdateCopy; - private final String connectionSchemaName; - private final String connectionCatalogName; - private final LinkedHashSet typeInfoSet; - - private ExtractedDatabaseMetaDataImpl( - boolean supportsRefCursors, - boolean supportsNamedParameters, - boolean supportsScrollableResults, - boolean supportsGetGeneratedKeys, - boolean supportsBatchUpdates, - boolean supportsDataDefinitionInTransaction, - boolean doesDataDefinitionCauseTransactionCommit, - Set extraKeywords, - SQLStateType sqlStateType, - boolean lobLocatorUpdateCopy, - String connectionSchemaName, - String connectionCatalogName, - LinkedHashSet typeInfoSet) { - this.supportsRefCursors = supportsRefCursors; - this.supportsNamedParameters = supportsNamedParameters; - this.supportsScrollableResults = supportsScrollableResults; - this.supportsGetGeneratedKeys = supportsGetGeneratedKeys; - this.supportsBatchUpdates = supportsBatchUpdates; - this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction; - this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit; - this.extraKeywords = extraKeywords; - this.sqlStateType = sqlStateType; - this.lobLocatorUpdateCopy = lobLocatorUpdateCopy; - this.connectionSchemaName = connectionSchemaName; - this.connectionCatalogName = connectionCatalogName; - this.typeInfoSet = typeInfoSet; - } - - @Override - public boolean supportsRefCursors() { - return supportsRefCursors; - } - - @Override - public boolean supportsNamedParameters() { - return supportsNamedParameters; - } - - @Override - public boolean supportsScrollableResults() { - return supportsScrollableResults; - } - - @Override - public boolean supportsGetGeneratedKeys() { - return supportsGetGeneratedKeys; - } - - @Override - public boolean supportsBatchUpdates() { - return supportsBatchUpdates; - } - - @Override - public boolean supportsDataDefinitionInTransaction() { - return supportsDataDefinitionInTransaction; - } - - @Override - public boolean doesDataDefinitionCauseTransactionCommit() { - return doesDataDefinitionCauseTransactionCommit; - } - - @Override - public Set getExtraKeywords() { - return extraKeywords; - } - - @Override - public SQLStateType getSqlStateType() { - return sqlStateType; - } - - @Override - public boolean doesLobLocatorUpdateCopy() { - return lobLocatorUpdateCopy; - } - - @Override - public String getConnectionSchemaName() { - return connectionSchemaName; - } - - @Override - public String getConnectionCatalogName() { - return connectionCatalogName; - } - - @Override - public LinkedHashSet getTypeInfoSet() { - return typeInfoSet; - } } @Override @@ -488,26 +90,30 @@ public SqlStatementLogger getSqlStatementLogger() { @Override public SqlExceptionHelper getSqlExceptionHelper() { - return sqlExceptionHelper; + return jdbcEnvironment == null ? null : jdbcEnvironment.getSqlExceptionHelper(); } @Override public Dialect getDialect() { - return dialect; + return jdbcEnvironment == null ? null : jdbcEnvironment.getDialect(); } @Override public ExtractedDatabaseMetaData getExtractedMetaDataSupport() { - return extractedMetaDataSupport; - } + return jdbcEnvironment == null ? null : jdbcEnvironment.getExtractedDatabaseMetaData(); } @Override public LobCreator getLobCreator(LobCreationContext lobCreationContext) { - return lobCreatorBuilder.buildLobCreator( lobCreationContext ); + return jdbcEnvironment == null ? null : jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext ); } @Override public ResultSetWrapper getResultSetWrapper() { return ResultSetWrapperImpl.INSTANCE; } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LobCreatorBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LobCreatorBuilder.java deleted file mode 100644 index 45f335cf1192..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/LobCreatorBuilder.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.engine.jdbc.internal; - -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.SQLException; -import java.util.Map; - -import org.hibernate.cfg.Environment; -import org.hibernate.engine.jdbc.ContextualLobCreator; -import org.hibernate.engine.jdbc.LobCreationContext; -import org.hibernate.engine.jdbc.LobCreator; -import org.hibernate.engine.jdbc.NonContextualLobCreator; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.config.ConfigurationHelper; - -import org.jboss.logging.Logger; - -/** - * Builds {@link LobCreator} instances based on the capabilities of the environment. - * - * @author Steve Ebersole - */ -public class LobCreatorBuilder { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - LobCreatorBuilder.class.getName() - ); - - private boolean useContextualLobCreation; - - /** - * The public factory method for obtaining the appropriate (according to given JDBC {@link java.sql.Connection}. - * - * @param configValues The map of settings - * @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support, - * specifically for creating LOB references. - */ - public LobCreatorBuilder(Map configValues, Connection jdbcConnection) { - this.useContextualLobCreation = useContextualLobCreation( configValues, jdbcConnection ); - } - - private static final Class[] NO_ARG_SIG = new Class[0]; - private static final Object[] NO_ARGS = new Object[0]; - - /** - * Basically here we are simply checking whether we can call the {@link Connection} methods for - * LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods, - * but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply - * throwing an exception). - * - * @param jdbcConnection The connection which can be used in level-of-support testing. - * - * @return True if the connection can be used to create LOBs; false otherwise. - */ - @SuppressWarnings("unchecked") - private static boolean useContextualLobCreation(Map configValues, Connection jdbcConnection) { - final boolean isNonContextualLobCreationRequired = - ConfigurationHelper.getBoolean( Environment.NON_CONTEXTUAL_LOB_CREATION, configValues ); - if ( isNonContextualLobCreationRequired ) { - LOG.disablingContextualLOBCreation( Environment.NON_CONTEXTUAL_LOB_CREATION ); - return false; - } - if ( jdbcConnection == null ) { - LOG.disablingContextualLOBCreationSinceConnectionNull(); - return false; - } - - try { - try { - final DatabaseMetaData meta = jdbcConnection.getMetaData(); - // if the jdbc driver version is less than 4, it shouldn't have createClob - if ( meta.getJDBCMajorVersion() < 4 ) { - LOG.disablingContextualLOBCreationSinceOldJdbcVersion( meta.getJDBCMajorVersion() ); - return false; - } - } - catch ( SQLException ignore ) { - // ignore exception and continue - } - - final Class connectionClass = Connection.class; - final Method createClobMethod = connectionClass.getMethod( "createClob", NO_ARG_SIG ); - if ( createClobMethod.getDeclaringClass().equals( Connection.class ) ) { - // If we get here we are running in a jdk 1.6 (jdbc 4) environment... - // Further check to make sure the driver actually implements the LOB creation methods. We - // check against createClob() as indicative of all; should we check against all 3 explicitly? - try { - final Object clob = createClobMethod.invoke( jdbcConnection, NO_ARGS ); - try { - final Method freeMethod = clob.getClass().getMethod( "free", NO_ARG_SIG ); - freeMethod.invoke( clob, NO_ARGS ); - } - catch ( Throwable ignore ) { - LOG.tracef( "Unable to free CLOB created to test createClob() implementation : %s", ignore ); - } - return true; - } - catch ( Throwable t ) { - LOG.disablingContextualLOBCreationSinceCreateClobFailed( t ); - } - } - } - catch ( NoSuchMethodException ignore ) { - } - - return false; - } - - /** - * Build a LobCreator using the given context - * - * @param lobCreationContext The LOB creation context - * - * @return The LobCreator - */ - public LobCreator buildLobCreator(LobCreationContext lobCreationContext) { - return useContextualLobCreation - ? new ContextualLobCreator( lobCreationContext ) - : NonContextualLobCreator.INSTANCE; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java index 0e67fdc95c2f..e4092dcbe5eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java @@ -27,6 +27,8 @@ import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.service.Service; /** @@ -90,4 +92,6 @@ public interface JdbcServices extends Service { * @return The ResultSet wrapper. */ public ResultSetWrapper getResultSetWrapper(); + + public JdbcEnvironment getJdbcEnvironment(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SqlExceptionHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SqlExceptionHelper.java index 3955bbead396..73b988271bce 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SqlExceptionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SqlExceptionHelper.java @@ -268,6 +268,10 @@ public void walkWarnings( public void logAndClearWarnings(Connection connection) { handleAndClearWarnings( connection, STANDARD_WARNING_HANDLER ); } + + public void logAndClearWarnings(Statement statement) { + handleAndClearWarnings( statement, STANDARD_WARNING_HANDLER ); + } /** * General purpose handling of warnings associated with a JDBC {@link Connection}. diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/EntityGraphQueryHint.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/EntityGraphQueryHint.java index 82ba32c713ef..4d8797652388 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/EntityGraphQueryHint.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/EntityGraphQueryHint.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; + import javax.persistence.AttributeNode; import javax.persistence.EntityGraph; import javax.persistence.Subgraph; @@ -36,6 +37,7 @@ import org.hibernate.hql.internal.ast.tree.FromElementFactory; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.sql.JoinType; +import org.hibernate.type.CollectionType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; @@ -85,6 +87,8 @@ private List getFromElements( final String attributeName = attributeNode.getAttributeName(); final String className = origin.getClassName(); + // TODO: This is ignored by collection types and probably wrong for entity types. Presumably it screws + // with inheritance. final String role = className + "." + attributeName; final String classAlias = origin.getClassAlias(); final String originTableAlias = origin.getTableAlias(); @@ -120,6 +124,7 @@ private List getFromElements( ); } else if ( propertyType.isCollectionType() ) { + CollectionType collectionType = (CollectionType) propertyType; final String[] columns = origin.toColumns( originTableAlias, attributeName, false ); final FromElementFactory fromElementFactory = new FromElementFactory( @@ -127,9 +132,9 @@ else if ( propertyType.isCollectionType() ) { attributeName, classAlias, columns, false ); final QueryableCollection queryableCollection = walker.getSessionFactoryHelper() - .requireQueryableCollection( role ); + .requireQueryableCollection( collectionType.getRole() ); fromElement = fromElementFactory.createCollection( - queryableCollection, role, JoinType.LEFT_OUTER_JOIN, true, false + queryableCollection, collectionType.getRole(), JoinType.LEFT_OUTER_JOIN, true, false ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/HQLQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/HQLQueryPlan.java index 58002a33b59e..40dacebab434 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/HQLQueryPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/HQLQueryPlan.java @@ -205,8 +205,9 @@ public List performList( queryParameters.traceParameters( session.getFactory() ); } - final boolean hasLimit = queryParameters.getRowSelection() != null - && queryParameters.getRowSelection().definesLimits(); + final RowSelection rowSelection = queryParameters.getRowSelection(); + final boolean hasLimit = rowSelection != null + && rowSelection.definesLimits(); final boolean needsLimit = hasLimit && translators.length > 1; final QueryParameters queryParametersToUse; @@ -221,8 +222,9 @@ public List performList( queryParametersToUse = queryParameters; } - final List combinedResults = new ArrayList(); - final IdentitySet distinction = new IdentitySet(); + final int guessedResultSize = guessResultSize( rowSelection ); + final List combinedResults = new ArrayList( guessedResultSize ); + final IdentitySet distinction = new IdentitySet( guessedResultSize ); int includedCount = -1; translator_loop: for ( QueryTranslator translator : translators ) { @@ -257,6 +259,31 @@ public List performList( return combinedResults; } + /** + * If we're able to guess a likely size of the results we can optimize allocation + * of our datastructures. + * Essentially if we detect the user is not using pagination, we attempt to use the FetchSize + * as a reasonable hint. If fetch size is not being set either, it is reasonable to expect + * that we're going to have a single hit. In such a case it would be tempting to return a constant + * of value one, but that's dangerous as it doesn't scale up appropriately for example + * with an ArrayList if the guess is wrong. + * + * @param rowSelection + * @return a reasonable size to use for allocation + */ + private final int guessResultSize(RowSelection rowSelection) { + if ( rowSelection != null ) { + final int maxReasonableAllocation = rowSelection.getFetchSize() != null ? rowSelection.getFetchSize().intValue() : 100; + if ( rowSelection.getMaxRows() != null && rowSelection.getMaxRows().intValue() > 0 ) { + return Math.min( maxReasonableAllocation, rowSelection.getMaxRows().intValue() ); + } + else if ( rowSelection.getFetchSize() != null && rowSelection.getFetchSize().intValue() > 0 ) { + return rowSelection.getFetchSize().intValue(); + } + } + return 7;//magic number guessed as a reasonable default. + } + /** * Coordinates the efforts to perform an iterate across all the included query translators. * diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java index c31b65b2f08a..f507404cb473 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java @@ -60,6 +60,8 @@ import org.hibernate.engine.internal.NonNullableTransientDependencies; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.proxy.HibernateProxy; +import org.hibernate.proxy.LazyInitializer; import org.hibernate.type.Type; /** @@ -102,8 +104,9 @@ public class ActionQueue { // an immutable array holding all 7 ExecutionLists in execution order private final List> executableLists; - private final AfterTransactionCompletionProcessQueue afterTransactionProcesses; - private final BeforeTransactionCompletionProcessQueue beforeTransactionProcesses; + private transient boolean isTransactionCoordinatorShared; + private AfterTransactionCompletionProcessQueue afterTransactionProcesses; + private BeforeTransactionCompletionProcessQueue beforeTransactionProcesses; /** * Constructs an action queue bound to the given session. @@ -140,6 +143,7 @@ public ActionQueue(SessionImplementor session) { executableLists = Collections.unmodifiableList( tmp ); + isTransactionCoordinatorShared = false; afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session ); beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session ); @@ -370,14 +374,20 @@ private void prepareActions(ExecutableList queue) throws HibernateException { * @param success Was the transaction successful. */ public void afterTransactionCompletion(boolean success) { - afterTransactionProcesses.afterTransactionCompletion( success ); + if ( !isTransactionCoordinatorShared ) { + // Execute completion actions only in transaction owner (aka parent session). + afterTransactionProcesses.afterTransactionCompletion( success ); + } } /** * Execute any registered {@link org.hibernate.action.spi.BeforeTransactionCompletionProcess} */ public void beforeTransactionCompletion() { - beforeTransactionProcesses.beforeTransactionCompletion(); + if ( !isTransactionCoordinatorShared ) { + // Execute completion actions only in transaction owner (aka parent session). + beforeTransactionProcesses.beforeTransactionCompletion(); + } } /** @@ -542,6 +552,24 @@ public int numberOfInsertions() { return insertions.size(); } + public TransactionCompletionProcesses getTransactionCompletionProcesses() { + return new TransactionCompletionProcesses( beforeTransactionProcesses, afterTransactionProcesses ); + } + + /** + * Bind transaction completion processes to make them shared between primary and secondary session. + * Transaction completion processes are always executed by transaction owner (primary session), + * but can be registered using secondary session too. + * + * @param processes Transaction completion processes. + * @param isTransactionCoordinatorShared Flag indicating shared transaction context. + */ + public void setTransactionCompletionProcesses(TransactionCompletionProcesses processes, boolean isTransactionCoordinatorShared) { + this.isTransactionCoordinatorShared = isTransactionCoordinatorShared; + this.beforeTransactionProcesses = processes.beforeTransactionCompletionProcesses; + this.afterTransactionProcesses = processes.afterTransactionCompletionProcesses; + } + public void sortCollectionActions() { if ( session.getFactory().getSettings().isOrderUpdatesEnabled() ) { // sort the updates by fk @@ -575,11 +603,11 @@ public void clearFromFlushNeededCheck(int previousCollectionRemovalSize) { } public boolean hasAfterTransactionActions() { - return !afterTransactionProcesses.processes.isEmpty(); + return isTransactionCoordinatorShared ? false : afterTransactionProcesses.hasActions(); } public boolean hasBeforeTransactionActions() { - return !beforeTransactionProcesses.processes.isEmpty(); + return isTransactionCoordinatorShared ? false : beforeTransactionProcesses.hasActions(); } public boolean hasAnyQueuedActions() { @@ -588,6 +616,12 @@ public boolean hasAnyQueuedActions() { } public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) { + if ( rescuedEntity instanceof HibernateProxy ) { + LazyInitializer initializer = ( ( HibernateProxy ) rescuedEntity ).getHibernateLazyInitializer(); + if ( !initializer.isUninitialized() ) { + rescuedEntity = initializer.getImplementation( session ); + } + } for ( int i = 0; i < deletions.size(); i++ ) { EntityDeleteAction action = deletions.get( i ); if ( action.getInstance() == rescuedEntity ) { @@ -645,30 +679,40 @@ public static ActionQueue deserialize(ObjectInputStream ois, SessionImplementor return rtn; } - /** - * Encapsulates behavior needed for after transaction processing - */ - private static class BeforeTransactionCompletionProcessQueue { - private SessionImplementor session; + private static abstract class AbstractTransactionCompletionProcessQueue { + protected SessionImplementor session; // Concurrency handling required when transaction completion process is dynamically registered // inside event listener (HHH-7478). - private Queue processes = new ConcurrentLinkedQueue(); + protected Queue processes = new ConcurrentLinkedQueue(); - private BeforeTransactionCompletionProcessQueue(SessionImplementor session) { + private AbstractTransactionCompletionProcessQueue(SessionImplementor session) { this.session = session; } - public void register(BeforeTransactionCompletionProcess process) { + public void register(T process) { if ( process == null ) { return; } processes.add( process ); } + public boolean hasActions() { + return !processes.isEmpty(); + } + } + + /** + * Encapsulates behavior needed for before transaction processing + */ + private static class BeforeTransactionCompletionProcessQueue extends AbstractTransactionCompletionProcessQueue { + private BeforeTransactionCompletionProcessQueue(SessionImplementor session) { + super( session ); + } + public void beforeTransactionCompletion() { - for ( BeforeTransactionCompletionProcess process : processes ) { + while ( !processes.isEmpty() ) { try { - process.doBeforeTransactionCompletion( session ); + processes.poll().doBeforeTransactionCompletion( session ); } catch (HibernateException he) { throw he; @@ -677,39 +721,27 @@ public void beforeTransactionCompletion() { throw new AssertionFailure( "Unable to perform beforeTransactionCompletion callback", e ); } } - processes.clear(); } } /** * Encapsulates behavior needed for after transaction processing */ - private static class AfterTransactionCompletionProcessQueue { - private SessionImplementor session; + private static class AfterTransactionCompletionProcessQueue extends AbstractTransactionCompletionProcessQueue { private Set querySpacesToInvalidate = new HashSet(); - // Concurrency handling required when transaction completion process is dynamically registered - // inside event listener (HHH-7478). - private Queue processes = new ConcurrentLinkedQueue(); private AfterTransactionCompletionProcessQueue(SessionImplementor session) { - this.session = session; + super( session ); } public void addSpaceToInvalidate(String space) { querySpacesToInvalidate.add( space ); } - public void register(AfterTransactionCompletionProcess process) { - if ( process == null ) { - return; - } - processes.add( process ); - } - public void afterTransactionCompletion(boolean success) { - for ( AfterTransactionCompletionProcess process : processes ) { + while ( !processes.isEmpty() ) { try { - process.doAfterTransactionCompletion( success, session ); + processes.poll().doAfterTransactionCompletion( success, session ); } catch (CacheException ce) { LOG.unableToReleaseCacheLock( ce ); @@ -719,7 +751,6 @@ public void afterTransactionCompletion(boolean success) { throw new AssertionFailure( "Exception releasing cache locks", e ); } } - processes.clear(); if ( session.getFactory().getSettings().isQueryCacheEnabled() ) { session.getFactory().getUpdateTimestampsCache().invalidate( @@ -731,6 +762,21 @@ public void afterTransactionCompletion(boolean success) { } } + /** + * Wrapper class allowing to bind the same transaction completion process queues in different sessions. + */ + public static class TransactionCompletionProcesses { + private final BeforeTransactionCompletionProcessQueue beforeTransactionCompletionProcesses; + private final AfterTransactionCompletionProcessQueue afterTransactionCompletionProcesses; + + private TransactionCompletionProcesses( + BeforeTransactionCompletionProcessQueue beforeTransactionCompletionProcessQueue, + AfterTransactionCompletionProcessQueue afterTransactionCompletionProcessQueue) { + this.beforeTransactionCompletionProcesses = beforeTransactionCompletionProcessQueue; + this.afterTransactionCompletionProcesses = afterTransactionCompletionProcessQueue; + } + } + /** * Order the {@link #insertions} queue such that we group inserts against the same entity together (without * violating constraints). The original order is generated by cascade order, which in turn is based on the diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java index b143a5fdfff0..d972b652e2b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/CacheInitiator.java @@ -25,7 +25,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.internal.CacheImpl; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java index 9b24418bb3ac..961c1dd8fc47 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java @@ -29,7 +29,6 @@ import java.io.Serializable; import org.hibernate.CustomEntityDirtinessStrategy; -import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.Session; @@ -53,8 +52,6 @@ public final class EntityEntry implements Serializable { private boolean existsInDatabase; private Object version; private transient EntityPersister persister; - private final EntityMode entityMode; - private final String tenantId; private final String entityName; // cached EntityKey (lazy-initialized) private transient EntityKey cachedEntityKey; @@ -73,8 +70,6 @@ public EntityEntry( final LockMode lockMode, final boolean existsInDatabase, final EntityPersister persister, - final EntityMode entityMode, - final String tenantId, final boolean disableVersionIncrement, final boolean lazyPropertiesAreUnfetched, final PersistenceContext persistenceContext) { @@ -92,8 +87,6 @@ public EntityEntry( this.isBeingReplicated=disableVersionIncrement; this.loadedWithLazyPropertiesUnfetched = lazyPropertiesAreUnfetched; this.persister=persister; - this.entityMode = entityMode; - this.tenantId = tenantId; this.entityName = persister == null ? null : persister.getEntityName(); this.persistenceContext = persistenceContext; } @@ -106,8 +99,6 @@ private EntityEntry( final SessionFactoryImplementor factory, final String entityName, final Serializable id, - final EntityMode entityMode, - final String tenantId, final Status status, final Status previousStatus, final Object[] loadedState, @@ -121,8 +112,6 @@ private EntityEntry( this.entityName = entityName; this.persister = ( factory == null ? null : factory.getEntityPersister( entityName ) ); this.id = id; - this.entityMode = entityMode; - this.tenantId = tenantId; this.status = status; this.previousStatus = previousStatus; this.loadedState = loadedState; @@ -410,8 +399,6 @@ public boolean isLoadedWithLazyPropertiesUnfetched() { public void serialize(ObjectOutputStream oos) throws IOException { oos.writeObject( entityName ); oos.writeObject( id ); - oos.writeObject( entityMode.toString() ); - oos.writeObject( tenantId ); oos.writeObject( status.name() ); oos.writeObject( (previousStatus == null ? "" : previousStatus.name()) ); // todo : potentially look at optimizing these two arrays @@ -445,8 +432,6 @@ public static EntityEntry deserialize( persistenceContext.getSession().getFactory(), (String) ois.readObject(), (Serializable) ois.readObject(), - EntityMode.parse( (String) ois.readObject() ), - (String) ois.readObject(), Status.valueOf( (String) ois.readObject() ), ( previousStatusString = (String) ois.readObject() ).length() == 0 ? null diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java index 8dd0aec44c48..fd811acb9de8 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java @@ -71,24 +71,6 @@ public EntityKey(Serializable id, EntityPersister persister) { this.hashCode = generateHashCode(); } - /** - * Used to reconstruct an EntityKey during deserialization. Note that this constructor - * is used only in very specific situations: the SessionFactory isn't actually available - * and so both equals and hashcode implementations can't be implemented correctly. - * - * @param identifier The identifier value - * @param persister The EntityPersister - * @param hashCode The hashCode needs to be provided as it can't be calculated correctly without the SessionFactory. - */ - private EntityKey(Serializable identifier, EntityPersister persister, int hashCode) { - this.persister = persister; - if ( identifier == null ) { - throw new AssertionFailure( "null identifier" ); - } - this.identifier = identifier; - this.hashCode = hashCode; - } - private int generateHashCode() { int result = 17; result = 37 * result + persister.getIdentifierType().getHashCode( identifier, persister.getFactory() ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java new file mode 100644 index 000000000000..46fe1f7727ef --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.spi; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class SyntheticAttributeHelper { + public static final String SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME = "_identifierMapper"; + + private static final String BACKREF_ATTRIBUTE_NAME_PREFIX = "_"; + private static final String BACKREF_ATTRIBUTE_NAME_SUFFIX = "BackRef"; + private static final String INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX = "IndexBackRef"; + + + public static String createBackRefAttributeName(String pluralAttributeRole) { + return createSyntheticAttributeName( + pluralAttributeRole, + BACKREF_ATTRIBUTE_NAME_PREFIX, + BACKREF_ATTRIBUTE_NAME_SUFFIX + ); + } + + public static String createIndexBackRefAttributeName(String pluralAttributeRole) { + return createSyntheticAttributeName( + pluralAttributeRole, + BACKREF_ATTRIBUTE_NAME_PREFIX, + INDEX_BACKREF_ATTRIBUTE_NAME_SUFFIX + ); + } + + private static String createSyntheticAttributeName(String attributeRole, String prefix, String suffix) { + return new StringBuilder( + prefix.length() + attributeRole.length() + suffix.length() ) + .append( prefix ) + .append( attributeRole ) + .append( suffix ) + .toString(); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/TypedValue.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/TypedValue.java index 7953d83578ea..0e772ff9a83e 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/TypedValue.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/TypedValue.java @@ -23,6 +23,8 @@ */ package org.hibernate.engine.spi; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; import org.hibernate.EntityMode; @@ -38,19 +40,13 @@ public final class TypedValue implements Serializable { private final Type type; private final Object value; - private final ValueHolder hashcode; + // "transient" is important here -- NaturalIdCacheKey needs to be Serializable + private transient ValueHolder hashcode; public TypedValue(final Type type, final Object value) { this.type = type; this.value = value; - this.hashcode = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public Integer initialize() { - return value == null ? 0 : type.getHashCode( value ); - } - } - ); + initTransients(); } /** @@ -89,9 +85,18 @@ public boolean equals(Object other) { && type.isEqual( that.value, value ); } -} - - - - + private void readObject(ObjectInputStream ois) + throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + initTransients(); + } + private void initTransients() { + this.hashcode = new ValueHolder( new ValueHolder.DeferredInitializer() { + @Override + public Integer initialize() { + return value == null ? 0 : type.getHashCode( value ); + } + } ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java index f10397a4cd54..36ad40d165a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java @@ -60,7 +60,7 @@ * * @author Steve Ebersole */ -public class TransactionCoordinatorImpl implements TransactionCoordinator { +public final class TransactionCoordinatorImpl implements TransactionCoordinator { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( TransactionCoordinatorImpl.class ); private final transient TransactionContext transactionContext; @@ -78,6 +78,9 @@ public class TransactionCoordinatorImpl implements TransactionCoordinator { private transient boolean open = true; private transient boolean synchronizationRegistered; private transient boolean ownershipTaken; + + private transient boolean isDebugging = LOG.isDebugEnabled(); + private transient boolean isTracing = LOG.isTraceEnabled(); public TransactionCoordinatorImpl( Connection userSuppliedConnection, @@ -132,7 +135,9 @@ public void reset() { } public void afterTransaction(TransactionImplementor hibernateTransaction, int status) { - LOG.trace( "after transaction completion" ); + if (isTracing) { + LOG.trace( "after transaction completion" ); + } final boolean success = JtaStatusHelper.isCommitted( status ); @@ -212,50 +217,59 @@ private void attemptToRegisterJtaSync() { return; } + final JtaPlatform jtaPlatform = getTransactionEnvironment().getJtaPlatform(); + if ( jtaPlatform == null ) { + // if no jta platform was registered we wont be able to register a jta synchronization + return; + } + // Has the local transaction (Hibernate facade) taken on the responsibility of driving the transaction inflow? if ( currentHibernateTransaction.isInitiator() ) { return; } - if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.JOINED ) { + final JoinStatus joinStatus = currentHibernateTransaction.getJoinStatus(); + if ( joinStatus != JoinStatus.JOINED ) { // the transaction is not (yet) joined, see if we should join... if ( !transactionContext.shouldAutoJoinTransaction() ) { // we are supposed to not auto join transactions; if the transaction is not marked for join // we cannot go any further in attempting to join (register sync). - if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.MARKED_FOR_JOINED ) { - LOG.debug( "Skipping JTA sync registration due to auto join checking" ); + if ( joinStatus != JoinStatus.MARKED_FOR_JOINED ) { + if (isDebugging) { + LOG.debug( "Skipping JTA sync registration due to auto join checking" ); + } return; } } } // IMPL NOTE : At this point the local callback is the "maybe" one. The only time that needs to change is if - // we are able to successfully register the transaction synchronization in which case the local callback would become + // we are able to successfully register the transaction synchronization in which case the local callback would become // non driving. To that end, the following checks are simply opt outs where we are unable to register the // synchronization - JtaPlatform jtaPlatform = getTransactionEnvironment().getJtaPlatform(); - if ( jtaPlatform == null ) { - // if no jta platform was registered we wont be able to register a jta synchronization - return; - } - // Can we resister a synchronization if ( !jtaPlatform.canRegisterSynchronization() ) { - LOG.trace( "registered JTA platform says we cannot currently resister synchronization; skipping" ); + if (isTracing) { + LOG.trace( "registered JTA platform says we cannot currently register synchronization; skipping" ); + } return; } // Should we resister a synchronization if ( !transactionFactory().isJoinableJtaTransaction( this, currentHibernateTransaction ) ) { - LOG.trace( "TransactionFactory reported no JTA transaction to join; skipping Synchronization registration" ); + if (isTracing) { + LOG.trace( "TransactionFactory reported no JTA transaction to join; skipping Synchronization registration" ); + } return; } jtaPlatform.registerSynchronization( new RegisteredSynchronization( getSynchronizationCallbackCoordinator() ) ); getSynchronizationCallbackCoordinator().synchronizationRegistered(); synchronizationRegistered = true; - LOG.debug( "successfully registered Synchronization" ); + if (isDebugging) { + LOG.debug( "successfully registered Synchronization" ); + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java index a04acb494865..e543cb8ecec3 100755 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java @@ -92,45 +92,58 @@ private void checkNaturalId( Object[] current, Object[] loaded, SessionImplementor session) { - if ( persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY ) { - if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) { - // SHORT-CUT: if the natural id is mutable (!immutable), no need to do the below checks - // EARLY EXIT!!! - return; - } + // series of short-cut checks + if ( !persister.hasNaturalIdentifier() ) { + return; + } - final int[] naturalIdentifierPropertiesIndexes = persister.getNaturalIdentifierProperties(); - final Type[] propertyTypes = persister.getPropertyTypes(); - final boolean[] propertyUpdateability = persister.getPropertyUpdateability(); + if ( entry.getStatus() == Status.READ_ONLY ) { + // this is a performance opt-out, but not sure this is entirely correct. What + // can happen is a situation where we have a immutable natural id that is changed + // but we do not check here. + // + // it comes down to the same old question.. is specifying a natural-id is immutable: + // a) a mandate to make sure its value is not changed by the app, or + // b) a optimization hint + return; + } - final Object[] snapshot = loaded == null - ? session.getPersistenceContext().getNaturalIdSnapshot( entry.getId(), persister ) - : session.getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues( loaded, persister ); + if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) { + return; + } - for ( int i = 0; i < naturalIdentifierPropertiesIndexes.length; i++ ) { - final int naturalIdentifierPropertyIndex = naturalIdentifierPropertiesIndexes[i]; - if ( propertyUpdateability[naturalIdentifierPropertyIndex] ) { - // if the given natural id property is updatable (mutable), there is nothing to check - continue; - } + // now get to the checks + final int[] naturalIdentifierPropertiesIndexes = persister.getNaturalIdentifierProperties(); + final Type[] propertyTypes = persister.getPropertyTypes(); + final boolean[] propertyUpdateability = persister.getPropertyUpdateability(); - final Type propertyType = propertyTypes[naturalIdentifierPropertyIndex]; - if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) { - throw new HibernateException( - String.format( - "An immutable natural identifier of entity %s was altered from %s to %s", - persister.getEntityName(), - propertyTypes[naturalIdentifierPropertyIndex].toLoggableString( - snapshot[i], - session.getFactory() - ), - propertyTypes[naturalIdentifierPropertyIndex].toLoggableString( - current[naturalIdentifierPropertyIndex], - session.getFactory() - ) - ) - ); - } + final Object[] snapshot = loaded == null + ? session.getPersistenceContext().getNaturalIdSnapshot( entry.getId(), persister ) + : session.getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues( loaded, persister ); + + for ( int i = 0; i < naturalIdentifierPropertiesIndexes.length; i++ ) { + final int naturalIdentifierPropertyIndex = naturalIdentifierPropertiesIndexes[i]; + if ( propertyUpdateability[naturalIdentifierPropertyIndex] ) { + // if the given natural id property is updatable (mutable), there is nothing to check + continue; + } + + final Type propertyType = propertyTypes[naturalIdentifierPropertyIndex]; + if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) { + throw new HibernateException( + String.format( + "An immutable natural identifier of entity %s was altered from %s to %s", + persister.getEntityName(), + propertyTypes[naturalIdentifierPropertyIndex].toLoggableString( + snapshot[i], + session.getFactory() + ), + propertyTypes[naturalIdentifierPropertyIndex].toLoggableString( + current[naturalIdentifierPropertyIndex], + session.getFactory() + ) + ) + ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultLoadEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultLoadEventListener.java index 0c8a112cb644..593d04c9f345 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultLoadEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultLoadEventListener.java @@ -103,11 +103,49 @@ public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType) throws throw new HibernateException( "Unable to locate persister: " + event.getEntityClassName() ); } + // There are 2 (related) cases we need to account for where JPA + // defines special handling for find-by-id in terms of the allowable + // id type: + // + // FIRST, where the identifier for the entity to be loaded is a + // to-one association to another entity E.g.: + // @Id + // @ManyToOne + // private Parent myParent; + // here, JPA allows loading this "dependent" entity using the + // identifier type of the "parent". E.g.: + // em.find( Dependent.class, parent.getId() ); + // rather than: + // em.find( Dependent.class, parent ); + final Type entityIdentifierType = persister.getIdentifierType(); + if ( !entityIdentifierType.getReturnedClass().isInstance( event.getEntityId() ) ) { + if ( entityIdentifierType.isEntityType() ) { + final EntityType parentEntityType = (EntityType) entityIdentifierType; + final Type parentEntityIdentifierType = parentEntityType + .getIdentifierOrUniqueKeyType( source.getFactory() ); + if ( parentEntityIdentifierType.getReturnedClass().isInstance( event.getEntityId() ) ) { + // So we have the described situation + final EntityPersister parentEntityPersister = source.getFactory() + .getEntityPersister( parentEntityType.getAssociatedEntityName() ); + final EntityKey parentEntityKey = event.getSession() + .generateEntityKey( event.getEntityId(), parentEntityPersister ); + final Object parent = doLoad( event, parentEntityPersister, parentEntityKey, loadType ); + final EntityKey dependentEntityKey = event.getSession() + .generateEntityKey( (Serializable) parent, persister ); + event.setEntityId( (Serializable) parent ); + final Object dependent = doLoad( event, persister, dependentEntityKey, loadType ); + event.setResult( dependent ); + + // EARLY EXIT!! + return; + } + } + } + + // SECOND, we have essentially the same situation described above, + // but the to-one association is wrapped in a composition final Class idClass = persister.getIdentifierType().getReturnedClass(); if ( idClass != null && !idClass.isInstance( event.getEntityId() ) ) { - // we may have the kooky jpa requirement of allowing find-by-id where - // "id" is the "simple pk value" of a dependent objects parent. This - // is part of its generally goofy "derived identity" "feature" if ( persister.getEntityMetamodel().getIdentifierProperty().isEmbedded() ) { final EmbeddedComponentType dependentIdType = (EmbeddedComponentType) persister.getEntityMetamodel().getIdentifierProperty().getType(); @@ -169,10 +207,10 @@ private void loadByDerivedIdentitySimplePkValue( final EntityKey parentEntityKey = event.getSession().generateEntityKey( event.getEntityId(), parentPersister ); final Object parent = doLoad( event, parentPersister, parentEntityKey, options ); - final Serializable dependent = (Serializable) dependentIdType.instantiate( parent, event.getSession() ); - dependentIdType.setPropertyValues( dependent, new Object[] {parent}, dependentPersister.getEntityMode() ); - final EntityKey dependentEntityKey = event.getSession().generateEntityKey( dependent, dependentPersister ); - event.setEntityId( dependent ); + final Serializable dependentId = (Serializable) dependentIdType.instantiate( parent, event.getSession() ); + dependentIdType.setPropertyValues( dependentId, new Object[] {parent}, dependentPersister.getEntityMode() ); + final EntityKey dependentEntityKey = event.getSession().generateEntityKey( dependentId, dependentPersister ); + event.setEntityId( dependentId ); event.setResult( doLoad( event, dependentPersister, dependentEntityKey, options ) ); } @@ -591,7 +629,7 @@ protected Object loadFromSecondLevelCache( final CacheKey ck = source.generateCacheKey( event.getEntityId(), persister.getIdentifierType(), - persister.getRootEntityName() + persister.getEntityName() ); final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() ); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java index ae4339585c4f..de6247731633 100755 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java @@ -211,14 +211,14 @@ protected void entityIsTransient(MergeEvent event, Map copyCache) { // copy created before we actually copy //cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE); super.cascadeBeforeSave( source, persister, entity, copyCache ); - copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ); + copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FROM_PARENT ); saveTransientEntity( copy, entityName, event.getRequestedId(), source, copyCache ); // cascade first, so that all unsaved objects get their // copy created before we actually copy super.cascadeAfterSave( source, persister, entity, copyCache ); - copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ); + copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT ); event.setResult( copy ); } @@ -391,7 +391,7 @@ protected void copyValues( final Object[] copiedValues; - if ( foreignKeyDirection == ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ) { + if ( foreignKeyDirection == ForeignKeyDirection.TO_PARENT ) { // this is the second pass through on a merge op, so here we limit the // replacement to associations types (value types were already replaced // during the first pass) diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java index 8f97f1dfcc73..fbd8c0e5562f 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java @@ -428,11 +428,20 @@ private static void prepareListeners(EventType type, Map void prepareListeners(EventType type, T defaultListener, Map map) { - final EventListenerGroupImpl listeners = new EventListenerGroupImpl( type ); + final EventListenerGroupImpl listenerGroup; + if ( type == EventType.POST_COMMIT_DELETE + || type == EventType.POST_COMMIT_INSERT + || type == EventType.POST_COMMIT_UPDATE ) { + listenerGroup = new PostCommitEventListenerGroupImpl( type ); + } + else { + listenerGroup = new EventListenerGroupImpl( type ); + } + if ( defaultListener != null ) { - listeners.appendListener( defaultListener ); + listenerGroup.appendListener( defaultListener ); } - map.put( type, listeners ); + map.put( type, listenerGroup ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java index 76493f43d5c6..60ecbab05bbf 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerServiceInitiator.java @@ -26,7 +26,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.service.spi.EventListenerRegistry; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/PostCommitEventListenerGroupImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/PostCommitEventListenerGroupImpl.java new file mode 100644 index 000000000000..840e856619ca --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/PostCommitEventListenerGroupImpl.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.event.service.internal; + +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitDeleteEventListener; +import org.hibernate.event.spi.PostCommitInsertEventListener; +import org.hibernate.event.spi.PostCommitUpdateEventListener; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; + +/** + * Historically, the listeners for the post-commit events simply reused the + * contracts from the non-post-commit variants. That has changed as part of + * the work for HHH-1582. The purpose of this specialized EventListenerGroup + * implementation is to recognize cases where post-commit event listeners + * are still using the legacy contracts and to issue "deprecation warnings". + * + * @author Steve Ebersole + */ +public class PostCommitEventListenerGroupImpl extends EventListenerGroupImpl { + private static final CoreMessageLogger log = CoreLogging.messageLogger( PostCommitEventListenerGroupImpl.class ); + + private final Class extendedListenerContract; + + public PostCommitEventListenerGroupImpl(EventType eventType) { + super( eventType ); + + if ( eventType == EventType.POST_COMMIT_DELETE ) { + this.extendedListenerContract = PostCommitDeleteEventListener.class; + } + else if ( eventType == EventType.POST_COMMIT_INSERT ) { + this.extendedListenerContract = PostCommitInsertEventListener.class; + } + else if ( eventType == EventType.POST_COMMIT_UPDATE ) { + this.extendedListenerContract = PostCommitUpdateEventListener.class; + } + else { + throw new IllegalStateException( "Unexpected usage of PostCommitEventListenerGroupImpl" ); + } + } + + @Override + public void appendListener(T listener) { + checkAgainstExtendedContract( listener ); + super.appendListener( listener ); + } + + private void checkAgainstExtendedContract(T listener) { + if ( !extendedListenerContract.isInstance( listener ) ) { + log.warnf( + "Encountered event listener [%s] for post-commit event [%s] " + + "which did not implement the corresponding extended " + + "listener contract [%s]", + listener.getClass().getName(), + getEventType().eventName(), + extendedListenerContract.getName() + ); + } + } + + @Override + public void prependListener(T listener) { + checkAgainstExtendedContract( listener ); + super.prependListener( listener ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEvent.java b/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEvent.java index ee975967d2ba..b291bc106d78 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEvent.java +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEvent.java @@ -25,6 +25,7 @@ import java.io.Serializable; +import org.hibernate.AssertionFailure; import org.hibernate.LockMode; import org.hibernate.LockOptions; @@ -35,6 +36,25 @@ */ public class LoadEvent extends AbstractEvent { public static final LockMode DEFAULT_LOCK_MODE = LockMode.NONE; + //Performance hotspot: avoid allocating unneeded LockOptions + public static final LockOptions DEFAULT_LOCK_OPTIONS = new LockOptions() { + @Override + public LockOptions setLockMode(LockMode lockMode) { + throw new AssertionFailure( "Should not be invoked: DEFAULT_LOCK_OPTIONS needs to be treated as immutable." ); + } + @Override + public LockOptions setAliasSpecificLockMode(String alias, LockMode lockMode) { + throw new AssertionFailure( "Should not be invoked: DEFAULT_LOCK_OPTIONS needs to be treated as immutable." ); + } + @Override + public LockOptions setTimeOut(int timeout) { + throw new AssertionFailure( "Should not be invoked: DEFAULT_LOCK_OPTIONS needs to be treated as immutable." ); + } + @Override + public LockOptions setScope(boolean scope) { + throw new AssertionFailure( "Should not be invoked: DEFAULT_LOCK_OPTIONS needs to be treated as immutable." ); + } + }; private Serializable entityId; private String entityClassName; @@ -44,19 +64,19 @@ public class LoadEvent extends AbstractEvent { private Object result; public LoadEvent(Serializable entityId, Object instanceToLoad, EventSource source) { - this(entityId, null, instanceToLoad, new LockOptions(), false, source); + this( entityId, null, instanceToLoad, DEFAULT_LOCK_OPTIONS, false, source ); } public LoadEvent(Serializable entityId, String entityClassName, LockMode lockMode, EventSource source) { - this(entityId, entityClassName, null, lockMode, false, source); + this( entityId, entityClassName, null, lockMode, false, source ); } public LoadEvent(Serializable entityId, String entityClassName, LockOptions lockOptions, EventSource source) { - this(entityId, entityClassName, null, lockOptions, false, source); + this( entityId, entityClassName, null, lockOptions, false, source ); } public LoadEvent(Serializable entityId, String entityClassName, boolean isAssociationFetch, EventSource source) { - this(entityId, entityClassName, null, new LockOptions(), isAssociationFetch, source); + this( entityId, entityClassName, null, DEFAULT_LOCK_OPTIONS, isAssociationFetch, source ); } public boolean isAssociationFetch() { @@ -70,7 +90,9 @@ private LoadEvent( LockMode lockMode, boolean isAssociationFetch, EventSource source) { - this(entityId, entityClassName, instanceToLoad, new LockOptions().setLockMode(lockMode), isAssociationFetch, source ); + this( entityId, entityClassName, instanceToLoad, + lockMode == DEFAULT_LOCK_MODE ? DEFAULT_LOCK_OPTIONS : new LockOptions().setLockMode( lockMode ), + isAssociationFetch, source ); } private LoadEvent( @@ -134,11 +156,23 @@ public LockMode getLockMode() { } public void setLockMode(LockMode lockMode) { - this.lockOptions.setLockMode(lockMode); + if ( lockMode != lockOptions.getLockMode() ) { + writingOnLockOptions(); + this.lockOptions.setLockMode( lockMode ); + } + } + + private void writingOnLockOptions() { + if ( lockOptions == DEFAULT_LOCK_OPTIONS ) { + this.lockOptions = new LockOptions(); + } } public void setLockTimeout(int timeout) { - this.lockOptions.setTimeOut(timeout); + if ( timeout != lockOptions.getTimeOut() ) { + writingOnLockOptions(); + this.lockOptions.setTimeOut( timeout ); + } } public int getLockTimeout() { @@ -146,7 +180,10 @@ public int getLockTimeout() { } public void setLockScope(boolean cascade) { - this.lockOptions.setScope(cascade); + if ( lockOptions.getScope() != cascade ) { + writingOnLockOptions(); + this.lockOptions.setScope( cascade ); + } } public boolean getLockScope() { diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEventListener.java index 60e75a233127..c85ed33419c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/LoadEventListener.java @@ -43,7 +43,7 @@ public interface LoadEventListener extends Serializable { */ public void onLoad(LoadEvent event, LoadType loadType) throws HibernateException; - public static final LoadType RELOAD = new LoadType( "GET" ) + public static final LoadType RELOAD = new LoadType( "RELOAD" ) .setAllowNulls( false ) .setAllowProxyCreation( false ) .setCheckDeleted( true ) diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitDeleteEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitDeleteEventListener.java new file mode 100644 index 000000000000..dd49d43300a5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitDeleteEventListener.java @@ -0,0 +1,15 @@ +package org.hibernate.event.spi; + +/** + * Called after an entity delete is committed to the datastore. + * + * @author Shawn Clowater + */ +public interface PostCommitDeleteEventListener extends PostDeleteEventListener { + /** + * Called when a commit fails and an an entity was scheduled for deletion + * + * @param event the delete event to be handled + */ + public void onPostDeleteCommitFailed(PostDeleteEvent event); +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitInsertEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitInsertEventListener.java new file mode 100644 index 000000000000..f2d4f0f47700 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitInsertEventListener.java @@ -0,0 +1,15 @@ +package org.hibernate.event.spi; + +/** + * Called after an entity insert is committed to the datastore. + * + * @author Shawn Clowater + */ +public interface PostCommitInsertEventListener extends PostInsertEventListener { + /** + * Called when a commit fails and an an entity was scheduled for insertion + * + * @param event the insert event to be handled + */ + public void onPostInsertCommitFailed(PostInsertEvent event); +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitUpdateEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitUpdateEventListener.java new file mode 100644 index 000000000000..3fb27823c1a1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitUpdateEventListener.java @@ -0,0 +1,15 @@ +package org.hibernate.event.spi; + +/** + * Called after an entity update is committed to the datastore. + * + * @author Shawn Clowater + */ +public interface PostCommitUpdateEventListener extends PostUpdateEventListener { + /** + * Called when a commit fails and an an entity was scheduled for update + * + * @param event the update event to be handled + */ + public void onPostUpdateCommitFailed(PostUpdateEvent event); +} diff --git a/hibernate-core/src/main/java/org/hibernate/exception/spi/SQLExceptionConverterFactory.java b/hibernate-core/src/main/java/org/hibernate/exception/spi/SQLExceptionConverterFactory.java index a1cfb474dcb2..3159312652c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/exception/spi/SQLExceptionConverterFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/exception/spi/SQLExceptionConverterFactory.java @@ -35,7 +35,6 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; - import org.jboss.logging.Logger; /** @@ -71,11 +70,6 @@ public static SQLExceptionConverter buildSQLExceptionConverter(Dialect dialect, converter = constructConverter( converterClassName, dialect.getViolatedConstraintNameExtracter() ); } - if ( converter == null ) { - LOG.trace( "Using dialect defined converter" ); - converter = dialect.buildSQLExceptionConverter(); - } - if ( converter instanceof Configurable ) { try { ( (Configurable) converter ).configure( properties ); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphNodeImplementor.java b/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphNodeImplementor.java index 708757e43c06..774cc7543530 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphNodeImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphNodeImplementor.java @@ -32,4 +32,5 @@ public interface GraphNodeImplementor { List> attributeImplementorNodes(); List> attributeNodes(); + boolean containsAttribute(String name); } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java index eb7bf0b9f673..9ce4794de643 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java @@ -47,6 +47,7 @@ import org.hibernate.hql.internal.antlr.SqlTokenTypes; import org.hibernate.hql.internal.ast.tree.AggregateNode; import org.hibernate.hql.internal.ast.tree.AssignmentSpecification; +import org.hibernate.hql.internal.ast.tree.CastFunctionNode; import org.hibernate.hql.internal.ast.tree.CollectionFunction; import org.hibernate.hql.internal.ast.tree.ConstructorNode; import org.hibernate.hql.internal.ast.tree.DeleteStatement; @@ -1076,6 +1077,12 @@ protected void processFunction(AST functionCall, boolean inSelect) throws Semant methodNode.resolve( inSelect ); } + @Override + protected void processCastFunction(AST castFunctionCall, boolean inSelect) throws SemanticException { + CastFunctionNode castFunctionNode = (CastFunctionNode) castFunctionCall; + castFunctionNode.resolve( inSelect ); + } + @Override protected void processAggregation(AST node, boolean inSelect) throws SemanticException { AggregateNode aggregateNode = (AggregateNode) node; diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlASTFactory.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlASTFactory.java index 293f50ffacc9..9e40176f4403 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlASTFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlASTFactory.java @@ -32,8 +32,9 @@ import org.hibernate.hql.internal.ast.tree.BinaryArithmeticOperatorNode; import org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode; import org.hibernate.hql.internal.ast.tree.BooleanLiteralNode; -import org.hibernate.hql.internal.ast.tree.Case2Node; -import org.hibernate.hql.internal.ast.tree.CaseNode; +import org.hibernate.hql.internal.ast.tree.CastFunctionNode; +import org.hibernate.hql.internal.ast.tree.SearchedCaseNode; +import org.hibernate.hql.internal.ast.tree.SimpleCaseNode; import org.hibernate.hql.internal.ast.tree.CollectionFunction; import org.hibernate.hql.internal.ast.tree.ConstructorNode; import org.hibernate.hql.internal.ast.tree.CountNode; @@ -133,6 +134,8 @@ public Class getASTNodeType(int tokenType) { return SqlFragment.class; case METHOD_CALL: return MethodNode.class; + case CAST: + return CastFunctionNode.class; case ELEMENTS: case INDICES: return CollectionFunction.class; @@ -171,9 +174,9 @@ public Class getASTNodeType(int tokenType) { case UNARY_PLUS: return UnaryArithmeticNode.class; case CASE2: - return Case2Node.class; + return SimpleCaseNode.class; case CASE: - return CaseNode.class; + return SearchedCaseNode.class; case PARAM: case NAMED_PARAM: return ParameterNode.class; diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java index 183c73c72002..8749fa7f61c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java @@ -44,6 +44,7 @@ import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.param.ParameterSpecification; import org.hibernate.type.Type; @@ -145,8 +146,8 @@ else if ( n instanceof ParameterContainer ) { } @Override - protected void commaBetweenParameters(String comma) { - writer.commaBetweenParameters( comma ); + protected void betweenFunctionArguments() { + writer.betweenFunctionArguments(); } @Override @@ -208,7 +209,12 @@ protected void beginFunctionTemplate(AST node, AST nameNode) { else { // this function has a registered SQLFunction -> redirect output and catch the arguments outputStack.addFirst( writer ); - writer = new FunctionArguments(); + if ( node.getType() == CAST ) { + writer = new CastFunctionArguments(); + } + else { + writer = new StandardFunctionArguments(); + } } } @@ -222,7 +228,7 @@ protected void endFunctionTemplate(AST node) { else { final Type functionType = functionNode.getFirstArgumentType(); // this function has a registered SQLFunction -> redirect output and catch the arguments - FunctionArguments functionArguments = (FunctionArguments) writer; + FunctionArgumentsCollectingWriter functionArguments = (FunctionArgumentsCollectingWriter) writer; writer = outputStack.removeFirst(); out( sqlFunction.render( functionType, functionArguments.getArgs(), sessionFactory ) ); } @@ -236,21 +242,18 @@ protected void endFunctionTemplate(AST node) { interface SqlWriter { void clause(String clause); - /** - * todo remove this hack - * The parameter is either ", " or " , ". This is needed to pass sql generating tests as the old - * sql generator uses " , " in the WHERE and ", " in SELECT. - * - * @param comma either " , " or ", " - */ - void commaBetweenParameters(String comma); + void betweenFunctionArguments(); + } + + interface FunctionArgumentsCollectingWriter extends SqlWriter { + public List getArgs(); } /** * SQL function processing code redirects generated SQL output to an instance of this class * which catches function arguments. */ - class FunctionArguments implements SqlWriter { + class StandardFunctionArguments implements FunctionArgumentsCollectingWriter { private int argInd; private final List args = new ArrayList( 3 ); @@ -265,7 +268,7 @@ public void clause(String clause) { } @Override - public void commaBetweenParameters(String comma) { + public void betweenFunctionArguments() { ++argInd; } @@ -274,6 +277,52 @@ public List getArgs() { } } + /** + * SQL function processing code redirects generated SQL output to an instance of this class + * which catches function arguments. + */ + class CastFunctionArguments implements FunctionArgumentsCollectingWriter { + private String castExpression; + private String castTargetType; + + private boolean startedType; + + @Override + public void clause(String clause) { + if ( startedType ) { + if ( castTargetType == null ) { + castTargetType = clause; + } + else { + castTargetType += clause; + } + } + else { + if ( castExpression == null ) { + castExpression = clause; + } + else { + castExpression += clause; + } + } + } + + @Override + public void betweenFunctionArguments() { + if ( startedType ) { + throw new QueryException( "CAST function should only have 2 arguments" ); + } + startedType = true; + } + + public List getArgs() { + List rtn = CollectionHelper.arrayList( 2 ); + rtn.add( castExpression ); + rtn.add( castTargetType ); + return rtn; + } + } + /** * The default SQL writer. */ @@ -284,8 +333,8 @@ public void clause(String clause) { } @Override - public void commaBetweenParameters(String comma) { - getStringBuilder().append( comma ); + public void betweenFunctionArguments() { + getStringBuilder().append( ", " ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java index 0b8f40561d30..be9f09765b52 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java @@ -29,6 +29,7 @@ import org.hibernate.TypeMismatchException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; +import org.hibernate.hql.internal.ast.util.ColumnHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.param.ParameterSpecification; import org.hibernate.type.OneToOneType; @@ -43,7 +44,7 @@ * * @author Steve Ebersole */ -public class BinaryLogicOperatorNode extends HqlSqlWalkerNode implements BinaryOperatorNode { +public class BinaryLogicOperatorNode extends AbstractSelectExpression implements BinaryOperatorNode { /** * Performs the operator node initialization by seeking out any parameter * nodes and setting their expected type, if possible. @@ -268,4 +269,8 @@ public Node getLeftHandOperand() { public Node getRightHandOperand() { return (Node) getFirstChild().getNextSibling(); } + + public void setScalarColumnText(int i) throws SemanticException { + ColumnHelper.generateSingleScalarColumn( this, i ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/Case2Node.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/Case2Node.java deleted file mode 100644 index 2dc65faca670..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/Case2Node.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - * - */ -package org.hibernate.hql.internal.ast.tree; - -import org.hibernate.hql.internal.ast.util.ColumnHelper; -import org.hibernate.type.Type; - -import antlr.SemanticException; - -/** - * Represents a case ... when .. then ... else ... end expression in a select. - * - * @author Gavin King - */ -public class Case2Node extends AbstractSelectExpression implements SelectExpression { - - public Type getDataType() { - return getFirstThenNode().getDataType(); - } - - private SelectExpression getFirstThenNode() { - return (SelectExpression) getFirstChild().getNextSibling().getFirstChild().getNextSibling(); - } - - public void setScalarColumnText(int i) throws SemanticException { - ColumnHelper.generateSingleScalarColumn( this, i ); - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CaseNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CaseNode.java deleted file mode 100644 index f8b73dd3bb9c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CaseNode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - * - */ -package org.hibernate.hql.internal.ast.tree; - -import org.hibernate.hql.internal.ast.util.ColumnHelper; -import org.hibernate.type.Type; - -import antlr.SemanticException; - -/** - * Represents a case ... when .. then ... else ... end expression in a select. - * - * @author Gavin King - */ -public class CaseNode extends AbstractSelectExpression implements SelectExpression { - - public Type getDataType() { - return getFirstThenNode().getDataType(); - } - - private SelectExpression getFirstThenNode() { - return (SelectExpression) getFirstChild().getFirstChild().getNextSibling(); - } - - public void setScalarColumnText(int i) throws SemanticException { - ColumnHelper.generateSingleScalarColumn( this, i ); - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CastFunctionNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CastFunctionNode.java new file mode 100644 index 000000000000..766554de635e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CastFunctionNode.java @@ -0,0 +1,115 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.hql.internal.ast.tree; + +import org.hibernate.QueryException; +import org.hibernate.dialect.function.CastFunction; +import org.hibernate.dialect.function.SQLFunction; +import org.hibernate.hql.internal.ast.util.ColumnHelper; +import org.hibernate.type.Type; + +import antlr.SemanticException; + +/** + * Represents a cast function call. We handle this specially because its type + * argument has a semantic meaning to the HQL query (its not just pass through). + * + * @author Steve Ebersole + */ +public class CastFunctionNode extends AbstractSelectExpression implements FunctionNode { + private SQLFunction dialectCastFunction; + + private Node expressionNode; + + private IdentNode typeNode; + private Type castType; + + + /** + * Called from the hql-sql grammar after the children of the CAST have been resolved. + * + * @param inSelect Is this call part of the SELECT clause? + */ + public void resolve(boolean inSelect) { + this.dialectCastFunction = getSessionFactoryHelper().findSQLFunction( "cast" ); + if ( dialectCastFunction == null ) { + dialectCastFunction = CastFunction.INSTANCE; + } + + this.expressionNode = (Node) getFirstChild(); + if ( expressionNode == null ) { + throw new QueryException( "Could not resolve expression to CAST" ); + } + if ( SqlNode.class.isInstance( expressionNode ) ) { + final Type expressionType = ( (SqlNode) expressionNode ).getDataType(); + if ( expressionType != null ) { + if ( expressionType.isEntityType() ) { + throw new QueryException( "Expression to CAST cannot be an entity : " + expressionNode.getText() ); + } + if ( expressionType.isComponentType() ) { + throw new QueryException( "Expression to CAST cannot be a composite : " + expressionNode.getText() ); + } + if ( expressionType.isCollectionType() ) { + throw new QueryException( "Expression to CAST cannot be a collection : " + expressionNode.getText() ); + } + } + } + + this.typeNode = (IdentNode) expressionNode.getNextSibling(); + if ( typeNode == null ) { + throw new QueryException( "Could not resolve requested type for CAST" ); + } + + final String typeName = typeNode.getText(); + this.castType = getSessionFactoryHelper().getFactory().getTypeResolver().heuristicType( typeName ); + if ( castType == null ) { + throw new QueryException( "Could not resolve requested type for CAST : " + typeName ); + } + if ( castType.isEntityType() ) { + throw new QueryException( "CAST target type cannot be an entity : " + expressionNode.getText() ); + } + if ( castType.isComponentType() ) { + throw new QueryException( "CAST target type cannot be a composite : " + expressionNode.getText() ); + } + if ( castType.isCollectionType() ) { + throw new QueryException( "CAST target type cannot be a collection : " + expressionNode.getText() ); + } + setDataType( castType ); + } + + @Override + public SQLFunction getSQLFunction() { + return dialectCastFunction; + } + + @Override + public Type getFirstArgumentType() { + return castType; + } + + @Override + public void setScalarColumnText(int i) throws SemanticException { + ColumnHelper.generateSingleScalarColumn( this, i ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java index 1d4ef4ab24a8..97d3ff937c1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java @@ -260,7 +260,10 @@ else if ( propertyType.isCollectionType() ) { private void initText() { String[] cols = getColumns(); String text = StringHelper.join( ", ", cols ); - if ( cols.length > 1 && getWalker().isComparativeExpressionClause() ) { + boolean countDistinct = getWalker().isInCountDistinct() + && getWalker().getSessionFactoryHelper().getFactory().getDialect().requiresParensForTupleDistinctCounts(); + if ( cols.length > 1 && + ( getWalker().isComparativeExpressionClause() || countDistinct ) ) { text = "(" + text + ")"; } setText( text ); diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IdentNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IdentNode.java index 88d33dd61b65..3acabfcef6b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IdentNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IdentNode.java @@ -27,6 +27,7 @@ import java.util.List; import org.hibernate.QueryException; +import org.hibernate.dialect.Dialect; import org.hibernate.dialect.function.SQLFunction; import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; import org.hibernate.hql.internal.antlr.SqlTokenTypes; @@ -173,10 +174,14 @@ private boolean resolveAsAlias() { } } - final boolean isInNonDistinctCount = getWalker().isInCount() && ! getWalker().isInCountDistinct(); + final Dialect dialect = getWalker().getSessionFactoryHelper().getFactory().getDialect(); + final boolean isInCount = getWalker().isInCount(); + final boolean isInDistinctCount = isInCount && getWalker().isInCountDistinct(); + final boolean isInNonDistinctCount = isInCount && ! getWalker().isInCountDistinct(); final boolean isCompositeValue = columnExpressions.length > 1; if ( isCompositeValue ) { - if ( isInNonDistinctCount && ! getWalker().getSessionFactoryHelper().getFactory().getDialect().supportsTupleCounts() ) { + if ( isInNonDistinctCount && ! dialect.supportsTupleCounts() ) { + // TODO: #supportsTupleCounts currently false for all Dialects -- could this be cleaned up? setText( columnExpressions[0] ); } else { @@ -184,7 +189,8 @@ private boolean resolveAsAlias() { // avoid wrapping in parenthesis (explicit tuple treatment) if possible due to varied support for // tuple syntax across databases.. final boolean shouldSkipWrappingInParenthesis = - getWalker().isInCount() + (isInDistinctCount && ! dialect.requiresParensForTupleDistinctCounts()) + || isInNonDistinctCount || getWalker().getCurrentTopLevelClauseType() == HqlSqlTokenTypes.ORDER || getWalker().getCurrentTopLevelClauseType() == HqlSqlTokenTypes.GROUP; if ( ! shouldSkipWrappingInParenthesis ) { diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MethodNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MethodNode.java index ae73c87977d1..e2d6df5b3b21 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MethodNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/MethodNode.java @@ -133,13 +133,9 @@ private void dialectFunction(AST exprList) { if ( function != null ) { AST firstChild = exprList != null ? exprList.getFirstChild() : null; Type functionReturnType = getSessionFactoryHelper() - .findFunctionReturnType( methodName, firstChild ); + .findFunctionReturnType( methodName, function, firstChild ); setDataType( functionReturnType ); } - //TODO: - /*else { - methodName = (String) getWalker().getTokenReplacements().get( methodName ); - }*/ } public boolean isCollectionPropertyMethod() { diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SearchedCaseNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SearchedCaseNode.java new file mode 100644 index 000000000000..0262907dc9c9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SearchedCaseNode.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + * + */ +package org.hibernate.hql.internal.ast.tree; + +import org.hibernate.QueryException; +import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; +import org.hibernate.hql.internal.ast.util.ASTUtil; +import org.hibernate.hql.internal.ast.util.ColumnHelper; +import org.hibernate.type.Type; + +import antlr.SemanticException; +import antlr.collections.AST; + +/** + * Models what ANSI SQL terms a searched case expression. This is a CASE expression + * in the form

    + * CASE
    + *     WHEN [firstCondition] THEN [firstResult]
    + *     WHEN [secondCondition] THEN [secondResult]
    + *     ELSE [defaultResult]
    + * END
    + * 
    + * + * @author Gavin King + * @author Steve Ebersole + */ +public class SearchedCaseNode extends AbstractSelectExpression implements SelectExpression { + @Override + public Type getDataType() { + // option is used to hold each WHEN/ELSE in turn + AST option = getFirstChild(); + while ( option != null ) { + final AST result; + if ( option.getType() == HqlSqlTokenTypes.WHEN ) { + result = option.getFirstChild().getNextSibling(); + } + else if ( option.getType() == HqlSqlTokenTypes.ELSE ) { + result = option.getFirstChild(); + } + else { + throw new QueryException( + "Unexpected node type :" + + ASTUtil.getTokenTypeName( HqlSqlTokenTypes.class, option.getType() ) + + "; expecting WHEN or ELSE" + ); + } + + if ( SqlNode.class.isInstance( result ) ) { + final Type nodeDataType = ( (SqlNode) result ).getDataType(); + if ( nodeDataType != null ) { + return nodeDataType; + } + } + + option = option.getNextSibling(); + } + + throw new QueryException( "Could not determine data type for searched case statement" ); + } + + @Override + public void setScalarColumnText(int i) throws SemanticException { + ColumnHelper.generateSingleScalarColumn( this, i ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SimpleCaseNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SimpleCaseNode.java new file mode 100644 index 000000000000..e46fa7f14a79 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SimpleCaseNode.java @@ -0,0 +1,87 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + * + */ +package org.hibernate.hql.internal.ast.tree; + +import org.hibernate.QueryException; +import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; +import org.hibernate.hql.internal.ast.util.ASTUtil; +import org.hibernate.hql.internal.ast.util.ColumnHelper; +import org.hibernate.type.Type; + +import antlr.SemanticException; +import antlr.collections.AST; + +/** + * Models what ANSI SQL terms a simple case statement. This is a CASE expression in the form
    + * CASE [expression]
    + *     WHEN [firstCondition] THEN [firstResult]
    + *     WHEN [secondCondition] THEN [secondResult]
    + *     ELSE [defaultResult]
    + * END
    + * 
    + * + * @author Gavin King + * @author Steve Ebersole + */ +public class SimpleCaseNode extends AbstractSelectExpression implements SelectExpression { + + public Type getDataType() { + final AST expression = getFirstChild(); + // option is used to hold each WHEN/ELSE in turn + AST option = expression.getNextSibling(); + while ( option != null ) { + final AST result; + if ( option.getType() == HqlSqlTokenTypes.WHEN ) { + result = option.getFirstChild().getNextSibling(); + } + else if ( option.getType() == HqlSqlTokenTypes.ELSE ) { + result = option.getFirstChild(); + } + else { + throw new QueryException( + "Unexpected node type :" + + ASTUtil.getTokenTypeName( HqlSqlTokenTypes.class, option.getType() ) + + "; expecting WHEN or ELSE" + ); + } + + if ( SqlNode.class.isInstance( result ) ) { + final Type nodeDataType = ( (SqlNode) result ).getDataType(); + if ( nodeDataType != null ) { + return nodeDataType; + } + } + + option = option.getNextSibling(); + } + + throw new QueryException( "Could not determine data type for simple case statement" ); + } + + public void setScalarColumnText(int i) throws SemanticException { + ColumnHelper.generateSingleScalarColumn( this, i ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/UnaryLogicOperatorNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/UnaryLogicOperatorNode.java index 197237dfad0c..02842d05266e 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/UnaryLogicOperatorNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/UnaryLogicOperatorNode.java @@ -23,6 +23,9 @@ */ package org.hibernate.hql.internal.ast.tree; +import antlr.SemanticException; + +import org.hibernate.hql.internal.ast.util.ColumnHelper; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; @@ -31,7 +34,7 @@ * * @author Steve Ebersole */ -public class UnaryLogicOperatorNode extends HqlSqlWalkerNode implements UnaryOperatorNode { +public class UnaryLogicOperatorNode extends AbstractSelectExpression implements UnaryOperatorNode { public Node getOperand() { return (Node) getFirstChild(); } @@ -45,4 +48,8 @@ public Type getDataType() { // logic operators by definition resolve to booleans return StandardBasicTypes.BOOLEAN; } + + public void setScalarColumnText(int i) throws SemanticException { + ColumnHelper.generateSingleScalarColumn( this, i ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/Assigned.java b/hibernate-core/src/main/java/org/hibernate/id/Assigned.java index c04ee9835d5b..a11e404416e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/Assigned.java +++ b/hibernate-core/src/main/java/org/hibernate/id/Assigned.java @@ -28,6 +28,7 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.Type; @@ -57,7 +58,7 @@ public Serializable generate(SessionImplementor session, Object obj) throws Hibe return id; } - public void configure(Type type, Properties params, Dialect d) throws MappingException { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { entityName = params.getProperty(ENTITY_NAME); if ( entityName == null ) { throw new MappingException("no entity name"); diff --git a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java index a924daaf91d3..2c824a95d4a6 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java @@ -22,9 +22,9 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.id; + import java.io.Serializable; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -102,7 +102,7 @@ public static interface GenerationPlan { } private final GenerationContextLocator generationContextLocator; - private List generationPlans = new ArrayList(); + private List generationPlans = new ArrayList(); public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) { this.generationContextLocator = generationContextLocator; @@ -115,19 +115,15 @@ public void addGeneratedValuePlan(GenerationPlan plan) { @Override public Serializable generate(SessionImplementor session, Object object) throws HibernateException { final Serializable context = generationContextLocator.locateGenerationContext( session, object ); - - for ( Object generationPlan : generationPlans ) { - final GenerationPlan plan = (GenerationPlan) generationPlan; + for ( final GenerationPlan plan : generationPlans ) { plan.execute( session, object, context ); } - return context; } @Override public void registerPersistentGenerators(Map generatorMap) { - for ( Object generationPlan : generationPlans ) { - final GenerationPlan plan = (GenerationPlan) generationPlan; + for(final GenerationPlan plan : generationPlans){ plan.registerPersistentGenerators( generatorMap ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/Configurable.java b/hibernate-core/src/main/java/org/hibernate/id/Configurable.java index a65bd7393d44..3c67868010ce 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/Configurable.java +++ b/hibernate-core/src/main/java/org/hibernate/id/Configurable.java @@ -26,6 +26,7 @@ import java.util.Properties; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.type.Type; @@ -43,7 +44,8 @@ public interface Configurable { * This method is called just once, following instantiation. * * @param params param values, keyed by parameter name + * @param classLoaderService */ - public void configure(Type type, Properties params, Dialect d) throws MappingException; + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException; } diff --git a/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java b/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java new file mode 100644 index 000000000000..d179e4e6fcb5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.id; + +/** + * Describes the nature of the entity-defined identifier. + * + * @author Steve Ebersole +*/ +public enum EntityIdentifierNature { + /** + * A simple identifier. Resolved as a basic type and mapped to a singular, basic attribute. Equivalent of:
      + *
    • an {@code } mapping
    • + *
    • a single {@code @Id} annotation
    • + *
    + */ + SIMPLE, + + /** + * What Hibernate used to term an "embedded composite identifier", which is not to be confused with the JPA + * term embedded. Resolved as a tuple of basic type values and mapped over multiple singular attributes. + * Specifically a composite identifier where there is no single attribute representing the composite value. + * Equivalent of:
      + *
    • + * a {@code } mapping without a specified {@code name} XML-attribute (which would name + * the single identifier attribute + *
    • + *
    • + * multiple {@code @Id} annotations + *
    • + *
    + * + * NOTE : May or may not have a related "lookup identifier class" as indicated by a {@code @IdClass} annotation. + * + * @see javax.persistence.IdClass + */ + NON_AGGREGATED_COMPOSITE, + + /** + * Composite identifier mapped to a single entity attribute by means of an actual component class used to + * aggregate the tuple values. + * Equivalent of:
      + *
    • + * a {@code } mapping naming a single identifier attribute via the {@code name} XML-attribute + *
    • + *
    • + * an {@code @EmbeddedId} annotation + *
    • + *
    + * + * @see javax.persistence.EmbeddedId + */ + AGGREGATED_COMPOSITE +} diff --git a/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java index 5ce6fd5ca7e7..b8f14ca311c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/ForeignGenerator.java @@ -29,6 +29,7 @@ import org.hibernate.MappingException; import org.hibernate.Session; import org.hibernate.TransientObjectException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.SessionImplementor; @@ -80,7 +81,7 @@ public String getRole() { } @Override - public void configure(Type type, Properties params, Dialect d) { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) { propertyName = params.getProperty( "property" ); entityName = params.getProperty( ENTITY_NAME ); if ( propertyName==null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java index 0e62f2fbf43e..27c14ad3ee3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java @@ -118,9 +118,15 @@ public static Serializable get(ResultSet rs, String identifier, Type type) throw return ( (ResultSetIdentifierConsumer) customType.getUserType() ).consumeIdentifier( rs ); } } - + int columnCount = 1; + try { + columnCount = rs.getMetaData().getColumnCount(); + } + catch (Exception e) { + // Oracle driver can throw NPE on rs.getMetaData() + } Class clazz = type.getReturnedClass(); - if (rs.getMetaData().getColumnCount() == 1) { + if (columnCount == 1) { if ( clazz == Long.class ) { return rs.getLong( 1 ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java index 1c027464cbb6..3ce7ef48cd5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java @@ -31,6 +31,7 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; @@ -71,7 +72,7 @@ public synchronized Serializable generate(SessionImplementor session, Object obj return previousValueHolder.makeValueThenIncrement(); } - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { returnClass = type.getReturnedClass(); ObjectNameNormalizer normalizer = diff --git a/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java index 175e27207f3d..8525fe85835e 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/MultipleHiLoPerTableGenerator.java @@ -33,7 +33,9 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; +import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.FormatStyle; @@ -47,9 +49,13 @@ import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; import org.hibernate.jdbc.WorkExecutorVisitable; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.type.Type; - import org.jboss.logging.Logger; /** @@ -99,7 +105,12 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera private static final String DEFAULT_PK_COLUMN = "sequence_name"; private static final String DEFAULT_VALUE_COLUMN = "sequence_next_hi_value"; + private ObjectName qualifiedTableName; + private Identifier qualifiedPkColumnName; + private Identifier qualifiedValueColumnName; + private String tableName; + private Table table; private String pkColumnName; private String valueColumnName; private String query; @@ -143,6 +154,15 @@ public Object generatorKey() { return tableName; } + /** + * The bound Table for this generator. + * + * @return The table. + */ + public final Table getTable() { + return table; + } + public synchronized Serializable generate(final SessionImplementor session, Object obj) { final SqlStatementLogger statementLogger = session.getFactory().getServiceRegistry() .getService( JdbcServices.class ) @@ -268,42 +288,42 @@ private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager } } - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); tableName = normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( ID_TABLE, params, DEFAULT_TABLE ) ); if ( tableName.indexOf( '.' ) < 0 ) { - tableName = dialect.quote( tableName ); - final String schemaName = dialect.quote( - normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ) - ); - final String catalogName = dialect.quote( - normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ) - ); - tableName = Table.qualify( catalogName, schemaName, tableName ); + final String normalizedTableName = tableName; + final String normalizedSchemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); + final String normalizedCatalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); + qualifiedTableName = new ObjectName( normalizedCatalogName, normalizedSchemaName, normalizedTableName ); + tableName = qualifiedTableName.toText( dialect ); } else { - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. + qualifiedTableName = ObjectName.parse( tableName ); } - pkColumnName = dialect.quote( + qualifiedPkColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN ) ) ); - valueColumnName = dialect.quote( + pkColumnName = qualifiedPkColumnName.getText( dialect ); + + qualifiedValueColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN ) ) ); + valueColumnName = qualifiedValueColumnName.getText( dialect ); + keySize = ConfigurationHelper.getInt(PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH); String keyValue = ConfigurationHelper.getString(PK_VALUE_NAME, params, params.getProperty(TABLE) ); query = "select " + valueColumnName + " from " + - dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) + + dialect.appendLockHint( new LockOptions( LockMode.PESSIMISTIC_WRITE ), tableName ) + " where " + pkColumnName + " = '" + keyValue + "'" + dialect.getForUpdateString(); @@ -332,4 +352,20 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp hiloOptimizer = new LegacyHiLoAlgorithmOptimizer( returnClass, maxLo ); } } + + @Override + public void registerExportables(Database database) { + final Dialect dialect = database.getJdbcEnvironment().getDialect(); + + final Schema schema = database.getSchemaFor( qualifiedTableName ); + table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() ); + + final Column pkColumn = table.createColumn( qualifiedPkColumnName ); + table.getPrimaryKey().addColumn( pkColumn ); + // todo : leverage TypeInfo-like info from JdbcEnvironment + pkColumn.setSqlType( dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) ); + + final Column valueColumn = table.createColumn( qualifiedValueColumnName ); + valueColumn.setSqlType( dialect.getTypeName( Types.INTEGER ) ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java index 2692c673985b..a96e8b0fdcd1 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java @@ -24,6 +24,7 @@ package org.hibernate.id; import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.ExportableProducer; /** * An IdentifierGenerator that requires creation of database objects. @@ -35,7 +36,7 @@ * @see Configurable * @author Gavin King */ -public interface PersistentIdentifierGenerator extends IdentifierGenerator { +public interface PersistentIdentifierGenerator extends IdentifierGenerator, ExportableProducer { /** * The configuration parameter holding the schema name diff --git a/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java index e0b7d28816a2..b8f25720581c 100755 --- a/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java @@ -32,6 +32,7 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.insert.AbstractSelectingDelegate; @@ -52,7 +53,7 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf private String uniqueKeyPropertyName; - public void configure(Type type, Properties params, Dialect d) throws MappingException { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { uniqueKeyPropertyName = params.getProperty( "key" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java index 6c26f4ed28e5..b02d0dabaa20 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceGenerator.java @@ -31,13 +31,15 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.type.Type; - import org.jboss.logging.Logger; /** @@ -50,12 +52,19 @@ * * @see SequenceHiLoGenerator * @author Gavin King + * + * @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} instead */ +@Deprecated public class SequenceGenerator implements PersistentIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, Configurable { private static final Logger LOG = Logger.getLogger( SequenceGenerator.class.getName() ); + public SequenceGenerator() { + LOG.warn( "Encountered use of deprecated " + getClass().getName() + " class" ); + } + /** * The sequence parameter */ @@ -67,6 +76,8 @@ public class SequenceGenerator */ public static final String PARAMETERS = "parameters"; + private ObjectName qualifiedSequenceName; + private String sequenceName; private String parameters; private Type identifierType; @@ -85,29 +96,24 @@ public String getSequenceName() { } @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); sequenceName = normalizer.normalizeIdentifierQuoting( ConfigurationHelper.getString( SEQUENCE, params, "hibernate_sequence" ) ); - parameters = params.getProperty( PARAMETERS ); - if ( sequenceName.indexOf( '.' ) < 0 ) { final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - sequenceName = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( sequenceName ) - ); + sequenceName = new ObjectName( catalogName, schemaName, sequenceName ).toText( dialect ); + this.qualifiedSequenceName = new ObjectName( catalogName, schemaName, sequenceName ); } else { - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. + this.qualifiedSequenceName = ObjectName.parse( sequenceName ); } + this.parameters = params.getProperty( PARAMETERS ); this.identifierType = type; - sql = dialect.getSequenceNextValString( sequenceName ); + this.sql = dialect.getSequenceNextValString( sequenceName ); } @Override @@ -149,10 +155,18 @@ protected IntegralDataTypeHolder buildHolder() { return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() ); } + @Override + public void registerExportables(Database database) { + final Schema schema = database.getSchemaFor( qualifiedSequenceName ); + if ( schema.locateSequence( qualifiedSequenceName.getName() ) == null ) { + schema.createSequence( qualifiedSequenceName.getName(), 1, 1 ); + } + } + @Override @SuppressWarnings( {"deprecation"}) public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { - String[] ddl = dialect.getCreateSequenceStrings( sequenceName ); + String[] ddl = new String[] { dialect.getCreateSequenceString( sequenceName ) }; if ( parameters != null ) { ddl[ddl.length - 1] += ' ' + parameters; } diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java index e0bfa069afa0..13b0e018bf4b 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceHiLoGenerator.java @@ -26,11 +26,14 @@ import java.util.Properties; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.enhanced.AccessCallback; import org.hibernate.id.enhanced.LegacyHiLoAlgorithmOptimizer; import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.type.Type; /** @@ -51,8 +54,8 @@ public class SequenceHiLoGenerator extends SequenceGenerator { private LegacyHiLoAlgorithmOptimizer hiloOptimizer; - public void configure(Type type, Properties params, Dialect d) throws MappingException { - super.configure(type, params, d); + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { + super.configure(type, params, d, classLoaderService ); maxLo = ConfigurationHelper.getInt( MAX_LO, params, 9 ); diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java index 1c7490651da0..df2c3e99b8ba 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceIdentityGenerator.java @@ -26,10 +26,10 @@ import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.Properties; + +import org.jboss.logging.Logger; import org.hibernate.HibernateException; -import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.insert.AbstractReturningDelegate; @@ -37,9 +37,6 @@ import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.sql.Insert; -import org.hibernate.type.Type; - -import org.jboss.logging.Logger; /** * A generator which combines sequence generation with immediate retrieval @@ -75,11 +72,6 @@ public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate( return new Delegate( persister, dialect, getSequenceName() ); } - @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { - super.configure( type, params, dialect ); - } - public static class Delegate extends AbstractReturningDelegate { private final Dialect dialect; private final String sequenceNextValFragment; diff --git a/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java index 6c919253e9a2..be14cf2cfec7 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java @@ -33,6 +33,8 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.FormatStyle; @@ -40,13 +42,12 @@ import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.engine.spi.SessionEventListenerManager; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.type.Type; - import org.jboss.logging.Logger; /** @@ -73,8 +74,9 @@ * * @see TableHiLoGenerator * @author Gavin King - * - * @deprecated use {@link SequenceStyleGenerator} instead. + * + * @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} or + * {@link org.hibernate.id.enhanced.TableGenerator} instead */ @Deprecated public class TableGenerator implements PersistentIdentifierGenerator, Configurable { @@ -99,7 +101,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab private String query; private String update; - public void configure(Type type, Properties params, Dialect dialect) { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) { identifierType = type; ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); @@ -108,11 +110,7 @@ public void configure(Type type, Properties params, Dialect dialect) { if ( tableName.indexOf( '.' ) < 0 ) { final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - tableName = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( tableName ) - ); + tableName = new ObjectName(catalogName, schemaName, tableName).toText( dialect ); } else { // if already qualified there is not much we can do in a portable manner so we pass it @@ -128,7 +126,7 @@ public void configure(Type type, Properties params, Dialect dialect) { query = "select " + columnName + " from " + - dialect.appendLockHint(LockMode.PESSIMISTIC_WRITE, tableName) + + dialect.appendLockHint(new LockOptions( LockMode.PESSIMISTIC_WRITE ), tableName) + dialect.getForUpdateString(); update = "update " + @@ -160,40 +158,50 @@ public IntegralDataTypeHolder execute(Connection connection) throws SQLException // The loop ensures atomicity of the select + update even for no transaction or // read committed isolation level do { - final PreparedStatement qps = prepareStatement( connection, query, statementLogger, listeners ); + final PreparedStatement qps = prepareStatement( + connection, + query, + statementLogger, + listeners + ); try { ResultSet rs = executeQuery( qps, listeners ); if ( !rs.next() ) { String err = "could not read a hi value - you need to populate the table: " + tableName; - LOG.error(err); - throw new IdentifierGenerationException(err); + LOG.error( err ); + throw new IdentifierGenerationException( err ); } value.initialize( rs, 1 ); rs.close(); } - catch (SQLException e) { - LOG.error("Could not read a hi value", e); + catch ( SQLException e ) { + LOG.error( "Could not read a hi value", e ); throw e; } finally { qps.close(); } - final PreparedStatement ups = prepareStatement( connection, update, statementLogger, listeners ); + final PreparedStatement ups = prepareStatement( + connection, + update, + statementLogger, + listeners + ); try { value.copy().increment().bind( ups, 1 ); value.bind( ups, 2 ); rows = executeUpdate( ups, listeners ); } - catch (SQLException sqle) { - LOG.error(LOG.unableToUpdateHiValue(tableName), sqle); + catch ( SQLException sqle ) { + LOG.error( LOG.unableToUpdateHiValue( tableName ), sqle ); throw sqle; } finally { ups.close(); } } - while (rows==0); + while ( rows == 0 ); return value; } }, @@ -237,6 +245,11 @@ private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager } } + @Override + public void registerExportables(Database database) { + // not doing anything here as I expect this to go away + } + public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return new String[] { dialect.getCreateTableString() + " " + tableName + " ( " diff --git a/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java index 60c339598086..df3b75d0ad1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/TableHiLoGenerator.java @@ -25,6 +25,7 @@ import java.io.Serializable; import java.util.Properties; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.enhanced.AccessCallback; @@ -63,8 +64,8 @@ public class TableHiLoGenerator extends TableGenerator { private int maxLo; @Override - public void configure(Type type, Properties params, Dialect d) { - super.configure( type, params, d ); + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) { + super.configure( type, params, d, classLoaderService ); maxLo = ConfigurationHelper.getInt( MAX_LO, params, Short.MAX_VALUE ); if ( maxLo >= 1 ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java index 74ae7ad2ddbd..f020a726c541 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/UUIDGenerator.java @@ -29,6 +29,8 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.uuid.StandardRandomStrategy; @@ -36,7 +38,6 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.UUIDTypeDescriptor; - import org.jboss.logging.Logger; /** @@ -72,7 +73,7 @@ public static UUIDGenerator buildSessionFactoryUniqueIdentifierGenerator() { return generator; } - public void configure(Type type, Properties params, Dialect d) throws MappingException { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) throws MappingException { // check first for the strategy instance strategy = (UUIDGenerationStrategy) params.get( UUID_GEN_STRATEGY ); if ( strategy == null ) { @@ -80,7 +81,14 @@ public void configure(Type type, Properties params, Dialect d) throws MappingExc final String strategyClassName = params.getProperty( UUID_GEN_STRATEGY_CLASS ); if ( strategyClassName != null ) { try { - final Class strategyClass = ReflectHelper.classForName( strategyClassName ); + final Class strategyClass; + // TODO: Exists purely for testing using the old .mappings. Eventually remove. + if (classLoaderService == null) { + strategyClass = ReflectHelper.classForName( strategyClassName ); + } + else { + strategyClass = classLoaderService.classForName( strategyClassName ); + } try { strategy = (UUIDGenerationStrategy) strategyClass.newInstance(); } @@ -88,9 +96,12 @@ public void configure(Type type, Properties params, Dialect d) throws MappingExc LOG.unableToInstantiateUuidGenerationStrategy(ignore); } } - catch ( ClassNotFoundException ignore ) { + catch ( ClassLoadingException ignore ) { LOG.unableToLocateUuidGenerationStrategy(strategyClassName); } + catch ( ClassNotFoundException ignore ) { + LOG.unableToLocateUuidGenerationStrategy(strategyClassName); + } } } if ( strategy == null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java index f8d4e42838d0..b1848111a4ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/UUIDHexGenerator.java @@ -26,6 +26,7 @@ import java.io.Serializable; import java.util.Properties; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.CoreMessageLogger; @@ -61,7 +62,7 @@ public UUIDHexGenerator() { } @Override - public void configure(Type type, Properties params, Dialect d) { + public void configure(Type type, Properties params, Dialect d, ClassLoaderService classLoaderService) { sep = ConfigurationHelper.getString( "separator", params, "" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java index f0080150f962..15aa56651dce 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/DatabaseStructure.java @@ -25,6 +25,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.metamodel.spi.relational.ExportableProducer; /** * Encapsulates definition of the underlying data structure backing a @@ -32,7 +33,7 @@ * * @author Steve Ebersole */ -public interface DatabaseStructure { +public interface DatabaseStructure extends ExportableProducer { /** * The name of the database structure (table or sequence). * @return The structure name. diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java index 822fd9289dda..caf4fe218a74 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java @@ -25,9 +25,8 @@ import java.lang.reflect.Constructor; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; - import org.jboss.logging.Logger; /** @@ -61,13 +60,15 @@ public static boolean isPooledOptimizer(String optimizerName) { * @param type The optimizer type, either a short-hand name or the {@link Optimizer} class name. * @param returnClass The generated value java type * @param incrementSize The increment size. + * @param classLoaderService ClassLoaderService * * @return The built optimizer * * @deprecated Use {@link #buildOptimizer(String, Class, int, long)} instead */ @Deprecated - public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize) { + public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, + ClassLoaderService classLoaderService) { final Class optimizerClass; final StandardOptimizerDescriptor standardDescriptor = StandardOptimizerDescriptor.fromExternalName( type ); @@ -76,7 +77,7 @@ public static Optimizer buildOptimizer(String type, Class returnClass, int incre } else { try { - optimizerClass = ReflectHelper.classForName( type ); + optimizerClass = classLoaderService.classForName( type ); } catch( Throwable ignore ) { LOG.unableToLocateCustomOptimizerClass( type ); @@ -106,11 +107,12 @@ private static Optimizer buildFallbackOptimizer(Class returnClass, int increment * @param returnClass The generated value java type * @param incrementSize The increment size. * @param explicitInitialValue The user supplied initial-value (-1 indicates the user did not specify). + * @param classLoaderService ClassLoaderService * * @return The built optimizer */ - public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue) { - final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize ); + public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue, ClassLoaderService classLoaderService) { + final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize, classLoaderService ); if ( InitialValueAwareOptimizer.class.isInstance( optimizer ) ) { ( (InitialValueAwareOptimizer) optimizer ).injectInitialValue( explicitInitialValue ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java index 6cb9bbd7617c..fc1eb2c5093c 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java @@ -29,7 +29,7 @@ import org.hibernate.HibernateException; import org.hibernate.id.IntegralDataTypeHolder; - +import org.hibernate.internal.CoreMessageLogger; import org.jboss.logging.Logger; /** @@ -41,13 +41,18 @@ * @see PooledOptimizer */ public class PooledLoOptimizer extends AbstractOptimizer { - private static final Logger log = Logger.getLogger( PooledLoOptimizer.class ); + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + PooledLoOptimizer.class.getName() + ); private static class GenerationState { // last value read from db source private IntegralDataTypeHolder lastSourceValue; // the current generator value private IntegralDataTypeHolder value; + // the value at which we'll hit the db again + private IntegralDataTypeHolder upperLimitValue; } /** @@ -61,9 +66,7 @@ public PooledLoOptimizer(Class returnClass, int incrementSize) { if ( incrementSize < 1 ) { throw new HibernateException( "increment size cannot be less than 1" ); } - if ( log.isTraceEnabled() ) { - log.tracev( "Creating pooled optimizer (lo) with [incrementSize={0}; returnClass=]", incrementSize, returnClass.getName() ); - } + LOG.creatingPooledLoOptimizer( incrementSize, returnClass.getName() ); } @Override @@ -71,8 +74,9 @@ public synchronized Serializable generate(AccessCallback callback) { final GenerationState generationState = locateGenerationState( callback.getTenantIdentifier() ); if ( generationState.lastSourceValue == null - || ! generationState.value.lt( generationState.lastSourceValue.copy().add( incrementSize ) ) ) { + || ! generationState.value.lt( generationState.upperLimitValue ) ) { generationState.lastSourceValue = callback.getNextValue(); + generationState.upperLimitValue = generationState.lastSourceValue.copy().add( incrementSize ); generationState.value = generationState.lastSourceValue.copy(); // handle cases where initial-value is less that one (hsqldb for instance). while ( generationState.value.lt( 1 ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java index c1737d18bb38..1c27a0dd175a 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as + * Copyright (c) 2008, 2012, 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -22,19 +22,22 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.id.enhanced; - import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import org.jboss.logging.Logger; + import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.internal.CoreMessageLogger; - -import org.jboss.logging.Logger; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; /** * Describes a sequence. @@ -47,6 +50,7 @@ public class SequenceStructure implements DatabaseStructure { SequenceStructure.class.getName() ); + private ObjectName qualifiedSequenceName; private final String sequenceName; private final int initialValue; private final int incrementSize; @@ -57,11 +61,12 @@ public class SequenceStructure implements DatabaseStructure { public SequenceStructure( Dialect dialect, - String sequenceName, + ObjectName qualifiedSequenceName, int initialValue, int incrementSize, Class numberType) { - this.sequenceName = sequenceName; + this.qualifiedSequenceName = qualifiedSequenceName; + this.sequenceName = qualifiedSequenceName.toText( dialect ); this.initialValue = initialValue; this.incrementSize = incrementSize; this.numberType = numberType; @@ -142,6 +147,19 @@ public void prepare(Optimizer optimizer) { applyIncrementSizeToSourceValues = optimizer.applyIncrementSizeToSourceValues(); } + @Override + public void registerExportables(Database database) { + final int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1; + final Schema schema = database.getSchemaFor( qualifiedSequenceName ); + Sequence sequence = schema.locateSequence( qualifiedSequenceName.getName() ); + if ( sequence != null ) { + sequence.validate( initialValue, sourceIncrementSize ); + } + else { + schema.createSequence( qualifiedSequenceName.getName(), initialValue, sourceIncrementSize ); + } + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { final int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1; diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java index bcd321196fbf..948c9a6bbb6a 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java @@ -26,8 +26,11 @@ import java.io.Serializable; import java.util.Properties; +import org.jboss.logging.Logger; + import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; @@ -37,11 +40,11 @@ import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.type.Type; -import org.jboss.logging.Logger; - /** * Generates identifier values based on an sequence-style database structure. * Variations range from actually using a sequence to using a table to mimic @@ -227,11 +230,12 @@ public Type getIdentifierType() { // Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { this.identifierType = type; boolean forceTableUse = ConfigurationHelper.getBoolean( FORCE_TBL_PARAM, params, false ); - final String sequenceName = determineSequenceName( params, dialect ); + final ObjectName qualifiedSequenceName = determineSequenceName( params, dialect ); + final String sequenceNameText = qualifiedSequenceName.toText( dialect ); final int initialValue = determineInitialValue( params ); int incrementSize = determineIncrementSize( params ); @@ -251,7 +255,7 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp params, dialect, forceTableUse, - sequenceName, + qualifiedSequenceName, initialValue, incrementSize ); @@ -259,7 +263,8 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp optimizationStrategy, identifierType.getReturnedClass(), incrementSize, - ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ) + ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ), + classLoaderService ); this.databaseStructure.prepare( optimizer ); } @@ -274,28 +279,25 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp * @param dialect The dialect in effect * @return The sequence name */ - protected String determineSequenceName(Properties params, Dialect dialect) { - final String sequencePerEntitySuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX ); + protected ObjectName determineSequenceName(Properties params, Dialect dialect) { + String sequencePerEntitySuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, params, DEF_SEQUENCE_SUFFIX ); // JPA_ENTITY_NAME value honors (HBM) and @Entity#name (JPA) overrides. String sequenceName = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEQUENCE_PER_ENTITY, params, false ) ? params.getProperty( JPA_ENTITY_NAME ) + sequencePerEntitySuffix : DEF_SEQUENCE_NAME; - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); - sequenceName = ConfigurationHelper.getString( SEQUENCE_PARAM, params, sequenceName ); + final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); + sequenceName = normalizer.normalizeIdentifierQuoting( + ConfigurationHelper.getString( SEQUENCE_PARAM, params, sequenceName ) + ); if ( sequenceName.indexOf( '.' ) < 0 ) { - sequenceName = normalizer.normalizeIdentifierQuoting( sequenceName ); - final String schemaName = params.getProperty( SCHEMA ); - final String catalogName = params.getProperty( CATALOG ); - sequenceName = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( sequenceName ) - ); - } - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. + final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); + final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - return sequenceName; + return new ObjectName( catalogName, schemaName, sequenceName ); + } + else { + return ObjectName.parse( sequenceName ); + } } /** @@ -309,10 +311,10 @@ protected String determineSequenceName(Properties params, Dialect dialect) { * @param dialect The dialect in effect. * @return The value column name */ - protected String determineValueColumnName(Properties params, Dialect dialect) { - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); + protected Identifier determineValueColumnName(Properties params, Dialect dialect) { + final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); - return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) ); + return Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) ); } /** @@ -401,7 +403,7 @@ protected DatabaseStructure buildDatabaseStructure( Properties params, Dialect dialect, boolean forceTableUse, - String sequenceName, + ObjectName sequenceName, int initialValue, int incrementSize) { final boolean useSequence = dialect.supportsSequences() && !forceTableUse; @@ -409,7 +411,7 @@ protected DatabaseStructure buildDatabaseStructure( return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize, type.getReturnedClass() ); } else { - final String valueColumnName = determineValueColumnName( params, dialect ); + Identifier valueColumnName = determineValueColumnName( params, dialect ); return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize, type.getReturnedClass() ); } } @@ -430,6 +432,11 @@ public Object generatorKey() { return databaseStructure.getName(); } + @Override + public void registerExportables(Database database) { + databaseStructure.registerExportables( database ); + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return databaseStructure.sqlCreateStrings( dialect ); diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java index 50fe25ac18e3..773a16f1c66e 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java @@ -37,6 +37,7 @@ import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.dialect.Dialect; @@ -53,7 +54,11 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -226,7 +231,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab private Type identifierType; + private ObjectName qualifiedTableName; + private Identifier qualifiedSegmentColumnName; + private Identifier qualifiedValueColumnName; + private String tableName; + private Table table; private String segmentColumnName; private String segmentValue; @@ -266,6 +276,15 @@ public final String getTableName() { return tableName; } + /** + * The bound Table for this generator. + * + * @return The table. + */ + public final Table getTable() { + return table; + } + /** * The name of the column in which we store the segment to which each row * belongs. The value here acts as PK. @@ -349,7 +368,7 @@ public final long getTableAccessCount() { } @Override - public void configure(Type type, Properties params, Dialect dialect) throws MappingException { + public void configure(Type type, Properties params, Dialect dialect, ClassLoaderService classLoaderService) throws MappingException { identifierType = type; tableName = determineGeneratorTableName( params, dialect ); @@ -379,14 +398,15 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp optimizationStrategy, identifierType.getReturnedClass(), incrementSize, - ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ) + ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 ), + classLoaderService ); } /** * Determine the table name to use for the generator values. *

    - * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getTableName() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -394,22 +414,23 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp * @return The table name to use. */ protected String determineGeneratorTableName(Properties params, Dialect dialect) { - String name = ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE ); + final ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER ); + String name = normalizer.normalizeIdentifierQuoting( + ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE ) + ); final boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0; if ( isGivenNameUnqualified ) { - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); - name = normalizer.normalizeIdentifierQuoting( name ); // if the given name is un-qualified we may neen to qualify it final String schemaName = normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) ); final String catalogName = normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ); - name = Table.qualify( - dialect.quote( catalogName ), - dialect.quote( schemaName ), - dialect.quote( name) - ); + + qualifiedTableName = new ObjectName( catalogName, schemaName, name ); + + name = qualifiedTableName.toText( dialect ); + } + else { + qualifiedTableName = ObjectName.parse( name ); } - // if already qualified there is not much we can do in a portable manner so we pass it - // through and assume the user has set up the name correctly. return name; } @@ -418,7 +439,7 @@ protected String determineGeneratorTableName(Properties params, Dialect dialect) * Determine the name of the column used to indicate the segment for each * row. This column acts as the primary key. *

    - * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getSegmentColumnName() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -428,13 +449,14 @@ protected String determineGeneratorTableName(Properties params, Dialect dialect) protected String determineSegmentColumnName(Properties params, Dialect dialect) { final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); final String name = ConfigurationHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN ); - return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) ); + qualifiedSegmentColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) ); + return qualifiedSegmentColumnName.getText( dialect ); } /** * Determine the name of the column in which we will store the generator persistent value. *

    - * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getValueColumnName() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -444,13 +466,14 @@ protected String determineSegmentColumnName(Properties params, Dialect dialect) protected String determineValueColumnName(Properties params, Dialect dialect) { final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER ); final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); - return dialect.quote( normalizer.normalizeIdentifierQuoting( name ) ); + qualifiedValueColumnName = Identifier.toIdentifier( normalizer.normalizeIdentifierQuoting( name ) ); + return qualifiedValueColumnName.getText( dialect ); } /** * Determine the segment value corresponding to this generator instance. *

    - * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getSegmentValue() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -472,16 +495,20 @@ protected String determineSegmentValue(Properties params) { * @return The default segment value to use. */ protected String determineDefaultSegmentValue(Properties params) { - final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEGMENT_PER_ENTITY, params, false ); + final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean( + CONFIG_PREFER_SEGMENT_PER_ENTITY, + params, + false + ); final String defaultToUse = preferSegmentPerEntity ? params.getProperty( TABLE ) : DEF_SEGMENT_VALUE; - LOG.usingDefaultIdGeneratorSegmentValue( tableName, segmentColumnName, defaultToUse ); + LOG.usingDefaultIdGeneratorSegmentValue( qualifiedTableName.toString(), segmentColumnName, defaultToUse ); return defaultToUse; } /** * Determine the size of the {@link #getSegmentColumnName segment column} *

    - * Called during {@link #configure configuration}. + * Called during {@link org.hibernate.id.Configurable#configure configuration}. * * @see #getSegmentValueLength() * @param params The params supplied in the generator config (plus some standard useful extras). @@ -502,7 +529,7 @@ protected int determineIncrementSize(Properties params) { protected String buildSelectQuery(Dialect dialect) { final String alias = "tbl"; final String query = "select " + StringHelper.qualify( alias, valueColumnName ) + - " from " + tableName + ' ' + alias + + " from " + qualifiedTableName.toText( dialect ) + ' ' + alias + " where " + StringHelper.qualify( alias, segmentColumnName ) + "=?"; final LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE ); lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE ); @@ -511,7 +538,7 @@ protected String buildSelectQuery(Dialect dialect) { } protected String buildUpdateQuery() { - return "update " + tableName + + return "update " + qualifiedTableName.toText( ) + " set " + valueColumnName + "=? " + " where " + valueColumnName + "=? and " + segmentColumnName + "=?"; } @@ -535,76 +562,98 @@ public Serializable generate(final SessionImplementor session, final Object obj) new AccessCallback() { @Override public IntegralDataTypeHolder getNextValue() { - return session.getTransactionCoordinator().getTransaction().createIsolationDelegate().delegateWork( - new AbstractReturningWork() { - @Override - public IntegralDataTypeHolder execute(Connection connection) throws SQLException { - final IntegralDataTypeHolder value = makeValue(); - int rows; - do { - final PreparedStatement selectPS = prepareStatement( connection, selectQuery, statementLogger, statsCollector ); - - try { - selectPS.setString( 1, segmentValue ); - final ResultSet selectRS = executeQuery( selectPS, statsCollector ); - if ( !selectRS.next() ) { - value.initialize( initialValue ); - - final PreparedStatement insertPS = prepareStatement( connection, insertQuery, statementLogger, statsCollector ); + return session.getTransactionCoordinator() + .getTransaction() + .createIsolationDelegate() + .delegateWork( + new AbstractReturningWork() { + @Override + public IntegralDataTypeHolder execute(Connection connection) + throws SQLException { + final IntegralDataTypeHolder value = makeValue(); + int rows; + do { + final PreparedStatement selectPS = prepareStatement( + connection, + selectQuery, + statementLogger, + statsCollector + ); + try { - insertPS.setString( 1, segmentValue ); - value.bind( insertPS, 2 ); - executeUpdate( insertPS, statsCollector ); + selectPS.setString( 1, segmentValue ); + final ResultSet selectRS = executeQuery( + selectPS, + statsCollector + ); + if ( !selectRS.next() ) { + value.initialize( initialValue ); + + final PreparedStatement insertPS = prepareStatement( + connection, + insertQuery, + statementLogger, + statsCollector + ); + try { + insertPS.setString( 1, segmentValue ); + value.bind( insertPS, 2 ); + executeUpdate( insertPS, statsCollector ); + } + finally { + insertPS.close(); + } + } + else { + value.initialize( selectRS, 1 ); + } + selectRS.close(); + } + catch ( SQLException e ) { + LOG.unableToReadOrInitHiValue( e ); + throw e; } finally { - insertPS.close(); + selectPS.close(); } - } - else { - value.initialize( selectRS, 1 ); - } - selectRS.close(); - } - catch (SQLException e) { - LOG.unableToReadOrInitHiValue( e ); - throw e; - } - finally { - selectPS.close(); - } - final PreparedStatement updatePS = prepareStatement( connection, updateQuery, statementLogger, statsCollector ); - try { - final IntegralDataTypeHolder updateValue = value.copy(); - if ( optimizer.applyIncrementSizeToSourceValues() ) { - updateValue.add( incrementSize ); - } - else { - updateValue.increment(); + final PreparedStatement updatePS = prepareStatement( + connection, + updateQuery, + statementLogger, + statsCollector + ); + try { + final IntegralDataTypeHolder updateValue = value.copy(); + if ( optimizer.applyIncrementSizeToSourceValues() ) { + updateValue.add( incrementSize ); + } + else { + updateValue.increment(); + } + updateValue.bind( updatePS, 1 ); + value.bind( updatePS, 2 ); + updatePS.setString( 3, segmentValue ); + rows = executeUpdate( updatePS, statsCollector ); + } + catch ( SQLException e ) { + LOG.unableToUpdateQueryHiValue( tableName, e ); + throw e; + } + finally { + updatePS.close(); + } } - updateValue.bind( updatePS, 1 ); - value.bind( updatePS, 2 ); - updatePS.setString( 3, segmentValue ); - rows = executeUpdate( updatePS, statsCollector ); - } - catch (SQLException e) { - LOG.unableToUpdateQueryHiValue( tableName, e ); - throw e; - } - finally { - updatePS.close(); - } - } - while ( rows == 0 ); + while ( rows == 0 ); - accessCount++; + accessCount++; - return value; - } - }, - true - ); + return value; + } + }, + true + ); } @Override @@ -651,6 +700,24 @@ private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager } } + @Override + public void registerExportables(Database database) { + final Dialect dialect = database.getJdbcEnvironment().getDialect(); + + table = database.getSchemaFor( qualifiedTableName ) + .createTable( qualifiedTableName.getName(), qualifiedTableName.getName() ); + + Column segmentColumn = table.createColumn( qualifiedSegmentColumnName ); + table.getPrimaryKey().addColumn( segmentColumn ); + // todo : leverage TypeInfo-like info from JdbcEnvironment + segmentColumn.setSqlType( dialect.getTypeName( Types.VARCHAR, segmentValueLength, 0, 0 ) ); + segmentColumn.setNullable( false ); + + Column valueColumn = table.createColumn( qualifiedValueColumnName ); + valueColumn.setSqlType( dialect.getTypeName( Types.BIGINT ) ); + valueColumn.setNullable( false ); + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return new String[] { diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java index 6f5c8f69cc49..9cc15e2b13ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java @@ -31,6 +31,7 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; +import org.hibernate.LockOptions; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.FormatStyle; import org.hibernate.engine.jdbc.spi.JdbcServices; @@ -42,7 +43,13 @@ import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.jdbc.AbstractReturningWork; - +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.InitCommand; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; import org.jboss.logging.Logger; /** @@ -56,8 +63,10 @@ public class TableStructure implements DatabaseStructure { TableStructure.class.getName() ); + private final ObjectName qualifiedTableName; + private final Identifier valueColumnName; + private final String tableName; - private final String valueColumnName; private final int initialValue; private final int incrementSize; private final Class numberType; @@ -69,24 +78,27 @@ public class TableStructure implements DatabaseStructure { public TableStructure( Dialect dialect, - String tableName, - String valueColumnName, + ObjectName qualifiedTableName, + Identifier valueColumnName, int initialValue, int incrementSize, Class numberType) { - this.tableName = tableName; + this.qualifiedTableName = qualifiedTableName; + this.valueColumnName = valueColumnName; + this.tableName = qualifiedTableName.toText( dialect ); this.initialValue = initialValue; this.incrementSize = incrementSize; - this.valueColumnName = valueColumnName; this.numberType = numberType; - selectQuery = "select " + valueColumnName + " as id_val" + - " from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) + + String valueColumnNameText = valueColumnName.getText( dialect ); + + selectQuery = "select " + valueColumnNameText + " as id_val" + + " from " + dialect.appendLockHint( new LockOptions( LockMode.PESSIMISTIC_WRITE ), tableName ) + dialect.getForUpdateString(); updateQuery = "update " + tableName + - " set " + valueColumnName + "= ?" + - " where " + valueColumnName + "=?"; + " set " + valueColumnNameText + "= ?" + + " where " + valueColumnNameText + "=?"; } @Override @@ -224,6 +236,25 @@ private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager } } + @Override + public void registerExportables(Database database) { + final Dialect dialect = database.getJdbcEnvironment().getDialect(); + final Schema schema = database.getSchemaFor( qualifiedTableName ); + Table table = schema.locateTable( qualifiedTableName.getName() ); + if ( table != null ) { + return; + } + + table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() ); + + Column valueColumn = table.createColumn( valueColumnName ); + valueColumn.setSqlType( dialect.getTypeName( Types.BIGINT ) ); + + database.addInitCommand( + new InitCommand( "insert into " + tableName + " values ( " + initialValue + " )" ) + ); + } + @Override public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return new String[] { diff --git a/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java b/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java index 0f4e4d98ff21..7368f24a375d 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java @@ -28,6 +28,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.id.Assigned; @@ -52,7 +54,6 @@ import org.hibernate.service.spi.ServiceRegistryAwareService; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.type.Type; - import org.jboss.logging.Logger; /** @@ -66,6 +67,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener DefaultIdentifierGeneratorFactory.class.getName()); private transient Dialect dialect; + private transient ClassLoaderService classLoaderService; private ConcurrentHashMap generatorStrategyToClassNameMap = new ConcurrentHashMap(); /** @@ -88,7 +90,7 @@ public DefaultIdentifierGeneratorFactory() { register( "enhanced-sequence", SequenceStyleGenerator.class ); register( "enhanced-table", TableGenerator.class ); } - + @Override public void register(String strategy, Class generatorClass) { LOG.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() ); final Class previous = generatorStrategyToClassNameMap.put( strategy, generatorClass ); @@ -114,7 +116,7 @@ public IdentifierGenerator createIdentifierGenerator(String strategy, Type type, Class clazz = getIdentifierGeneratorClass( strategy ); IdentifierGenerator identifierGenerator = ( IdentifierGenerator ) clazz.newInstance(); if ( identifierGenerator instanceof Configurable ) { - ( ( Configurable ) identifierGenerator ).configure( type, config, dialect ); + ( ( Configurable ) identifierGenerator ).configure( type, config, dialect, classLoaderService ); } return identifierGenerator; } @@ -133,9 +135,19 @@ public Class getIdentifierGeneratorClass(String strategy) { Class generatorClass = generatorStrategyToClassNameMap.get( strategy ); try { if ( generatorClass == null ) { - generatorClass = ReflectHelper.classForName( strategy ); + // TODO: Exists purely for testing using the old .mappings. Eventually remove. + if (classLoaderService == null) { + generatorClass = ReflectHelper.classForName( strategy ); + } + else { + generatorClass = classLoaderService.classForName( strategy ); + } + register( strategy, generatorClass ); } } + catch ( ClassLoadingException e ) { + throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) ); + } catch ( ClassNotFoundException e ) { throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) ); } @@ -145,5 +157,6 @@ public Class getIdentifierGeneratorClass(String strategy) { @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { this.dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java b/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java index 8b748c78f4ef..a8fd06e468ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java +++ b/hibernate-core/src/main/java/org/hibernate/integrator/spi/Integrator.java @@ -25,7 +25,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractQueryImpl.java index 8b76fc3b1b29..2b8b29bb2476 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractQueryImpl.java @@ -222,8 +222,8 @@ public Integer getMaxResults() { @Override public Query setMaxResults(int maxResults) { - if ( maxResults < 0 ) { - // treat negatives specically as meaning no limit... + if ( maxResults <= 0 ) { + // treat zero and negatives specically as meaning no limit... selection.setMaxRows( null ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CacheImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/CacheImpl.java index 986a84e0feae..e8d660db3154 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CacheImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CacheImpl.java @@ -260,6 +260,8 @@ public void evictQueryRegion(String regionName) { @Override public void evictQueryRegions() { + evictDefaultQueryRegion(); + if ( CollectionHelper.isEmpty( queryCaches ) ) { return; } @@ -268,7 +270,6 @@ public void evictQueryRegions() { } for ( QueryCache queryCache : queryCaches.values() ) { queryCache.clear(); - // TODO : cleanup entries in queryCaches + allCacheRegions ? } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java index 3d400ee2a2a0..aa4f3c3f294b 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java @@ -1411,7 +1411,7 @@ void usingDefaultIdGeneratorSegmentValue(String tableName, void usingDriver(String driverClassName, String url); - @LogMessage(level = INFO) + @LogMessage(level = WARN) @Message(value = "Using Hibernate built-in connection pool (not for production use!)", id = 402) void usingHibernateBuiltInConnectionPool(); @@ -1674,4 +1674,50 @@ void cannotResolveNonNullableTransientDependencies(String transientEntityString, "(%2$s=true)" ) void applyingExplicitDiscriminatorColumnForJoined(String className, String overrideSetting); + + @Message(value = "@CollectionTable and @JoinTable specified on the same attribute. Check %s#%s", id = 458) + String collectionTableAndJoinTableUsedTogether(String entityName, String propertyName); + + @Message(value = "@CollectionTable annotation without a @ElementCollection. Check %s#%s", id = 459) + String collectionTableWithoutElementCollection(String entityName, String propertyName); + + @Message(value = "@JoinTable annotation without an association. Check %s#%s", id = 460) + String joinTableForNonAssociationAttribute(String entityName, String propertyName); + + @LogMessage( level = ERROR ) + @Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 461 ) + void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName, + String attributeName, + String attributeJavaType, + String metamodelFieldJavaType ); + // moved from EntityManagerMessageLogger w/ id 15007 + + @LogMessage( level = ERROR ) + @Message( value = "Unable to locate static metamodel field : %s#%s", id = 462 ) + void unableToLocateStaticMetamodelField( String metamodelClassName, + String attributeName ); + // moved from EntityManagerMessageLogger w/ id 15011 + + + @Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + + "@Access has to be placed on the property (getter)", id = 463) + String accessTypeOverrideShouldBeAnnotatedOnProperty( String className ); + + @Message(value = "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + + "@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " + + "Using AccessType.FIELD on the property has no effect", id = 464) + String accessTypeOverrideShouldBeProperty( String className ); + + @Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + + "@Access has to be placed on the field ", id = 465) + String accessTypeOverrideShouldBeAnnotatedOnField( String className ); + + @Message(value = "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + + "@Access has to be placed on the field with an access type of AccessType.FIELD. " + + "Using AccessType.PROPERTY on the field has no effect", id = 466) + String accessTypeOverrideShouldBeField( String className ); + + @LogMessage(level = DEBUG) + @Message(value = "Creating pooled optimizer (lo) with [incrementSize=%s; returnClass=%s]", id = 467) + void creatingPooledLoOptimizer(int incrementSize, String name); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java b/hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java new file mode 100644 index 000000000000..a14fee4c88a5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/internal/DefaultCustomEntityDirtinessStrategy.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.internal; + +import org.hibernate.CustomEntityDirtinessStrategy; +import org.hibernate.Session; +import org.hibernate.persister.entity.EntityPersister; + +/** + * The default implementation of {@link CustomEntityDirtinessStrategy} which does nada. + * + * @author Steve Ebersole + */ +public class DefaultCustomEntityDirtinessStrategy implements CustomEntityDirtinessStrategy { + public static final DefaultCustomEntityDirtinessStrategy INSTANCE = new DefaultCustomEntityDirtinessStrategy(); + + @Override + public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) { + return false; + } + + @Override + public boolean isDirty(Object entity, EntityPersister persister, Session session) { + return false; + } + + @Override + public void resetDirty(Object entity, EntityPersister persister, Session session) { + } + + @Override + public void findDirty( + Object entity, + EntityPersister persister, + Session session, + DirtyCheckContext dirtyCheckContext) { + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java b/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java index 7ae640910fe7..f5e89b4e390d 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FilterConfiguration.java @@ -29,9 +29,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.persister.entity.Joinable; /** + * Captures all relevant metadata specified as part of defining the filter. * * @author Rob Worsnop */ @@ -42,14 +44,52 @@ public class FilterConfiguration { private final Map aliasTableMap; private final Map aliasEntityMap; private final PersistentClass persistentClass; - - public FilterConfiguration(String name, String condition, boolean autoAliasInjection, Map aliasTableMap, Map aliasEntityMap, PersistentClass persistentClass) { + private final EntityBinding entityBinding; + public FilterConfiguration( + String name, + String condition, + boolean autoAliasInjection, + Map aliasTableMap, + Map aliasEntityMap){ + this.name = name; + this.condition = condition; + this.autoAliasInjection = autoAliasInjection; + this.aliasTableMap = aliasTableMap; + this.aliasEntityMap = aliasEntityMap; + this.entityBinding = null; + this.persistentClass = null; + } + + public FilterConfiguration( + String name, + String condition, + boolean autoAliasInjection, + Map aliasTableMap, + Map aliasEntityMap, + PersistentClass persistentClass) { this.name = name; this.condition = condition; this.autoAliasInjection = autoAliasInjection; this.aliasTableMap = aliasTableMap; this.aliasEntityMap = aliasEntityMap; this.persistentClass = persistentClass; + this.entityBinding = null; + } + + public FilterConfiguration( + String name, + String condition, + boolean autoAliasInjection, + Map aliasTableMap, + Map aliasEntityMap, + EntityBinding entityBinding) { + this.name = name; + this.condition = condition; + this.autoAliasInjection = autoAliasInjection; + this.aliasTableMap = aliasTableMap; + this.aliasEntityMap = aliasEntityMap; + this.persistentClass = null; + this.entityBinding = entityBinding; } public String getName() { @@ -65,28 +105,38 @@ public boolean useAutoAliasInjection() { } public Map getAliasTableMap(SessionFactoryImplementor factory) { - Map mergedAliasTableMap = mergeAliasMaps(factory); - if (!mergedAliasTableMap.isEmpty()){ + Map mergedAliasTableMap = mergeAliasMaps( factory ); + if ( !mergedAliasTableMap.isEmpty() ) { return mergedAliasTableMap; - } else if (persistentClass != null){ - String table = persistentClass.getTable().getQualifiedName(factory.getDialect(), + } + else if ( persistentClass != null ) { + String table = persistentClass.getTable().getQualifiedName( + factory.getDialect(), factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName()); - return Collections.singletonMap(null, table); - } else{ + factory.getSettings().getDefaultSchemaName() + ); + return Collections.singletonMap( null, table ); + } + else if ( entityBinding != null ) { + String table = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); + return Collections.singletonMap( null, table ); + } + else { return Collections.emptyMap(); } } - - private Map mergeAliasMaps(SessionFactoryImplementor factory){ - Map ret = new HashMap(); - if (aliasTableMap != null){ - ret.putAll(aliasTableMap); + + private Map mergeAliasMaps(SessionFactoryImplementor factory) { + Map ret = new HashMap(); + if ( aliasTableMap != null ) { + ret.putAll( aliasTableMap ); } - if (aliasEntityMap != null){ - for (Map.Entry entry : aliasEntityMap.entrySet()){ - ret.put(entry.getKey(), - Joinable.class.cast(factory.getEntityPersister(entry.getValue())).getTableName()); + if ( aliasEntityMap != null ) { + for ( Map.Entry entry : aliasEntityMap.entrySet() ) { + ret.put( + entry.getKey(), + Joinable.class.cast( factory.getEntityPersister( entry.getValue() ) ).getTableName() + ); } } return ret; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SQLQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SQLQueryImpl.java index abe865ff2051..6f5bc091e4eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SQLQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SQLQueryImpl.java @@ -89,10 +89,10 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery { queryDef.getResultSetRef() ); } - this.queryReturns = Arrays.asList( definition.getQueryReturns() ); + this.queryReturns = new ArrayList(Arrays.asList( definition.getQueryReturns() )); } else if ( queryDef.getQueryReturns() != null && queryDef.getQueryReturns().length > 0 ) { - this.queryReturns = Arrays.asList( queryDef.getQueryReturns() ); + this.queryReturns = new ArrayList(Arrays.asList( queryDef.getQueryReturns())); } else { this.queryReturns = new ArrayList(); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index cc58b8be2088..2a6b582e5d29 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -31,6 +31,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -53,7 +54,6 @@ import org.hibernate.Interceptor; import org.hibernate.MappingException; import org.hibernate.MultiTenancyStrategy; -import org.hibernate.ObjectNotFoundException; import org.hibernate.Session; import org.hibernate.SessionBuilder; import org.hibernate.SessionEventListener; @@ -61,8 +61,8 @@ import org.hibernate.SessionFactoryObserver; import org.hibernate.StatelessSession; import org.hibernate.StatelessSessionBuilder; +import org.hibernate.TruthValue; import org.hibernate.TypeHelper; -import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.cache.internal.CacheDataDescriptionImpl; @@ -78,11 +78,8 @@ import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; import org.hibernate.cache.spi.access.RegionAccessStrategy; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Settings; -import org.hibernate.cfg.SettingsFactory; import org.hibernate.cfg.annotations.NamedProcedureCallDefinition; import org.hibernate.context.internal.JTASessionContext; import org.hibernate.context.internal.ManagedSessionContext; @@ -104,9 +101,11 @@ import org.hibernate.engine.profile.Fetch; import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.query.spi.QueryPlanCache; +import org.hibernate.engine.query.spi.ReturnMetadata; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.engine.spi.ActionQueue; import org.hibernate.engine.spi.CacheImplementor; import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.NamedQueryDefinition; import org.hibernate.engine.spi.NamedSQLQueryDefinition; import org.hibernate.engine.spi.SessionBuilderImplementor; @@ -122,22 +121,22 @@ import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.IntegratorService; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.RootClass; +import org.hibernate.internal.util.StringHelper; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.NamedStoredProcedureQueryDefinition; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.spi.PersisterFactory; import org.hibernate.procedure.ProcedureCallMemento; +import org.hibernate.procedure.internal.ProcedureCallMementoImpl; +import org.hibernate.procedure.internal.Util; import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; @@ -145,8 +144,6 @@ import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractor; import org.hibernate.tool.hbm2ddl.SchemaExport; -import org.hibernate.tool.hbm2ddl.SchemaUpdate; -import org.hibernate.tool.hbm2ddl.SchemaValidator; import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.type.AssociationType; import org.hibernate.type.Type; @@ -214,389 +211,442 @@ public final class SessionFactoryImpl private final transient TypeHelper typeHelper; private final transient TransactionEnvironment transactionEnvironment; private final transient SessionFactoryOptions sessionFactoryOptions; - private final transient CustomEntityDirtinessStrategy customEntityDirtinessStrategy; - private final transient CurrentTenantIdentifierResolver currentTenantIdentifierResolver; - @SuppressWarnings( {"unchecked", "ThrowableResultOfMethodCallIgnored"}) - public SessionFactoryImpl( - final Configuration cfg, - Mapping mapping, - final ServiceRegistry serviceRegistry, - Settings settings, - SessionFactoryObserver observer) throws HibernateException { - LOG.debug( "Building session factory" ); - - sessionFactoryOptions = new SessionFactoryOptions() { - private EntityNotFoundDelegate entityNotFoundDelegate; - - @Override - public StandardServiceRegistry getServiceRegistry() { - return (StandardServiceRegistry) serviceRegistry; - } - - @Override - public Interceptor getInterceptor() { - return cfg.getInterceptor(); - } - - @Override - public EntityNotFoundDelegate getEntityNotFoundDelegate() { - if ( entityNotFoundDelegate == null ) { - if ( cfg.getEntityNotFoundDelegate() != null ) { - entityNotFoundDelegate = cfg.getEntityNotFoundDelegate(); - } - else { - entityNotFoundDelegate = new EntityNotFoundDelegate() { - public void handleEntityNotFound(String entityName, Serializable id) { - throw new ObjectNotFoundException( id, entityName ); - } - }; - } - } - return entityNotFoundDelegate; - } - }; - - this.settings = settings; - - this.properties = new Properties(); - this.properties.putAll( cfg.getProperties() ); - - this.serviceRegistry = serviceRegistry.getService( SessionFactoryServiceRegistryFactory.class ).buildServiceRegistry( - this, - cfg - ); - this.jdbcServices = this.serviceRegistry.getService( JdbcServices.class ); - this.dialect = this.jdbcServices.getDialect(); - this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class ); - this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() ); - if ( observer != null ) { - this.observer.addObserver( observer ); - } - - this.typeResolver = cfg.getTypeResolver().scope( this ); - this.typeHelper = new TypeLocatorImpl( typeResolver ); - - this.filters = new HashMap(); - this.filters.putAll( cfg.getFilterDefinitions() ); - - LOG.debugf( "Session factory constructed with filter configurations : %s", filters ); - LOG.debugf( "Instantiating session factory with properties: %s", properties ); - - - this.queryPlanCache = new QueryPlanCache( this ); - - // todo : everything above here consider implementing as standard SF service. specifically: stats, caches, types, function-reg - - class IntegratorObserver implements SessionFactoryObserver { - private ArrayList integrators = new ArrayList(); - - @Override - public void sessionFactoryCreated(SessionFactory factory) { - } - - @Override - public void sessionFactoryClosed(SessionFactory factory) { - for ( Integrator integrator : integrators ) { - integrator.disintegrate( SessionFactoryImpl.this, SessionFactoryImpl.this.serviceRegistry ); - } - integrators.clear(); - } - } - - final IntegratorObserver integratorObserver = new IntegratorObserver(); - this.observer.addObserver( integratorObserver ); - for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) { - integrator.integrate( cfg, this, this.serviceRegistry ); - integratorObserver.integrators.add( integrator ); - } - - //Generators: - - identifierGenerators = new HashMap(); - Iterator classes = cfg.getClassMappings(); - while ( classes.hasNext() ) { - PersistentClass model = (PersistentClass) classes.next(); - if ( !model.isInherited() ) { - IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator( - cfg.getIdentifierGeneratorFactory(), - getDialect(), - settings.getDefaultCatalogName(), - settings.getDefaultSchemaName(), - (RootClass) model - ); - identifierGenerators.put( model.getEntityName(), generator ); - } - } - - imports = new HashMap( cfg.getImports() ); - - /////////////////////////////////////////////////////////////////////// - // Prepare persisters and link them up with their cache - // region/access-strategy - - final RegionFactory regionFactory = cacheAccess.getRegionFactory(); - final String cacheRegionPrefix = settings.getCacheRegionPrefix() == null ? "" : settings.getCacheRegionPrefix() + "."; - final PersisterFactory persisterFactory = serviceRegistry.getService( PersisterFactory.class ); - - // todo : consider removing this silliness and just have EntityPersister directly implement ClassMetadata - // EntityPersister.getClassMetadata() for the internal impls simply "return this"; - // collapsing those would allow us to remove this "extra" Map - // - // todo : similar for CollectionPersister/CollectionMetadata - - entityPersisters = new HashMap(); - Map entityAccessStrategies = new HashMap(); - Map classMeta = new HashMap(); - classes = cfg.getClassMappings(); - while ( classes.hasNext() ) { - final PersistentClass model = (PersistentClass) classes.next(); - model.prepareTemporaryTables( mapping, getDialect() ); - final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName(); - // cache region is defined by the root-class in the hierarchy... - EntityRegionAccessStrategy accessStrategy = ( EntityRegionAccessStrategy ) entityAccessStrategies.get( cacheRegionName ); - if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) { - final AccessType accessType = AccessType.fromExternalName( model.getCacheConcurrencyStrategy() ); - if ( accessType != null ) { - LOG.tracef( "Building shared cache region for entity data [%s]", model.getEntityName() ); - EntityRegion entityRegion = regionFactory.buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) ); - accessStrategy = entityRegion.buildAccessStrategy( accessType ); - entityAccessStrategies.put( cacheRegionName, accessStrategy ); - cacheAccess.addCacheRegion( cacheRegionName, entityRegion ); - } - } - - NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null; - if ( model.hasNaturalId() && model.getNaturalIdCacheRegionName() != null ) { - final String naturalIdCacheRegionName = cacheRegionPrefix + model.getNaturalIdCacheRegionName(); - naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName ); - - if ( naturalIdAccessStrategy == null && settings.isSecondLevelCacheEnabled() ) { - final CacheDataDescriptionImpl cacheDataDescription = CacheDataDescriptionImpl.decode( model ); - - NaturalIdRegion naturalIdRegion = null; - try { - naturalIdRegion = regionFactory.buildNaturalIdRegion( naturalIdCacheRegionName, properties, - cacheDataDescription ); - } - catch ( UnsupportedOperationException e ) { - LOG.warnf( - "Shared cache region factory [%s] does not support natural id caching; " + - "shared NaturalId caching will be disabled for not be enabled for %s", - regionFactory.getClass().getName(), - model.getEntityName() - ); - } - - if (naturalIdRegion != null) { - naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() ); - entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy ); - cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion ); - } - } - } - - EntityPersister cp = persisterFactory.createEntityPersister( - model, - accessStrategy, - naturalIdAccessStrategy, - this, - mapping - ); - entityPersisters.put( model.getEntityName(), cp ); - classMeta.put( model.getEntityName(), cp.getClassMetadata() ); - } - this.classMetadata = Collections.unmodifiableMap(classMeta); - - Map> tmpEntityToCollectionRoleMap = new HashMap>(); - collectionPersisters = new HashMap(); - Map tmpCollectionMetadata = new HashMap(); - Iterator collections = cfg.getCollectionMappings(); - while ( collections.hasNext() ) { - Collection model = (Collection) collections.next(); - final String cacheRegionName = cacheRegionPrefix + model.getCacheRegionName(); - final AccessType accessType = AccessType.fromExternalName( model.getCacheConcurrencyStrategy() ); - CollectionRegionAccessStrategy accessStrategy = null; - if ( accessType != null && settings.isSecondLevelCacheEnabled() ) { - LOG.tracev( "Building shared cache region for collection data [{0}]", model.getRole() ); - CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl - .decode( model ) ); - accessStrategy = collectionRegion.buildAccessStrategy( accessType ); - entityAccessStrategies.put( cacheRegionName, accessStrategy ); - cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); - } - CollectionPersister persister = persisterFactory.createCollectionPersister( - cfg, - model, - accessStrategy, - this - ) ; - collectionPersisters.put( model.getRole(), persister ); - tmpCollectionMetadata.put( model.getRole(), persister.getCollectionMetadata() ); - Type indexType = persister.getIndexType(); - if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) { - String entityName = ( ( AssociationType ) indexType ).getAssociatedEntityName( this ); - Set roles = tmpEntityToCollectionRoleMap.get( entityName ); - if ( roles == null ) { - roles = new HashSet(); - tmpEntityToCollectionRoleMap.put( entityName, roles ); - } - roles.add( persister.getRole() ); - } - Type elementType = persister.getElementType(); - if ( elementType.isAssociationType() && !elementType.isAnyType() ) { - String entityName = ( ( AssociationType ) elementType ).getAssociatedEntityName( this ); - Set roles = tmpEntityToCollectionRoleMap.get( entityName ); - if ( roles == null ) { - roles = new HashSet(); - tmpEntityToCollectionRoleMap.put( entityName, roles ); - } - roles.add( persister.getRole() ); - } - } - collectionMetadata = Collections.unmodifiableMap( tmpCollectionMetadata ); - Iterator itr = tmpEntityToCollectionRoleMap.entrySet().iterator(); - while ( itr.hasNext() ) { - final Map.Entry entry = ( Map.Entry ) itr.next(); - entry.setValue( Collections.unmodifiableSet( ( Set ) entry.getValue() ) ); - } - collectionRolesByEntityParticipant = Collections.unmodifiableMap( tmpEntityToCollectionRoleMap ); - - //Named Queries: - this.namedQueryRepository = new NamedQueryRepository( - cfg.getNamedQueries().values(), - cfg.getNamedSQLQueries().values(), - cfg.getSqlResultSetMappings().values(), - toProcedureCallMementos( cfg.getNamedProcedureCallMap(), cfg.getSqlResultSetMappings() ) - ); - - // after *all* persisters and named queries are registered - for ( EntityPersister persister : entityPersisters.values() ) { - persister.generateEntityDefinition(); - } - - for ( EntityPersister persister : entityPersisters.values() ) { - persister.postInstantiate(); - registerEntityNameResolvers( persister ); - } - for ( CollectionPersister persister : collectionPersisters.values() ) { - persister.postInstantiate(); - } - - //JNDI + Serialization: - - name = settings.getSessionFactoryName(); - try { - uuid = (String) UUID_GENERATOR.generate(null, null); - } - catch (Exception e) { - throw new AssertionFailure("Could not generate UUID"); - } - SessionFactoryRegistry.INSTANCE.addSessionFactory( - uuid, - name, - settings.isSessionFactoryNameAlsoJndiName(), - this, - serviceRegistry.getService( JndiService.class ) - ); - - LOG.debug( "Instantiated session factory" ); - - settings.getMultiTableBulkIdStrategy().prepare( - jdbcServices, - buildLocalConnectionAccess(), - cfg.createMappings(), - cfg.buildMapping(), - properties - ); - - - if ( settings.isAutoCreateSchema() ) { - new SchemaExport( serviceRegistry, cfg ) - .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ) - .create( false, true ); - } - if ( settings.isAutoUpdateSchema() ) { - new SchemaUpdate( serviceRegistry, cfg ).execute( false, true ); - } - if ( settings.isAutoValidateSchema() ) { - new SchemaValidator( serviceRegistry, cfg ).validate(); - } - if ( settings.isAutoDropSchema() ) { - schemaExport = new SchemaExport( serviceRegistry, cfg ) - .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ); - } - - currentSessionContext = buildCurrentSessionContext(); - - //checking for named queries - if ( settings.isNamedQueryStartupCheckingEnabled() ) { - final Map errors = checkNamedQueries(); - if ( ! errors.isEmpty() ) { - StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " ); - String sep = ""; - for ( Map.Entry entry : errors.entrySet() ) { - LOG.namedQueryError( entry.getKey(), entry.getValue() ); - failingQueries.append( sep ).append( entry.getKey() ); - sep = ", "; - } - throw new HibernateException( failingQueries.toString() ); - } - } - - // this needs to happen after persisters are all ready to go... - this.fetchProfiles = new HashMap(); - itr = cfg.iterateFetchProfiles(); - while ( itr.hasNext() ) { - final org.hibernate.mapping.FetchProfile mappingProfile = - ( org.hibernate.mapping.FetchProfile ) itr.next(); - final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() ); - for ( org.hibernate.mapping.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { - // resolve the persister owning the fetch - final String entityName = getImportedClassName( mappingFetch.getEntity() ); - final EntityPersister owner = entityName == null - ? null - : entityPersisters.get( entityName ); - if ( owner == null ) { - throw new HibernateException( - "Unable to resolve entity reference [" + mappingFetch.getEntity() - + "] in fetch profile [" + fetchProfile.getName() + "]" - ); - } - - // validate the specified association fetch - Type associationType = owner.getPropertyType( mappingFetch.getAssociation() ); - if ( associationType == null || !associationType.isAssociationType() ) { - throw new HibernateException( "Fetch profile [" + fetchProfile.getName() + "] specified an invalid association" ); - } - - // resolve the style - final Fetch.Style fetchStyle = Fetch.Style.parse( mappingFetch.getStyle() ); - - // then construct the fetch instance... - fetchProfile.addFetch( new Association( owner, mappingFetch.getAssociation() ), fetchStyle ); - ((Loadable) owner).registerAffectingFetchProfile( fetchProfile.getName() ); - } - fetchProfiles.put( fetchProfile.getName(), fetchProfile ); - } - - this.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy(); - this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( cfg.getCurrentTenantIdentifierResolver() ); - this.transactionEnvironment = new TransactionEnvironmentImpl( this ); - this.observer.sessionFactoryCreated( this ); - } - - private Map toProcedureCallMementos( - Map definitions, - Map resultSetMappingMap) { - final Map rtn = new HashMap(); - if ( definitions != null ) { - for (String name : definitions.keySet()){ - rtn.put( name, definitions.get( name ).toMemento( this, resultSetMappingMap )); - } - } - return rtn; - } +// @SuppressWarnings( {"unchecked", "ThrowableResultOfMethodCallIgnored"}) +// public SessionFactoryImpl( +// final Configuration cfg, +// Mapping mapping, +// final ServiceRegistry serviceRegistry, +// final Settings settings, +// final SessionFactoryObserver userObserver) throws HibernateException { +// LOG.debug( "Building session factory" ); +// +// sessionFactoryOptions = new SessionFactoryOptions() { +// private final Interceptor interceptor; +// private final CustomEntityDirtinessStrategy customEntityDirtinessStrategy; +// private final CurrentTenantIdentifierResolver currentTenantIdentifierResolver; +// private final EntityNotFoundDelegate entityNotFoundDelegate; +// +// { +// interceptor = cfg.getInterceptor(); +// +// customEntityDirtinessStrategy = serviceRegistry.getService( StrategySelector.class ).resolveDefaultableStrategy( +// CustomEntityDirtinessStrategy.class, +// cfg.getProperties().get( AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY ), +// DefaultCustomEntityDirtinessStrategy.INSTANCE +// ); +// +// if ( cfg.getCurrentTenantIdentifierResolver() != null ) { +// currentTenantIdentifierResolver = cfg.getCurrentTenantIdentifierResolver(); +// } +// else { +// currentTenantIdentifierResolver =serviceRegistry.getService( StrategySelector.class ).resolveStrategy( +// CurrentTenantIdentifierResolver.class, +// cfg.getProperties().get( AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER ) +// ); +// } +// +// if ( cfg.getEntityNotFoundDelegate() != null ) { +// entityNotFoundDelegate = cfg.getEntityNotFoundDelegate(); +// } +// else { +// entityNotFoundDelegate = new EntityNotFoundDelegate() { +// public void handleEntityNotFound(String entityName, Serializable id) { +// throw new ObjectNotFoundException( id, entityName ); +// } +// }; +// } +// } +// +// @Override +// public StandardServiceRegistry getServiceRegistry() { +// return (StandardServiceRegistry) serviceRegistry; +// } +// +// @Override +// public Interceptor getInterceptor() { +// return interceptor; +// } +// +// @Override +// public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { +// return customEntityDirtinessStrategy; +// } +// +// @Override +// public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { +// return currentTenantIdentifierResolver; +// } +// +// @Override +// public SessionFactoryObserver[] getSessionFactoryObservers() { +// return userObserver == null +// ? new SessionFactoryObserver[0] +// : new SessionFactoryObserver[] { userObserver }; +// } +// +// @Override +// public EntityNameResolver[] getEntityNameResolvers() { +// return new EntityNameResolver[0]; +// } +// +// @Override +// public Settings getSettings() { +// return settings; +// } +// +// @Override +// public EntityNotFoundDelegate getEntityNotFoundDelegate() { +// if ( entityNotFoundDelegate == null ) { +// } +// return entityNotFoundDelegate; +// } +// }; +// +// this.settings = settings; +// +// this.properties = new Properties(); +// this.properties.putAll( cfg.getProperties() ); +// +// this.serviceRegistry = serviceRegistry.getService( SessionFactoryServiceRegistryFactory.class ).buildServiceRegistry( +// this, +// cfg +// ); +// this.jdbcServices = this.serviceRegistry.getService( JdbcServices.class ); +// this.dialect = this.jdbcServices.getDialect(); +// this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class ); +// this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() ); +// for ( SessionFactoryObserver observer : sessionFactoryOptions.getSessionFactoryObservers() ) { +// this.observer.addObserver( observer ); +// } +// +// this.typeResolver = cfg.getTypeResolver().scope( this ); +// this.typeHelper = new TypeLocatorImpl( typeResolver ); +// +// this.filters = new HashMap(); +// this.filters.putAll( cfg.getFilterDefinitions() ); +// +// LOG.debugf( "Session factory constructed with filter configurations : %s", filters ); +// LOG.debugf( "Instantiating session factory with properties: %s", properties ); +// +// +// this.queryPlanCache = new QueryPlanCache( this ); +// +// // todo : everything above here consider implementing as standard SF service. specifically: stats, caches, types, function-reg +// +// class IntegratorObserver implements SessionFactoryObserver { +// private ArrayList integrators = new ArrayList(); +// +// @Override +// public void sessionFactoryCreated(SessionFactory factory) { +// } +// +// @Override +// public void sessionFactoryClosed(SessionFactory factory) { +// for ( Integrator integrator : integrators ) { +// integrator.disintegrate( SessionFactoryImpl.this, SessionFactoryImpl.this.serviceRegistry ); +// } +// integrators.clear(); +// } +// } +// +// final IntegratorObserver integratorObserver = new IntegratorObserver(); +// this.observer.addObserver( integratorObserver ); +// for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) { +// integrator.integrate( cfg, this, this.serviceRegistry ); +// integratorObserver.integrators.add( integrator ); +// } +// +// //Generators: +// +// identifierGenerators = new HashMap(); +// Iterator classes = cfg.getClassMappings(); +// while ( classes.hasNext() ) { +// PersistentClass model = (PersistentClass) classes.next(); +// if ( !model.isInherited() ) { +// IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator( +// cfg.getIdentifierGeneratorFactory(), +// getDialect(), +// settings.getDefaultCatalogName(), +// settings.getDefaultSchemaName(), +// (RootClass) model +// ); +// identifierGenerators.put( model.getEntityName(), generator ); +// } +// } +// +// imports = new HashMap( cfg.getImports() ); +// +// /////////////////////////////////////////////////////////////////////// +// // Prepare persisters and link them up with their cache +// // region/access-strategy +// +// final RegionFactory regionFactory = cacheAccess.getRegionFactory(); +// final String cacheRegionPrefix = settings.getCacheRegionPrefix() == null ? "" : settings.getCacheRegionPrefix() + "."; +// final PersisterFactory persisterFactory = serviceRegistry.getService( PersisterFactory.class ); +// +// // todo : consider removing this silliness and just have EntityPersister directly implement ClassMetadata +// // EntityPersister.getClassMetadata() for the internal impls simply "return this"; +// // collapsing those would allow us to remove this "extra" Map +// // +// // todo : similar for CollectionPersister/CollectionMetadata +// +// entityPersisters = new HashMap(); +// Map entityAccessStrategies = new HashMap(); +// Map classMeta = new HashMap(); +// classes = cfg.getClassMappings(); +// while ( classes.hasNext() ) { +// final PersistentClass model = (PersistentClass) classes.next(); +// model.prepareTemporaryTables( mapping, getDialect() ); +// final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName(); +// // cache region is defined by the root-class in the hierarchy... +// EntityRegionAccessStrategy accessStrategy = ( EntityRegionAccessStrategy ) entityAccessStrategies.get( cacheRegionName ); +// if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) { +// final AccessType accessType = AccessType.fromExternalName( model.getCacheConcurrencyStrategy() ); +// if ( accessType != null ) { +// LOG.tracef( "Building shared cache region for entity data [%s]", model.getEntityName() ); +// EntityRegion entityRegion = regionFactory.buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) ); +// accessStrategy = entityRegion.buildAccessStrategy( accessType ); +// entityAccessStrategies.put( cacheRegionName, accessStrategy ); +// cacheAccess.addCacheRegion( cacheRegionName, entityRegion ); +// } +// } +// +// NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null; +// if ( model.hasNaturalId() && model.getNaturalIdCacheRegionName() != null ) { +// final String naturalIdCacheRegionName = cacheRegionPrefix + model.getNaturalIdCacheRegionName(); +// naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName ); +// +// if ( naturalIdAccessStrategy == null && settings.isSecondLevelCacheEnabled() ) { +// final CacheDataDescriptionImpl cacheDataDescription = CacheDataDescriptionImpl.decode( model ); +// +// NaturalIdRegion naturalIdRegion = null; +// try { +// naturalIdRegion = regionFactory.buildNaturalIdRegion( naturalIdCacheRegionName, properties, +// cacheDataDescription ); +// } +// catch ( UnsupportedOperationException e ) { +// LOG.warnf( +// "Shared cache region factory [%s] does not support natural id caching; " + +// "shared NaturalId caching will be disabled for not be enabled for %s", +// regionFactory.getClass().getName(), +// model.getEntityName() +// ); +// } +// +// if (naturalIdRegion != null) { +// naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() ); +// entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy ); +// cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion ); +// } +// } +// } +// +// EntityPersister cp = persisterFactory.createEntityPersister( +// model, +// accessStrategy, +// naturalIdAccessStrategy, +// this, +// mapping +// ); +// entityPersisters.put( model.getEntityName(), cp ); +// classMeta.put( model.getEntityName(), cp.getClassMetadata() ); +// } +// this.classMetadata = Collections.unmodifiableMap(classMeta); +// +// Map> tmpEntityToCollectionRoleMap = new HashMap>(); +// collectionPersisters = new HashMap(); +// Map tmpCollectionMetadata = new HashMap(); +// Iterator collections = cfg.getCollectionMappings(); +// while ( collections.hasNext() ) { +// Collection model = (Collection) collections.next(); +// final String cacheRegionName = cacheRegionPrefix + model.getCacheRegionName(); +// final AccessType accessType = AccessType.fromExternalName( model.getCacheConcurrencyStrategy() ); +// CollectionRegionAccessStrategy accessStrategy = null; +// if ( accessType != null && settings.isSecondLevelCacheEnabled() ) { +// LOG.tracev( "Building shared cache region for collection data [{0}]", model.getRole() ); +// CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl +// .decode( model ) ); +// accessStrategy = collectionRegion.buildAccessStrategy( accessType ); +// entityAccessStrategies.put( cacheRegionName, accessStrategy ); +// cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); +// } +// CollectionPersister persister = persisterFactory.createCollectionPersister( +// cfg, +// model, +// accessStrategy, +// this +// ) ; +// collectionPersisters.put( model.getRole(), persister ); +// tmpCollectionMetadata.put( model.getRole(), persister.getCollectionMetadata() ); +// Type indexType = persister.getIndexType(); +// if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) { +// String entityName = ( ( AssociationType ) indexType ).getAssociatedEntityName( this ); +// Set roles = tmpEntityToCollectionRoleMap.get( entityName ); +// if ( roles == null ) { +// roles = new HashSet(); +// tmpEntityToCollectionRoleMap.put( entityName, roles ); +// } +// roles.add( persister.getRole() ); +// } +// Type elementType = persister.getElementType(); +// if ( elementType.isAssociationType() && !elementType.isAnyType() ) { +// String entityName = ( ( AssociationType ) elementType ).getAssociatedEntityName( this ); +// Set roles = tmpEntityToCollectionRoleMap.get( entityName ); +// if ( roles == null ) { +// roles = new HashSet(); +// tmpEntityToCollectionRoleMap.put( entityName, roles ); +// } +// roles.add( persister.getRole() ); +// } +// } +// collectionMetadata = Collections.unmodifiableMap( tmpCollectionMetadata ); +// Iterator itr = tmpEntityToCollectionRoleMap.entrySet().iterator(); +// while ( itr.hasNext() ) { +// final Map.Entry entry = ( Map.Entry ) itr.next(); +// entry.setValue( Collections.unmodifiableSet( ( Set ) entry.getValue() ) ); +// } +// collectionRolesByEntityParticipant = Collections.unmodifiableMap( tmpEntityToCollectionRoleMap ); +// +// //Named Queries: +// this.namedQueryRepository = new NamedQueryRepository( +// cfg.getNamedQueries().values(), +// cfg.getNamedSQLQueries().values(), +// cfg.getSqlResultSetMappings().values(), +// toProcedureCallMementos( cfg.getNamedProcedureCallMap(), cfg.getSqlResultSetMappings() ) +// ); +// +// // after *all* persisters and named queries are registered +// for ( EntityPersister persister : entityPersisters.values() ) { +// persister.generateEntityDefinition(); +// } +// +// for ( EntityPersister persister : entityPersisters.values() ) { +// persister.postInstantiate(); +// registerEntityNameResolvers( persister ); +// } +// if ( sessionFactoryOptions.getEntityNameResolvers() != null ) { +// for ( EntityNameResolver resolver : sessionFactoryOptions.getEntityNameResolvers() ) { +// registerEntityNameResolver( resolver ); +// } +// } +// +// for ( CollectionPersister persister : collectionPersisters.values() ) { +// persister.postInstantiate(); +// } +// +// //JNDI + Serialization: +// +// name = settings.getSessionFactoryName(); +// try { +// uuid = (String) UUID_GENERATOR.generate(null, null); +// } +// catch (Exception e) { +// throw new AssertionFailure("Could not generate UUID"); +// } +// SessionFactoryRegistry.INSTANCE.addSessionFactory( +// uuid, +// name, +// settings.isSessionFactoryNameAlsoJndiName(), +// this, +// serviceRegistry.getService( JndiService.class ) +// ); +// +// LOG.debug( "Instantiated session factory" ); +// +// settings.getMultiTableBulkIdStrategy().prepare( +// jdbcServices, +// buildLocalConnectionAccess(), +// cfg.createMappings(), +// cfg.buildMapping(), +// properties +// ); +// +// +// if ( settings.isAutoCreateSchema() ) { +// new SchemaExport( serviceRegistry, cfg ) +// .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ) +// .create( false, true ); +// } +// if ( settings.isAutoUpdateSchema() ) { +// new SchemaUpdate( serviceRegistry, cfg ).execute( false, true ); +// } +// if ( settings.isAutoValidateSchema() ) { +// new SchemaValidator( serviceRegistry, cfg ).validate(); +// } +// if ( settings.isAutoDropSchema() ) { +// schemaExport = new SchemaExport( serviceRegistry, cfg ) +// .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ); +// } +// +// currentSessionContext = buildCurrentSessionContext(); +// +// //checking for named queries +// if ( settings.isNamedQueryStartupCheckingEnabled() ) { +// final Map errors = checkNamedQueries(); +// if ( ! errors.isEmpty() ) { +// StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " ); +// String sep = ""; +// for ( Map.Entry entry : errors.entrySet() ) { +// LOG.namedQueryError( entry.getKey(), entry.getValue() ); +// failingQueries.append( sep ).append( entry.getKey() ); +// sep = ", "; +// } +// throw new HibernateException( failingQueries.toString() ); +// } +// } +// +// // this needs to happen after persisters are all ready to go... +// this.fetchProfiles = new HashMap(); +// itr = cfg.iterateFetchProfiles(); +// while ( itr.hasNext() ) { +// final org.hibernate.mapping.FetchProfile mappingProfile = +// ( org.hibernate.mapping.FetchProfile ) itr.next(); +// final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() ); +// for ( org.hibernate.mapping.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { +// // resolve the persister owning the fetch +// final String entityName = getImportedClassName( mappingFetch.getEntity() ); +// final EntityPersister owner = entityName == null +// ? null +// : entityPersisters.get( entityName ); +// if ( owner == null ) { +// throw new HibernateException( +// "Unable to resolve entity reference [" + mappingFetch.getEntity() +// + "] in fetch profile [" + fetchProfile.getName() + "]" +// ); +// } +// +// // validate the specified association fetch +// Type associationType = owner.getPropertyType( mappingFetch.getAssociation() ); +// if ( associationType == null || !associationType.isAssociationType() ) { +// throw new HibernateException( "Fetch profile [" + fetchProfile.getName() + "] specified an invalid association" ); +// } +// +// // resolve the style +// final Fetch.Style fetchStyle = Fetch.Style.parse( mappingFetch.getStyle() ); +// +// // then construct the fetch instance... +// fetchProfile.addFetch( new Association( owner, mappingFetch.getAssociation() ), fetchStyle ); +// ((Loadable) owner).registerAffectingFetchProfile( fetchProfile.getName() ); +// } +// fetchProfiles.put( fetchProfile.getName(), fetchProfile ); +// } +// +// this.transactionEnvironment = new TransactionEnvironmentImpl( this ); +// this.observer.sessionFactoryCreated( this ); +// +// final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg ); +// if ( jpaMetaModelPopulationSetting != JpaMetaModelPopulationSetting.DISABLED ) { +// this.jpaMetamodel = org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl.buildMetamodel( +// cfg.getClassMappings(), +// this, +// jpaMetaModelPopulationSetting == JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED +// ); +// } +// else { +// jpaMetamodel = null; +// } +// } private JdbcConnectionAccess buildLocalConnectionAccess() { return new JdbcConnectionAccess() { @@ -624,59 +674,10 @@ public boolean supportsAggressiveRelease() { }; } - @SuppressWarnings({ "unchecked" }) - private CustomEntityDirtinessStrategy determineCustomEntityDirtinessStrategy() { - CustomEntityDirtinessStrategy defaultValue = new CustomEntityDirtinessStrategy() { - @Override - public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) { - return false; - } - - @Override - public boolean isDirty(Object entity, EntityPersister persister, Session session) { - return false; - } - - @Override - public void resetDirty(Object entity, EntityPersister persister, Session session) { - } - - @Override - public void findDirty( - Object entity, - EntityPersister persister, - Session session, - DirtyCheckContext dirtyCheckContext) { - // todo : implement proper method body - } - }; - return serviceRegistry.getService( ConfigurationService.class ).getSetting( - AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY, - CustomEntityDirtinessStrategy.class, - defaultValue - ); - } - - @SuppressWarnings({ "unchecked" }) - private CurrentTenantIdentifierResolver determineCurrentTenantIdentifierResolver( - CurrentTenantIdentifierResolver explicitResolver) { - if ( explicitResolver != null ) { - return explicitResolver; - } - return serviceRegistry.getService( ConfigurationService.class ) - .getSetting( - AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, - CurrentTenantIdentifierResolver.class, - null - ); - - } - @SuppressWarnings( {"ThrowableResultOfMethodCallIgnored"}) public SessionFactoryImpl( MetadataImplementor metadata, - SessionFactoryOptions sessionFactoryOptions, - SessionFactoryObserver observer) throws HibernateException { + SessionFactoryOptions providedSessionFactoryOptions) throws HibernateException { final boolean traceEnabled = LOG.isTraceEnabled(); final boolean debugEnabled = traceEnabled || LOG.isDebugEnabled(); @@ -684,17 +685,13 @@ public SessionFactoryImpl( LOG.debug( "Building session factory" ); } - this.sessionFactoryOptions = sessionFactoryOptions; + this.sessionFactoryOptions = providedSessionFactoryOptions; this.properties = createPropertiesFromMap( metadata.getServiceRegistry().getService( ConfigurationService.class ).getSettings() ); - // TODO: these should be moved into SessionFactoryOptions - this.settings = new SettingsFactory().buildSettings( - properties, - metadata.getServiceRegistry() - ); + this.settings = sessionFactoryOptions.getSettings(); this.serviceRegistry = sessionFactoryOptions.getServiceRegistry() @@ -712,17 +709,16 @@ public SessionFactoryImpl( // TODO: get SQL functions from a new service // this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() ); - if ( observer != null ) { - this.observer.addObserver( observer ); + if ( sessionFactoryOptions.getSessionFactoryObservers() != null ) { + for ( SessionFactoryObserver observer : sessionFactoryOptions.getSessionFactoryObservers() ) { + this.observer.addObserver( observer ); + } } this.typeResolver = metadata.getTypeResolver().scope( this ); this.typeHelper = new TypeLocatorImpl( typeResolver ); - this.filters = new HashMap(); - for ( FilterDefinition filterDefinition : metadata.getFilterDefinitions() ) { - filters.put( filterDefinition.getFilterName(), filterDefinition ); - } + this.filters = Collections.unmodifiableMap( metadata.getFilterDefinitions() ); if ( debugEnabled ) { LOG.debugf( "Session factory constructed with filter configurations : %s", filters ); @@ -760,7 +756,7 @@ public void sessionFactoryClosed(SessionFactory factory) { for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { if ( entityBinding.isRoot() ) { identifierGenerators.put( - entityBinding.getEntity().getName(), + entityBinding.getEntityName(), entityBinding.getHierarchyDetails().getEntityIdentifier().getIdentifierGenerator() ); } @@ -770,47 +766,93 @@ public void sessionFactoryClosed(SessionFactory factory) { // Prepare persisters and link them up with their cache // region/access-strategy - StringBuilder stringBuilder = new StringBuilder(); - if ( settings.getCacheRegionPrefix() != null) { - stringBuilder - .append( settings.getCacheRegionPrefix() ) - .append( '.' ); - } - final String cacheRegionPrefix = stringBuilder.toString(); - entityPersisters = new HashMap(); Map entityAccessStrategies = new HashMap(); Map classMeta = new HashMap(); + + final RegionFactory regionFactory = cacheAccess.getRegionFactory(); for ( EntityBinding model : metadata.getEntityBindings() ) { // TODO: should temp table prep happen when metadata is being built? //model.prepareTemporaryTables( metadata, getDialect() ); - // cache region is defined by the root-class in the hierarchy... - EntityBinding rootEntityBinding = metadata.getRootEntityBinding( model.getEntity().getName() ); + EntityRegionAccessStrategy accessStrategy = null; - if ( settings.isSecondLevelCacheEnabled() && - rootEntityBinding.getHierarchyDetails().getCaching() != null && - model.getHierarchyDetails().getCaching() != null && - model.getHierarchyDetails().getCaching().getAccessType() != null ) { - final String cacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails().getCaching().getRegion(); - accessStrategy = EntityRegionAccessStrategy.class.cast( entityAccessStrategies.get( cacheRegionName ) ); - if ( accessStrategy == null ) { - final AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType(); - if ( traceEnabled ) { - LOG.tracev( "Building cache for entity data [{0}]", model.getEntity().getName() ); + NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null; + + if ( settings.isSecondLevelCacheEnabled() ) { + // caching is defined per hierarchy.. so only do this for the root of the hierarchy + if ( model.getSuperEntityBinding() == null ) { + if ( model.getHierarchyDetails().getCaching().getRequested() == TruthValue.TRUE ) { + String baseRegionName = model.getHierarchyDetails().getCaching().getRegion(); + if ( baseRegionName == null ) { + baseRegionName = model.getEntityName(); + } + final String cacheRegionName = StringHelper.makePath( + settings.getCacheRegionPrefix(), + baseRegionName + ); + accessStrategy = EntityRegionAccessStrategy.class.cast( entityAccessStrategies.get( cacheRegionName ) ); + if ( accessStrategy == null ) { + AccessType accessType = model.getHierarchyDetails().getCaching().getAccessType(); + if ( accessType == null ) { + accessType = regionFactory.getDefaultAccessType(); + } + if ( traceEnabled ) { + LOG.tracev( "Building cache for entity data [{0}]", model.getEntityName() ); + } + EntityRegion entityRegion = regionFactory.buildEntityRegion( + cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) + ); + accessStrategy = entityRegion.buildAccessStrategy( accessType ); + entityAccessStrategies.put( cacheRegionName, accessStrategy ); + cacheAccess.addCacheRegion( cacheRegionName, entityRegion ); + } + } + + if ( model.getHierarchyDetails().getNaturalIdCaching().getRequested() == TruthValue.TRUE ) { + String baseRegionName = model.getHierarchyDetails().getNaturalIdCaching().getRegion(); + if ( StringHelper.isEmpty( baseRegionName ) ) { + baseRegionName = model.getEntityName() + "##NaturalId"; + } + final String naturalIdCacheRegionName = StringHelper.makePath( + settings.getCacheRegionPrefix(), + baseRegionName + ); + naturalIdAccessStrategy = (NaturalIdRegionAccessStrategy) entityAccessStrategies.get( + naturalIdCacheRegionName + ); + if ( naturalIdAccessStrategy == null ) { + final CacheDataDescriptionImpl naturalIdCacheDataDescription = CacheDataDescriptionImpl.decode( model ); + NaturalIdRegion naturalIdRegion = null; + try { + naturalIdRegion = regionFactory.buildNaturalIdRegion( + naturalIdCacheRegionName, + properties, + naturalIdCacheDataDescription + ); + } + catch ( UnsupportedOperationException e ) { + LOG.warnf( + "Shared cache region factory [%s] does not support natural id caching; " + + "shared NaturalId caching will be disabled for not be enabled for %s", + regionFactory.getClass().getName(), + model.getEntityName() + ); + } + if ( naturalIdRegion != null ) { + naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( regionFactory.getDefaultAccessType() ); + entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy ); + cacheAccess.addCacheRegion( naturalIdCacheRegionName, naturalIdRegion ); + } + } } - EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion( - cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) - ); - accessStrategy = entityRegion.buildAccessStrategy( accessType ); - entityAccessStrategies.put( cacheRegionName, accessStrategy ); - cacheAccess.addCacheRegion( cacheRegionName, entityRegion ); } } + EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister( - model, accessStrategy, this, metadata + model, accessStrategy, naturalIdAccessStrategy, this, metadata ); - entityPersisters.put( model.getEntity().getName(), cp ); - classMeta.put( model.getEntity().getName(), cp.getClassMetadata() ); + entityPersisters.put( model.getEntityName(), cp ); + classMeta.put( model.getEntityName(), cp.getClassMetadata() ); } this.classMetadata = Collections.unmodifiableMap(classMeta); @@ -826,19 +868,38 @@ public void sessionFactoryClosed(SessionFactory factory) { "AbstractPluralAttributeBinding has a Singular attribute defined: " + model.getAttribute().getName() ); } - final String cacheRegionName = cacheRegionPrefix + model.getCaching().getRegion(); - final AccessType accessType = model.getCaching().getAccessType(); CollectionRegionAccessStrategy accessStrategy = null; - if ( accessType != null && settings.isSecondLevelCacheEnabled() ) { - if ( traceEnabled ) { - LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() ); + if ( settings.isSecondLevelCacheEnabled() + && model.getCaching().getRequested() == TruthValue.TRUE ) { + String baseRegionName = model.getCaching().getRegion(); + if ( baseRegionName == null ) { + baseRegionName = model.getAttributePath().getFullPath(); + } + final String cacheRegionName = StringHelper.makePath( + settings.getCacheRegionPrefix(), + baseRegionName + ); + AccessType accessType = model.getCaching().getAccessType(); + if ( accessType == null ) { + accessType = regionFactory.getDefaultAccessType(); } - CollectionRegion collectionRegion = settings.getRegionFactory().buildCollectionRegion( + if ( accessType != null ) { + if ( traceEnabled ) { + LOG.tracev( "Building cache for collection data [{0}]", model.getAttribute().getRole() ); + } + CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( + cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) + ); + accessStrategy = collectionRegion.buildAccessStrategy( accessType ); + entityAccessStrategies.put( cacheRegionName, accessStrategy ); + cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); + } + CollectionRegion collectionRegion = regionFactory.buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) ); accessStrategy = collectionRegion.buildAccessStrategy( accessType ); entityAccessStrategies.put( cacheRegionName, accessStrategy ); - cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); + cacheAccess.addCacheRegion( cacheRegionName, collectionRegion ); } CollectionPersister persister = serviceRegistry .getService( PersisterFactory.class ) @@ -877,26 +938,35 @@ public void sessionFactoryClosed(SessionFactory factory) { namedQueryRepository = new NamedQueryRepository( metadata.getNamedQueryDefinitions(), metadata.getNamedNativeQueryDefinitions(), - metadata.getResultSetMappingDefinitions(), - new HashMap( ) + metadata.getResultSetMappingDefinitions().values(), + toProcedureCallMementos( + metadata.getNamedStoredProcedureQueryDefinitions(), + metadata.getResultSetMappingDefinitions() + ) ); imports = new HashMap(); - for ( Map.Entry importEntry : metadata.getImports() ) { + for ( Map.Entry importEntry : metadata.getImports().entrySet() ) { imports.put( importEntry.getKey(), importEntry.getValue() ); } // after *all* persisters and named queries are registered - Iterator iter = entityPersisters.values().iterator(); - while ( iter.hasNext() ) { - final EntityPersister persister = ( ( EntityPersister ) iter.next() ); + for ( EntityPersister persister : entityPersisters.values() ) { + persister.generateEntityDefinition(); + } + + for ( EntityPersister persister : entityPersisters.values() ) { persister.postInstantiate(); registerEntityNameResolvers( persister ); + } + if ( sessionFactoryOptions.getEntityNameResolvers() != null ) { + for ( EntityNameResolver resolver : sessionFactoryOptions.getEntityNameResolvers() ) { + registerEntityNameResolver( resolver ); + } } - iter = collectionPersisters.values().iterator(); - while ( iter.hasNext() ) { - final CollectionPersister persister = ( ( CollectionPersister ) iter.next() ); + + for ( CollectionPersister persister : collectionPersisters.values() ) { persister.postInstantiate(); } @@ -909,24 +979,34 @@ public void sessionFactoryClosed(SessionFactory factory) { catch (Exception e) { throw new AssertionFailure("Could not generate UUID"); } - SessionFactoryRegistry.INSTANCE.addSessionFactory( - uuid, - name, - settings.isSessionFactoryNameAlsoJndiName(), - this, - serviceRegistry.getService( JndiService.class ) - ); if ( debugEnabled ) { LOG.debug("Instantiated session factory"); } + // TODO: FIX this + //settings.getMultiTableBulkIdStrategy().prepare( + // jdbcServices, + // buildLocalConnectionAccess(), + // mapp, + // metadata, + // properties + //); + + if ( settings.isAutoCreateSchema() ) { new SchemaExport( metadata ) .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ) .create( false, true ); } + // TODO: implement these for new metamodel + //if ( settings.isAutoUpdateSchema() ) { + // new SchemaUpdate( metadata ).execute( false, true ); + //} + //if ( settings.isAutoValidateSchema() ) { + // new SchemaValidator( metadata ).validate(); + //} if ( settings.isAutoDropSchema() ) { schemaExport = new SchemaExport( metadata ) .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ); @@ -951,9 +1031,9 @@ public void sessionFactoryClosed(SessionFactory factory) { // this needs to happen after persisters are all ready to go... this.fetchProfiles = new HashMap(); - for ( org.hibernate.metamodel.binding.FetchProfile mappingProfile : metadata.getFetchProfiles() ) { + for ( org.hibernate.metamodel.spi.binding.FetchProfile mappingProfile : metadata.getFetchProfiles() ) { final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() ); - for ( org.hibernate.metamodel.binding.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { + for ( org.hibernate.metamodel.spi.binding.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { // resolve the persister owning the fetch final String entityName = getImportedClassName( mappingFetch.getEntity() ); final EntityPersister owner = entityName == null ? null : entityPersisters.get( entityName ); @@ -980,10 +1060,143 @@ public void sessionFactoryClosed(SessionFactory factory) { fetchProfiles.put( fetchProfile.getName(), fetchProfile ); } - this.customEntityDirtinessStrategy = determineCustomEntityDirtinessStrategy(); - this.currentTenantIdentifierResolver = determineCurrentTenantIdentifierResolver( null ); this.transactionEnvironment = new TransactionEnvironmentImpl( this ); this.observer.sessionFactoryCreated( this ); + + SessionFactoryRegistry.INSTANCE.addSessionFactory( + uuid, + name, + settings.isSessionFactoryNameAlsoJndiName(), + this, + serviceRegistry.getService( JndiService.class ) + ); + } + + private Map toProcedureCallMementos( + Map definitions, + Map resultSetMappingMap) { + final Map rtn = new HashMap(); + if ( definitions != null ) { + for (String name : definitions.keySet()){ + rtn.put( name, definitions.get( name ).toMemento( this, resultSetMappingMap )); + } + } + return rtn; + } + + private Map toProcedureCallMementos( + Collection procedureQueryDefinitions, + Map resultSetMappingDefinitions) { + final Map rtn = new HashMap(); + if ( procedureQueryDefinitions != null ) { + for (NamedStoredProcedureQueryDefinition definition : procedureQueryDefinitions ) { + rtn.put( + definition.getName(), + toMemento( definition, resultSetMappingDefinitions ) + ); + } + } + return rtn; + } + + private ProcedureCallMemento toMemento( + NamedStoredProcedureQueryDefinition definition, + final Map resultSetMappingDefinitions) { + final List collectedQueryReturns = new ArrayList(); + final Set collectedQuerySpaces = new HashSet(); + + final boolean specifiesResultClasses = definition.getClassNames().size() > 0; + final boolean specifiesResultSetMappings = definition.getResultSetMappingNames().size() > 0; + + final ClassLoaderService cls = getServiceRegistry().getService( ClassLoaderService.class ); + + if ( specifiesResultClasses ) { + final Class[] classes = new Class[ definition.getClassNames().size() ]; + + List classNames = definition.getClassNames(); + for ( int i = 0, classNamesSize = classNames.size(); i < classNamesSize; i++ ) { + classes[i] = cls.classForName( classNames.get( i ) ); + } + + Util.resolveResultClasses( + new Util.ResultClassesResolutionContext() { + @Override + public SessionFactoryImplementor getSessionFactory() { + return SessionFactoryImpl.this; + } + + @Override + public void addQueryReturns(NativeSQLQueryReturn... queryReturns) { + Collections.addAll( collectedQueryReturns, queryReturns ); + } + + @Override + public void addQuerySpaces(String... spaces) { + Collections.addAll( collectedQuerySpaces, spaces ); + } + }, + classes + ); + } + else if ( specifiesResultSetMappings ) { + Util.resolveResultSetMappings( + new Util.ResultSetMappingResolutionContext() { + @Override + public SessionFactoryImplementor getSessionFactory() { + return SessionFactoryImpl.this; + } + + @Override + public ResultSetMappingDefinition findResultSetMapping(String name) { + return resultSetMappingDefinitions.get( name ); + } + + @Override + public void addQueryReturns(NativeSQLQueryReturn... queryReturns) { + Collections.addAll( collectedQueryReturns, queryReturns ); + } + + @Override + public void addQuerySpaces(String... spaces) { + Collections.addAll( collectedQuerySpaces, spaces ); + } + }, + definition.getResultSetMappingNames() + ); + } + + return new ProcedureCallMementoImpl( + definition.getName(), + collectedQueryReturns.toArray( new NativeSQLQueryReturn[ collectedQueryReturns.size() ] ), + definition.getParameterStrategy(), + toParameterMementos( definition.getParameters(), cls ), + collectedQuerySpaces, + definition.getQueryHints() + ); + } + + private List toParameterMementos( + List parameters, + ClassLoaderService cls) { + final List mementos = new ArrayList(); + for ( int i = 0, parametersSize = parameters.size(); i < parametersSize; i++ ) { + NamedStoredProcedureQueryDefinition.Parameter definition = parameters.get( i ); + mementos.add( toParameterMemento( i+1, definition, cls ) ); + } + return mementos; + } + + private ProcedureCallMementoImpl.ParameterMemento toParameterMemento( + int position, + NamedStoredProcedureQueryDefinition.Parameter definition, + ClassLoaderService cls) { + return new ProcedureCallMementoImpl.ParameterMemento( + position, + name, + definition.getMode(), + cls.classForName( definition.getJavaType() ), + getTypeResolver().heuristicType( definition.getJavaType() ) + ); } @SuppressWarnings( {"unchecked"} ) @@ -1195,15 +1408,15 @@ public String getIdentifierPropertyName(String className) throws MappingExceptio } public Type[] getReturnTypes(String queryString) throws HibernateException { - return queryPlanCache.getHQLQueryPlan( queryString, false, Collections.EMPTY_MAP ) - .getReturnMetadata() - .getReturnTypes(); + final ReturnMetadata metadata = queryPlanCache.getHQLQueryPlan( queryString, false, Collections.EMPTY_MAP ) + .getReturnMetadata(); + return metadata == null ? null : metadata.getReturnTypes(); } public String[] getReturnAliases(String queryString) throws HibernateException { - return queryPlanCache.getHQLQueryPlan( queryString, false, Collections.EMPTY_MAP ) - .getReturnMetadata() - .getReturnAliases(); + final ReturnMetadata metadata = queryPlanCache.getHQLQueryPlan( queryString, false, Collections.EMPTY_MAP ) + .getReturnMetadata(); + return metadata == null ? null : metadata.getReturnAliases(); } public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException { @@ -1577,6 +1790,10 @@ protected TransactionCoordinatorImpl getTransactionCoordinator() { return null; } + protected ActionQueue.TransactionCompletionProcesses getTransactionCompletionProcesses() { + return null; + } + @Override public Session openSession() { log.tracef( "Opening Hibernate Session. tenant=%s, owner=%s", tenantIdentifier, sessionOwner ); @@ -1585,6 +1802,7 @@ public Session openSession() { sessionFactory, sessionOwner, getTransactionCoordinator(), + getTransactionCompletionProcesses(), autoJoinTransactions, sessionFactory.settings.getRegionFactory().nextTimestamp(), interceptor, @@ -1683,7 +1901,8 @@ public StatelessSessionBuilderImpl(SessionFactoryImpl sessionFactory) { @Override public StatelessSession openStatelessSession() { - return new StatelessSessionImpl( connection, tenantIdentifier, sessionFactory ); + return new StatelessSessionImpl( connection, tenantIdentifier, sessionFactory, + sessionFactory.settings.getRegionFactory().nextTimestamp() ); } @Override @@ -1701,12 +1920,12 @@ public StatelessSessionBuilder tenantIdentifier(String tenantIdentifier) { @Override public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { - return customEntityDirtinessStrategy; + return sessionFactoryOptions.getCustomEntityDirtinessStrategy(); } @Override public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { - return currentTenantIdentifierResolver; + return sessionFactoryOptions.getCurrentTenantIdentifierResolver(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 411a5a95cef1..c21066be5f80 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -232,6 +232,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc final SessionFactoryImpl factory, final SessionOwner sessionOwner, final TransactionCoordinatorImpl transactionCoordinator, + final ActionQueue.TransactionCompletionProcesses transactionCompletionProcesses, final boolean autoJoinTransactions, final long timestamp, final Interceptor interceptor, @@ -266,6 +267,9 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc this.transactionCoordinator = transactionCoordinator; this.isTransactionCoordinatorShared = true; this.autoJoinTransactions = false; + if ( transactionCompletionProcesses != null ) { + actionQueue.setTransactionCompletionProcesses( transactionCompletionProcesses, true ); + } if ( autoJoinTransactions ) { LOG.debug( "Session creation specified 'autoJoinTransactions', which is invalid in conjunction " + @@ -365,8 +369,8 @@ public Connection close() throws HibernateException { return transactionCoordinator.close(); } else { - if ( getActionQueue().hasAfterTransactionActions() ){ - LOG.warn( "On close, shared Session had after transaction actions that have not yet been processed" ); + if ( getActionQueue().hasBeforeTransactionActions() || getActionQueue().hasAfterTransactionActions() ) { + LOG.warn( "On close, shared Session had before / after transaction actions that have not yet been processed" ); } else { transactionCoordinator.removeObserver( transactionObserver ); @@ -2318,6 +2322,13 @@ protected TransactionCoordinatorImpl getTransactionCoordinator() { return shareTransactionContext ? session.transactionCoordinator : super.getTransactionCoordinator(); } + @Override + protected ActionQueue.TransactionCompletionProcesses getTransactionCompletionProcesses() { + return shareTransactionContext ? + session.getActionQueue().getTransactionCompletionProcesses() : + super.getTransactionCompletionProcesses(); + } + @Override public SharedSessionBuilder interceptor() { return interceptor( session.interceptor ); @@ -2539,11 +2550,14 @@ public final Object load(Serializable id) { try { fireLoad( event, LoadEventListener.GET ); success = true; - return event.getResult(); + } + catch (ObjectNotFoundException e) { + // if session cache contains proxy for non-existing object } finally { afterOperation( success ); } + return event.getResult(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/StandardEntityNotFoundDelegate.java b/hibernate-core/src/main/java/org/hibernate/internal/StandardEntityNotFoundDelegate.java new file mode 100644 index 000000000000..3e0ebe12bc36 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/internal/StandardEntityNotFoundDelegate.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.internal; + +import java.io.Serializable; + +import org.hibernate.ObjectNotFoundException; +import org.hibernate.proxy.EntityNotFoundDelegate; + +/** + * @author Steve Ebersole + */ +public class StandardEntityNotFoundDelegate implements EntityNotFoundDelegate { + /** + * Singleton access + */ + public static final StandardEntityNotFoundDelegate INSTANCE = new StandardEntityNotFoundDelegate(); + + @Override + public void handleEntityNotFound(String entityName, Serializable id) { + throw new ObjectNotFoundException( id, entityName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java index ea99c5895506..3157f162ae19 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java @@ -84,10 +84,23 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele private TransactionCoordinator transactionCoordinator; private PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext( this ); - - StatelessSessionImpl(Connection connection, String tenantIdentifier, SessionFactoryImpl factory) { + private long timestamp; + + StatelessSessionImpl( + Connection connection, + String tenantIdentifier, + SessionFactoryImpl factory) { + this( connection, tenantIdentifier, factory, factory.getSettings().getRegionFactory().nextTimestamp() ); + } + + StatelessSessionImpl( + Connection connection, + String tenantIdentifier, + SessionFactoryImpl factory, + long timestamp) { super( factory, tenantIdentifier ); this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this ); + this.timestamp = timestamp; } // TransactionContext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -532,7 +545,7 @@ public PersistenceContext getPersistenceContext() { @Override public long getTimestamp() { - throw new UnsupportedOperationException(); + return timestamp; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/JaxbRoot.java b/hibernate-core/src/main/java/org/hibernate/internal/jaxb/JaxbRoot.java deleted file mode 100644 index 57bbb80461ef..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/JaxbRoot.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.internal.jaxb; - -/** - * Holds information about a JAXB-unmarshalled XML document. - * - * @author Hardy Ferentschik - * @author Steve Ebersole - */ -public class JaxbRoot { - private final T root; - private final Origin origin; - - public JaxbRoot(T root, Origin origin) { - this.root = root; - this.origin = origin; - } - - /** - * Obtain the root JAXB bound object - * - * @return The JAXB root object - */ - public T getRoot() { - return root; - } - - /** - * Obtain the metadata about the document's origin - * - * @return The origin - */ - public Origin getOrigin() { - return origin; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/Origin.java b/hibernate-core/src/main/java/org/hibernate/internal/jaxb/Origin.java deleted file mode 100644 index c596537f8b04..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/Origin.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.internal.jaxb; - -import java.io.Serializable; - -/** - * Describes the origin of an xml document - * - * @author Steve Ebersole - */ -public class Origin implements Serializable { - private final SourceType type; - private final String name; - - public Origin(SourceType type, String name) { - this.type = type; - this.name = name; - } - - /** - * Retrieve the type of origin. - * - * @return The origin type. - */ - public SourceType getType() { - return type; - } - - /** - * The name of the document origin. Interpretation is relative to the type, but might be the - * resource name or file URL. - * - * @return The name. - */ - public String getName() { - return name; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/CustomSqlElement.java b/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/CustomSqlElement.java deleted file mode 100644 index 5213c84d3629..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/CustomSqlElement.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.internal.jaxb.mapping.hbm; - -/** - * @author Steve Ebersole - */ -public interface CustomSqlElement { - public String getValue(); - public boolean isCallable(); - public JaxbCheckAttribute getCheck(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/EntityElement.java b/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/EntityElement.java deleted file mode 100644 index a0280bc69cfb..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/EntityElement.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.internal.jaxb.mapping.hbm; - -import java.util.List; - -/** - * @author Steve Ebersole - */ -public interface EntityElement extends MetaAttributeContainer { - public String getName(); - public String getEntityName(); - - public Boolean isAbstract(); - public Boolean isLazy(); - public String getProxy(); - public String getBatchSize(); - public boolean isDynamicInsert(); - public boolean isDynamicUpdate(); - public boolean isSelectBeforeUpdate(); - - public List getTuplizer(); - public String getPersister(); - - public JaxbLoaderElement getLoader(); - public JaxbSqlInsertElement getSqlInsert(); - public JaxbSqlUpdateElement getSqlUpdate(); - public JaxbSqlDeleteElement getSqlDelete(); - - public List getSynchronize(); - - public List getFetchProfile(); - - public List getResultset(); - - public List getQueryOrSqlQuery(); - - public List getPropertyOrManyToOneOrOneToOne(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SingularAttributeSource.java deleted file mode 100644 index 0030cbe725d7..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SingularAttributeSource.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.internal.jaxb.mapping.hbm; - -/** - * @author Steve Ebersole - */ -public interface SingularAttributeSource extends MetaAttributeContainer { - public String getName(); - - public String getTypeAttribute(); - - public JaxbTypeElement getType(); - - public String getAccess(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java index a1b289b54001..3db3b8a38785 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java @@ -24,10 +24,14 @@ */ package org.hibernate.internal.util; +import java.beans.Introspector; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; import org.hibernate.AssertionFailure; import org.hibernate.MappingException; @@ -39,6 +43,14 @@ import org.hibernate.type.PrimitiveType; import org.hibernate.type.Type; +import com.fasterxml.classmate.MemberResolver; +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import com.fasterxml.classmate.TypeResolver; +import com.fasterxml.classmate.members.ResolvedField; +import com.fasterxml.classmate.members.ResolvedMethod; +import com.fasterxml.classmate.types.ResolvedArrayType; + /** * Utility class for various reflection operations. * @@ -60,6 +72,9 @@ public final class ReflectHelper { private static final Method OBJECT_EQUALS; private static final Method OBJECT_HASHCODE; + private static final TypeResolver TYPE_RESOLVER = new TypeResolver(); + private static final MemberResolver MEMBER_RESOLVER = new MemberResolver( TYPE_RESOLVER ); + static { Method eq; Method hash; @@ -303,9 +318,7 @@ public static Constructor getDefaultConstructor(Class clazz) throws Pr try { Constructor constructor = clazz.getDeclaredConstructor( NO_PARAM_SIGNATURE ); - if ( !isPublic( clazz, constructor ) ) { - constructor.setAccessible( true ); - } + constructor.setAccessible( true ); return constructor; } catch ( NoSuchMethodException nme ) { @@ -363,9 +376,7 @@ public static Constructor getConstructor(Class clazz, Type[] types) throws Prope } } if ( found ) { - if ( !isPublic( clazz, constructor ) ) { - constructor.setAccessible( true ); - } + constructor.setAccessible( true ); return constructor; } } @@ -382,4 +393,97 @@ public static Method getMethod(Class clazz, Method method) { } } + /** + * Process bean properties getter by applying the JavaBean naming conventions. + * + * @param member the member for which to get the property name. + * + * @return The bean method name with the "is" or "get" prefix stripped off, {@code null} + * the method name id not according to the JavaBeans standard. + */ + public static String getPropertyName(Member member) { + String name = null; + + if ( member instanceof Field ) { + name = member.getName(); + } + + if ( member instanceof Method ) { + name = getPropertyNameFromGetterMethod( member.getName() ); + } + return name; + } + + public static String getPropertyNameFromGetterMethod(String methodName) { + if ( methodName.startsWith( "is" ) ) { + return Introspector.decapitalize( methodName.substring( 2 ) ); + } + else if ( methodName.startsWith( "has" ) ) { + return Introspector.decapitalize( methodName.substring( 3 ) ); + } + else if ( methodName.startsWith( "get" ) ) { + return Introspector.decapitalize( methodName.substring( 3 ) ); + } + + return null; + } + + public static boolean isProperty(Member m) { + if ( m instanceof Method ) { + Method method = (Method) m; + return !method.isSynthetic() + && !method.isBridge() + && !Modifier.isStatic( method.getModifiers() ) + && method.getParameterTypes().length == 0 + && ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) ); + } + else { + return !Modifier.isTransient( m.getModifiers() ) && !m.isSynthetic(); + } + } + + /** + * Returns a Set of field types in the given class. However, for Collection + * and Map fields, the value and key types are returned instead of the + * Iterable class itself. + * + * @param clazz + * @return Set> + */ + // TODO: This should be moved out of ReflectHelper. Partial duplication with + // AnnotationBindingContextImpl#resolveMemberTypes + public static Set> getMemberTypes( Class clazz ) { + Set> fieldTypes = new HashSet>(); + + ResolvedType resolvedType = TYPE_RESOLVER.resolve( clazz ); + ResolvedTypeWithMembers resolvedTypes = MEMBER_RESOLVER.resolve( resolvedType, null, null ); + ResolvedField[] resolvedFields = resolvedTypes.getMemberFields(); + + for ( ResolvedField resolvedField : resolvedFields ) { + resolveAllTypes( resolvedField.getType(), fieldTypes ); + } + + // TODO: This should really just be checking getters, but for now do everything. + ResolvedMethod[] resolvedMethods = resolvedTypes.getMemberMethods(); + for ( ResolvedMethod resolvedMethod : resolvedMethods ) { + if ( resolvedMethod.getReturnType() != null ) { + resolveAllTypes( resolvedMethod.getReturnType(), fieldTypes ); + } + } + + return fieldTypes; + } + + private static void resolveAllTypes(ResolvedType fieldType, Set> fieldTypes) { + if ( fieldType instanceof ResolvedArrayType ) { + ResolvedArrayType arrayType = (ResolvedArrayType) fieldType; + resolveAllTypes( arrayType.getArrayElementType(), fieldTypes ); + } else { + fieldTypes.add( fieldType.getErasedType() ); + } + + for ( ResolvedType typeParameter : fieldType.getTypeBindings().getTypeParameters() ) { + resolveAllTypes( typeParameter, fieldTypes ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java index bf2a8fdf8c2d..5f814756b8b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/StringHelper.java @@ -39,6 +39,7 @@ public final class StringHelper { private static final int ALIAS_TRUNCATE_LENGTH = 10; public static final String WHITESPACE = " \n\r\f\t"; + public static final String [] EMPTY_STRINGS = new String[0]; private StringHelper() { /* static methods only - hide constructor */ } @@ -454,6 +455,10 @@ public static boolean isEmpty(String string) { return string == null || string.length() == 0; } + public static boolean isEmptyOrWhiteSpace(String string){ + return isEmpty( string ) || isEmpty( string.trim() ); + } + public static String qualify(String prefix, String name) { if ( name == null || prefix == null ) { throw new NullPointerException( "prefix or name were null attempting to build qualified name" ); @@ -490,6 +495,18 @@ public static String[] qualifyIfNot(String prefix, String[] names) { return qualified; } + public static String qualifyIfNot(String qualifier, String name) { + if ( isEmpty( name ) ) { + return null; + } + + if ( name.indexOf( '.' ) > 0 ) { + return name; + } + + return qualify( qualifier, name ); + } + public static int firstIndexOfChar(String sqlString, BitSet keys, int startindex) { for ( int i = startindex, size = sqlString.length(); i < size; i++ ) { if ( keys.get( sqlString.charAt( i ) ) ) { @@ -617,7 +634,9 @@ public static String moveAndToBeginning(String filter) { * @return True if the given string starts and ends with '`'; false otherwise. */ public static boolean isQuoted(String name) { - return name != null && name.length() != 0 && name.charAt( 0 ) == '`' && name.charAt( name.length() - 1 ) == '`'; + return name != null && name.length() != 0 + && ( ( name.charAt( 0 ) == '`' && name.charAt( name.length() - 1 ) == '`' ) + || ( name.charAt( 0 ) == '"' && name.charAt( name.length() - 1 ) == '"' ) ); } /** @@ -631,7 +650,7 @@ public static String quote(String name) { if ( isEmpty( name ) || isQuoted( name ) ) { return name; } -// Convert the JPA2 specific quoting character (double quote) to Hibernate's (back tick) + // Convert the JPA2 specific quoting character (double quote) to Hibernate's (back tick) else if ( name.startsWith( "\"" ) && name.endsWith( "\"" ) ) { name = name.substring( 1, name.length() - 1 ); } @@ -663,18 +682,11 @@ public static String unquote(String name) { * @return True if quoted, false otherwise */ public static boolean isQuoted(String name, Dialect dialect) { - return name != null - && - name.length() != 0 - && ( - name.charAt( 0 ) == '`' - && - name.charAt( name.length() - 1 ) == '`' - || - name.charAt( 0 ) == dialect.openQuote() - && - name.charAt( name.length() - 1 ) == dialect.closeQuote() - ); + return name != null && name.length() != 0 + && ( ( name.charAt( 0 ) == '`' && name.charAt( name.length() - 1 ) == '`' ) + || ( name.charAt( 0 ) == '"' && name.charAt( name.length() - 1 ) == '"' ) + || ( name.charAt( 0 ) == dialect.openQuote() + && name.charAt( name.length() - 1 ) == dialect.closeQuote() ) ); } /** @@ -783,4 +795,16 @@ public static String expandBatchIdPlaceholder( public static String[] toArrayElement(String s) { return ( s == null || s.length() == 0 ) ? new String[0] : new String[] { s }; } + + public static String makePath(String base, String name) { + if ( isEmpty( name ) ) { + throw new IllegalArgumentException( "Name used to make path cannot be empty" ); + } + + return isEmpty( base ) ? name : base + '.' + name; + } + + public static String nullIfEmpty(String value) { + return isEmpty( value ) ? null : value; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ValueHolder.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ValueHolder.java index 3570bb20205d..d17dc0be5297 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ValueHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ValueHolder.java @@ -26,6 +26,8 @@ /** * Represents a "final" value that is initialized either {@link #ValueHolder(Object) up front} or once at some point * {@link #ValueHolder(ValueHolder.DeferredInitializer) after} declaration. + * + * Note: If a Serializable class has a {@link ValueHolder} property, that property should be declared transient! * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java index 8a928d264294..417acdd4f791 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java @@ -339,6 +339,17 @@ private static int hash(int seed, int i) { return PRIME_NUMER * seed + i; } + /** + * Returns {@code true} if the specified array is {@code null} or empty. + * + * @param array the array to check. + * @return {@code true} if the specified array is {@code null} or empty. + */ + + public static boolean isEmpty(final Object[] array) { + return array == null || array.length == 0; + } + /** * Compare 2 arrays only at the first level */ diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java index d241d768a432..206f75462aae 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java @@ -156,7 +156,11 @@ public static boolean isEmpty(Collection collection) { return collection == null || collection.isEmpty(); } - public static boolean isEmpty(Map map) { + public static boolean isEmpty(Iterable iterable){ + return iterable == null || !iterable.iterator().hasNext(); + } + + public static boolean isEmpty(Map map) { return map == null || map.isEmpty(); } @@ -172,6 +176,23 @@ public static boolean isEmpty(Object[] objects){ return objects == null || objects.length==0; } + public static boolean isCollectionOrArray(Class clazz) { + if ( clazz == null ) { + return false; + } + if ( Collection.class.isAssignableFrom( clazz ) ) { + return true; + } + if ( Map.class.isAssignableFrom( clazz ) ) { + return true; + } + // TODO: why is the next block commented out??? +// if ( clazz.isArray() ) { +// return true; +// } + return false; + } + public static Map makeCopy(Map map) { final Map copy = mapOfSize( map.size() + 1 ); copy.putAll( map ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/DTDEntityResolver.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/DTDEntityResolver.java index 66008b68a2b4..afd8b6ec7718 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/DTDEntityResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/DTDEntityResolver.java @@ -55,6 +55,7 @@ * @author Steve Ebersole * @author Hardy Ferentschik */ +@Deprecated public class DTDEntityResolver implements EntityResolver, Serializable { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, DTDEntityResolver.class.getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/ErrorLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/ErrorLogger.java index 36ba7906917b..3f0ee6ea9a37 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/ErrorLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/ErrorLogger.java @@ -41,6 +41,7 @@ * @author Steve Ebersole * @author Hardy Ferentschik */ +@Deprecated public class ErrorLogger implements ErrorHandler, Serializable { private static final CoreMessageLogger LOG = Logger.getMessageLogger( diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java deleted file mode 100644 index f138998e4386..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/MappingReader.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.internal.util.xml; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.net.URL; -import javax.xml.XMLConstants; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.XMLEvent; -import javax.xml.transform.stax.StAXSource; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; - -import org.hibernate.InvalidMappingException; -import org.hibernate.internal.CoreMessageLogger; - -import org.jboss.logging.Logger; - -import org.dom4j.Document; -import org.dom4j.io.SAXReader; -import org.dom4j.io.STAXEventReader; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -/** - * Handles reading mapping documents, both {@code hbm} and {@code orm} varieties. - * - * @author Steve Ebersole - */ -public class MappingReader { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - MappingReader.class.getName() - ); - - public static final MappingReader INSTANCE = new MappingReader(); - - /** - * Disallow direct instantiation. - *

    - * Eventually we perhaps need to have this configurable by the "configuration" and simply reference it - * from there (registry). This would allow, for example, injection of the entity resolver to use as - * instance state. - */ - private MappingReader() { - } - - public XmlDocument readMappingDocument(InputSource source, Origin origin) { - XMLEventReader staxReader = buildStaxEventReader( source, origin ); - try { - return read( staxReader, origin ); - } - finally { - try { - staxReader.close(); - } - catch ( Exception ignore ) { - } - } - } - - private XMLEventReader buildStaxEventReader(InputSource source, Origin origin) { - XMLEventReader reader = null; - - if ( source.getByteStream() != null ) { - try { - reader = staxFactory().createXMLEventReader( source.getByteStream() ); - } - catch (XMLStreamException e) { - throw new XmlInfrastructureException( - "Unable to create stax reader, origin = " + toLoggableString( origin ), - e - ); - } - } - else if ( source.getCharacterStream() != null ) { - try { - reader = staxFactory().createXMLEventReader( source.getCharacterStream() ); - } - catch (XMLStreamException e) { - throw new XmlInfrastructureException( - "Unable to create stax reader, origin = " + toLoggableString( origin ), - e - ); - } - } - // todo : try to interpret the InputSource SystemId or Origin path? - - if ( reader == null ) { - throw new XmlInfrastructureException( "Unable to convert SAX InputStream into StAX XMLEventReader" ); - } - - // For performance we wrap the reader in a buffered reader - return new BufferedXMLEventReader( reader ); - } - - private XMLInputFactory staxFactory; - - private XMLInputFactory staxFactory() { - if ( staxFactory == null ) { - staxFactory = buildStaxFactory(); - } - return staxFactory; - } - - @SuppressWarnings( { "UnnecessaryLocalVariable" }) - private XMLInputFactory buildStaxFactory() { - XMLInputFactory staxFactory = XMLInputFactory.newInstance(); - staxFactory.setXMLResolver( LocalXmlResourceResolver.INSTANCE ); - return staxFactory; - } - - private String toLoggableString(Origin origin) { - return "[type=" + origin.getType() + ", name=" + origin.getName() + "]"; - } - - private static final QName ORM_VERSION_ATTRIBUTE_QNAME = new QName( "version" ); - - private XmlDocument read(XMLEventReader staxEventReader, Origin origin) { - XMLEvent event; - try { - event = staxEventReader.peek(); - while ( event != null && !event.isStartElement() ) { - staxEventReader.nextEvent(); - event = staxEventReader.peek(); - } - } - catch ( Exception e ) { - throw new InvalidMappingException( "Error accessing stax stream", origin, e ); - } - - if ( event == null ) { - throw new InvalidMappingException( "Could not locate root element", origin ); - } - - final String rootElementName = event.asStartElement().getName().getLocalPart(); - - if ( "entity-mappings".equals( rootElementName ) ) { - final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME ); - final String explicitVersion = attribute == null ? null : attribute.getValue(); - validateMapping( - SupportedOrmXsdVersion.parse( explicitVersion, origin ), - staxEventReader, - origin - ); - } - - return new XmlDocumentImpl( toDom4jDocument( staxEventReader, origin ), origin ); - } - - private Document toDom4jDocument(XMLEventReader staxEventReader, Origin origin) { - STAXEventReader dom4jStaxEventReader = new STAXEventReader(); - try { - // the dom4j converter class is touchy about comments (aka, comments make it implode) - // so wrap the event stream in a filtering stream to filter out comment events - staxEventReader = new FilteringXMLEventReader( staxEventReader ) { - @Override - protected XMLEvent filterEvent(XMLEvent event, boolean peek) { - return event.getEventType() == XMLStreamConstants.COMMENT - ? null - : event; - } - }; - - return dom4jStaxEventReader.readDocument( staxEventReader ); - } - catch (XMLStreamException e) { - throw new InvalidMappingException( "Unable to read StAX source as dom4j Document for processing", origin, e ); - } - } - - private void validateMapping(SupportedOrmXsdVersion xsdVersion, XMLEventReader staxEventReader, Origin origin) { - final Validator validator = xsdVersion.getSchema().newValidator(); - final StAXSource staxSource; - try { - staxSource = new StAXSource( staxEventReader ); - } - catch (XMLStreamException e) { - throw new InvalidMappingException( "Unable to generate StAXSource from mapping", origin, e ); - } - - try { - validator.validate( staxSource ); - } - catch (SAXException e) { - throw new InvalidMappingException( "SAXException performing validation", origin, e ); - } - catch (IOException e) { - throw new InvalidMappingException( "IOException performing validation", origin, e ); - } - } - - public static enum SupportedOrmXsdVersion { - ORM_1_0( "org/hibernate/jpa/orm_1_0.xsd" ), - ORM_2_0( "org/hibernate/jpa/orm_2_0.xsd" ), - ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" ); - - private final String schemaResourceName; - - private SupportedOrmXsdVersion(String schemaResourceName) { - this.schemaResourceName = schemaResourceName; - } - - public static SupportedOrmXsdVersion parse(String name, Origin origin) { - if ( "1.0".equals( name ) ) { - return ORM_1_0; - } - else if ( "2.0".equals( name ) ) { - return ORM_2_0; - } - else if ( "2.1".equals( name ) ) { - return ORM_2_1; - } - throw new UnsupportedOrmXsdVersionException( name, origin ); - } - - private URL schemaUrl; - - public URL getSchemaUrl() { - if ( schemaUrl == null ) { - schemaUrl = resolveLocalSchemaUrl( schemaResourceName ); - } - return schemaUrl; - } - - private Schema schema; - - public Schema getSchema() { - if ( schema == null ) { - schema = resolveLocalSchema( getSchemaUrl() ); - } - return schema; - } - } - - private static URL resolveLocalSchemaUrl(String schemaName) { - URL url = MappingReader.class.getClassLoader().getResource( schemaName ); - if ( url == null ) { - throw new XmlInfrastructureException( "Unable to locate schema [" + schemaName + "] via classpath" ); - } - return url; - } - - private static Schema resolveLocalSchema(URL schemaUrl) { - - try { - InputStream schemaStream = schemaUrl.openStream(); - try { - StreamSource source = new StreamSource(schemaUrl.openStream()); - SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); - return schemaFactory.newSchema(source); - } - catch ( Exception e ) { - throw new XmlInfrastructureException( "Unable to load schema [" + schemaUrl.toExternalForm() + "]", e ); - } - finally { - try { - schemaStream.close(); - } - catch ( IOException e ) { - LOG.debugf( "Problem closing schema stream - %s", e.toString() ); - } - } - } - catch ( IOException e ) { - throw new XmlInfrastructureException( "Stream error handling schema url [" + schemaUrl.toExternalForm() + "]" ); - } - - } - - - public XmlDocument readMappingDocument(EntityResolver entityResolver, InputSource source, Origin origin) { - return legacyReadMappingDocument( entityResolver, source, origin ); -// return readMappingDocument( source, origin ); - } - - private XmlDocument legacyReadMappingDocument(EntityResolver entityResolver, InputSource source, Origin origin) { - // IMPL NOTE : this is the legacy logic as pulled from the old AnnotationConfiguration code - - Exception failure; - - ErrorLogger errorHandler = new ErrorLogger(); - - SAXReader saxReader = new SAXReader(); - saxReader.setEntityResolver( entityResolver ); - saxReader.setErrorHandler( errorHandler ); - saxReader.setMergeAdjacentText( true ); - saxReader.setValidation( true ); - - Document document = null; - try { - // first try with orm 2.1 xsd validation - setValidationFor( saxReader, "orm_2_1.xsd" ); - document = saxReader.read( source ); - if ( errorHandler.hasErrors() ) { - throw errorHandler.getErrors().get( 0 ); - } - return new XmlDocumentImpl( document, origin.getType(), origin.getName() ); - } - catch ( Exception e ) { - if ( LOG.isDebugEnabled() ) { - LOG.debugf( "Problem parsing XML using orm 2.1 xsd, trying 2.0 xsd : %s", e.getMessage() ); - } - failure = e; - errorHandler.reset(); - - if ( document != null ) { - // next try with orm 2.0 xsd validation - try { - setValidationFor( saxReader, "orm_2_0.xsd" ); - document = saxReader.read( new StringReader( document.asXML() ) ); - if ( errorHandler.hasErrors() ) { - errorHandler.logErrors(); - throw errorHandler.getErrors().get( 0 ); - } - return new XmlDocumentImpl( document, origin.getType(), origin.getName() ); - } - catch ( Exception e2 ) { - if ( LOG.isDebugEnabled() ) { - LOG.debugf( "Problem parsing XML using orm 2.0 xsd, trying 1.0 xsd : %s", e2.getMessage() ); - } - errorHandler.reset(); - - if ( document != null ) { - // next try with orm 1.0 xsd validation - try { - setValidationFor( saxReader, "orm_1_0.xsd" ); - document = saxReader.read( new StringReader( document.asXML() ) ); - if ( errorHandler.hasErrors() ) { - errorHandler.logErrors(); - throw errorHandler.getErrors().get( 0 ); - } - return new XmlDocumentImpl( document, origin.getType(), origin.getName() ); - } - catch ( Exception e3 ) { - if ( LOG.isDebugEnabled() ) { - LOG.debugf( "Problem parsing XML using orm 1.0 xsd : %s", e3.getMessage() ); - } - } - } - } - } - } - throw new InvalidMappingException( "Unable to read XML", origin.getType(), origin.getName(), failure ); - } - - private void setValidationFor(SAXReader saxReader, String xsd) { - try { - saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true ); - // saxReader.setFeature( "http://apache.org/xml/features/validation/dynamic", true ); - if ( "orm_2_1.xsd".equals( xsd ) ) { - saxReader.setProperty( - "http://apache.org/xml/properties/schema/external-schemaLocation", - "http://xmlns.jcp.org/xml/ns/persistence/orm " + xsd - ); - } - else { - saxReader.setProperty( - "http://apache.org/xml/properties/schema/external-schemaLocation", - "http://java.sun.com/xml/ns/persistence/orm " + xsd - ); - } - } - catch ( SAXException e ) { - saxReader.setValidation( false ); - } - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/Origin.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/Origin.java index 805cdd816881..b2ed1a702dd3 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/Origin.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/Origin.java @@ -30,9 +30,10 @@ * * @author Steve Ebersole */ +@Deprecated public interface Origin extends Serializable { /** - * Retrieve the type of origin. This is not a discrete set, but might be somethign like + * Retrieve the type of origin. This is not a discrete set, but might be something like * {@code file} for file protocol URLs, or {@code resource} for classpath resource lookups. * * @return The origin type. diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/OriginImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/OriginImpl.java index 5bd66025cde2..6a6b739f6c98 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/OriginImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/OriginImpl.java @@ -30,6 +30,7 @@ * * @author Steve Ebersole */ +@Deprecated public class OriginImpl implements Origin, Serializable { private final String type; private final String name; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java index 6708dfd63a91..8d2dab7e1945 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java @@ -37,6 +37,7 @@ /** * Small helper class that lazy loads DOM and SAX reader and keep them for fast use afterwards. */ +@Deprecated public final class XMLHelper { public static final EntityResolver DEFAULT_DTD_RESOLVER = new DTDEntityResolver(); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocument.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocument.java index 0822a9f6aa08..6e6f3ee8d30f 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocument.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocument.java @@ -32,6 +32,7 @@ * * @author Steve Ebersole */ +@Deprecated public interface XmlDocument extends Serializable { /** * Retrieve the parsed DOM tree. diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocumentImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocumentImpl.java index aac9763100a9..33caa55600e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocumentImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlDocumentImpl.java @@ -28,10 +28,11 @@ import org.dom4j.Document; /** - * Basic implemementation of {@link XmlDocument} + * Basic implementation of {@link XmlDocument} * * @author Steve Ebersole */ +@Deprecated public class XmlDocumentImpl implements XmlDocument, Serializable { private final Document documentTree; private final Origin origin; @@ -40,6 +41,7 @@ public XmlDocumentImpl(Document documentTree, String originType, String originNa this( documentTree, new OriginImpl( originType, originName ) ); } + public XmlDocumentImpl(Document documentTree, Origin origin) { this.documentTree = documentTree; this.origin = origin; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java b/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java index c415c6e7a475..40a4fc8d0e53 100755 --- a/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/JoinWalker.java @@ -549,15 +549,9 @@ else if ( type.isComponentType() ) { final Type idType = persister.getIdentifierType(); if ( idType.isComponentType() ) { final CompositeType cidType = (CompositeType) idType; - if ( cidType.isEmbedded() ) { - // we have an embedded composite identifier. Most likely we need to process the composite - // properties separately, although there is an edge case where the identifier is really - // a simple identifier (single value) wrapped in a JPA @IdClass or even in the case of a - // a simple identifier (single value) wrapped in a Hibernate composite type. - // - // We really do not have a built-in method to determine that. However, generally the - // persister would report that there is single, physical identifier property which is - // explicitly at odds with the notion of "embedded composite". So we use that for now + if ( persister.getEntityMetamodel().getIdentifierProperty().isVirtual() ) { + // we have a non-aggregated composite identifier. We need to process + // the composite sub-properties separately if ( persister.getEntityMetamodel().getIdentifierProperty().isEmbedded() ) { walkComponentTree( cidType, @@ -570,6 +564,27 @@ else if ( type.isComponentType() ) { ); } } +// if ( cidType.isEmbedded() ) { +// // we have an embedded composite identifier. Most likely we need to process the composite +// // properties separately, although there is an edge case where the identifier is really +// // a simple identifier (single value) wrapped in a JPA @IdClass or even in the case of a +// // a simple identifier (single value) wrapped in a Hibernate composite type. +// // +// // We really do not have a built-in method to determine that. However, generally the +// // persister would report that there is single, physical identifier property which is +// // explicitly at odds with the notion of "embedded composite". So we use that for now +// if ( persister.getEntityMetamodel().getIdentifierProperty().isEmbedded() ) { +// walkComponentTree( +// cidType, +// -1, +// 0, +// persister, +// alias, +// path, +// currentDepth +// ); +// } +// } } } @@ -792,7 +807,7 @@ protected boolean isDuplicateAssociation(final String foreignKeyTable, final Str protected boolean isDuplicateAssociation(final String lhsTable, final String[] lhsColumnNames, final AssociationType type) { final String foreignKeyTable; final String[] foreignKeyColumns; - if ( type.getForeignKeyDirection()==ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) { + if ( type.getForeignKeyDirection()==ForeignKeyDirection.FROM_PARENT ) { foreignKeyTable = lhsTable; foreignKeyColumns = lhsColumnNames; } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java index c477d813d986..5a2642fb51de 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java @@ -2104,15 +2104,17 @@ private ResultSet wrapResultSetIfEnabled(final ResultSet rs, final SessionImplem } private ColumnNameCache retreiveColumnNameToIndexCache(final ResultSet rs) throws SQLException { - if ( columnNameCache == null ) { - synchronized ( this ) { - if ( columnNameCache == null ) { - LOG.trace( "Building columnName -> columnIndex cache" ); - columnNameCache = new ColumnNameCache( rs.getMetaData().getColumnCount() ); - } - } + final ColumnNameCache cache = columnNameCache; + if ( cache == null ) { + //there is no need for a synchronized second check, as in worst case + //we'll have allocated an unnecessary ColumnNameCache + LOG.trace( "Building columnName -> columnIndex cache" ); + columnNameCache = new ColumnNameCache( rs.getMetaData().getColumnCount() ); + return columnNameCache; + } + else { + return cache; } - return columnNameCache; } /** @@ -2506,7 +2508,7 @@ private EntityPersister getEntityPersister(EntityType entityType) { return factory.getEntityPersister( entityType.getAssociatedEntityName() ); } - private void putResultInQueryCache( + protected void putResultInQueryCache( final SessionImplementor session, final QueryParameters queryParameters, final Type[] resultTypes, diff --git a/hibernate-core/src/main/java/org/hibernate/loader/PropertyPath.java b/hibernate-core/src/main/java/org/hibernate/loader/PropertyPath.java index 3a1f6284cec6..fdbf269fe642 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/PropertyPath.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/PropertyPath.java @@ -30,13 +30,36 @@ */ public class PropertyPath { public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper"; + + private final char delimiter; private final PropertyPath parent; private final String property; private final String fullPath; - public PropertyPath(PropertyPath parent, String property) { + public PropertyPath() { + this( null, "", '.' ); + } + + public PropertyPath(char delimiter) { + this( null, "", delimiter ); + } + + public PropertyPath(String base) { + this( null, base, '.' ); + } + + public PropertyPath(String base, char delimiter) { + this( null, base, delimiter ); + } + + private PropertyPath(PropertyPath parent, String property) { + this( parent, property, parent.delimiter ); + } + + private PropertyPath(PropertyPath parent, String property, char delimiter) { this.parent = parent; this.property = property; + this.delimiter = delimiter; // the _identifierMapper is a "hidden" property on entities with composite keys. // concatenating it will prevent the path from correctly being used to look up @@ -52,7 +75,7 @@ public PropertyPath(PropertyPath parent, String property) { prefix = ""; } else { - prefix = resolvedParent + '.'; + prefix = resolvedParent + delimiter; } } else { @@ -63,14 +86,6 @@ public PropertyPath(PropertyPath parent, String property) { } } - public PropertyPath(String property) { - this( null, property ); - } - - public PropertyPath() { - this( "" ); - } - public PropertyPath append(String property) { return new PropertyPath( this, property ); } @@ -87,8 +102,12 @@ public String getFullPath() { return fullPath; } + public char getDelimiter() { + return delimiter; + } + public boolean isRoot() { - return parent == null && StringHelper.isEmpty( property ); + return parent == null; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/loader/custom/CustomLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/custom/CustomLoader.java index 25a622007328..8e85de6033be 100755 --- a/hibernate-core/src/main/java/org/hibernate/loader/custom/CustomLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/custom/CustomLoader.java @@ -38,6 +38,8 @@ import org.hibernate.QueryException; import org.hibernate.ScrollableResults; import org.hibernate.Session; +import org.hibernate.cache.spi.QueryCache; +import org.hibernate.cache.spi.QueryKey; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -529,5 +531,27 @@ private void validateAliases(List aliases) { @SuppressWarnings("UnusedParameters") protected void validateAlias(String alias) { } + + /** + * {@link #resultTypes} can be overridden by {@link #autoDiscoverTypes(ResultSet)}, + * *after* {@link #list(SessionImplementor, QueryParameters)} has already been called. It's a bit of a + * chicken-and-the-egg issue since {@link #autoDiscoverTypes(ResultSet)} needs the {@link ResultSet}. + * + * As a hacky workaround, override + * {@link #putResultInQueryCache(SessionImplementor, QueryParameters, Type[], QueryCache, QueryKey, List)} here + * and provide the {@link #resultTypes}. + * + * @see HHH-3051 + */ + @Override + protected void putResultInQueryCache( + final SessionImplementor session, + final QueryParameters queryParameters, + final Type[] resultTypes, + final QueryCache queryCache, + final QueryKey key, + final List result) { + super.putResultInQueryCache( session, queryParameters, this.resultTypes, queryCache, key, result ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractEntityGraphVisitationStrategy.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractEntityGraphVisitationStrategy.java index 58f46cb12a9c..ae996108194a 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractEntityGraphVisitationStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractEntityGraphVisitationStrategy.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; + import javax.persistence.AttributeNode; import javax.persistence.Subgraph; import javax.persistence.metamodel.Attribute; @@ -44,17 +45,17 @@ import org.hibernate.graph.spi.GraphNodeImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.loader.plan.spi.EntityReturn; +import org.hibernate.loader.plan.spi.FetchSource; import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.loader.plan.spi.Return; +import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; +import org.hibernate.persister.walking.spi.AssociationKey; import org.hibernate.persister.walking.spi.AttributeDefinition; -import org.hibernate.persister.walking.spi.CollectionDefinition; import org.hibernate.persister.walking.spi.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition; -import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.WalkingException; - import org.jboss.logging.Logger; /** @@ -73,6 +74,7 @@ * it is not, then depends on which property is used to apply this entity graph. * * @author Strong Liu + * @author Brett Meyer */ public abstract class AbstractEntityGraphVisitationStrategy extends AbstractLoadPlanBuildingAssociationVisitationStrategy { @@ -87,10 +89,14 @@ public abstract class AbstractEntityGraphVisitationStrategy protected static final FetchStrategy DEFAULT_EAGER = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); protected static final FetchStrategy DEFAULT_LAZY = new FetchStrategy( FetchTiming.DELAYED, FetchStyle.SELECT ); protected final LoadQueryInfluencers loadQueryInfluencers; - protected final ArrayDeque graphStack = new ArrayDeque(); - protected final ArrayDeque attributeStack = new ArrayDeque(); - //the attribute nodes defined in the current graph node (entity graph or subgraph) we're working on - protected Map attributeNodeImplementorMap = Collections.emptyMap(); + // Queue containing entity/sub graphs to be visited. + private final ArrayDeque graphStack = new ArrayDeque(); + // Queue containing attributes being visited, used eventually to determine the fetch strategy. + private final ArrayDeque attributeStack = new ArrayDeque(); + // Queue of maps containing the current graph node's attributes. Used for fast lookup, instead of iterating + // over graphStack.peekLast().attributeImplementorNodes(). + private final ArrayDeque> attributeMapStack + = new ArrayDeque>(); private EntityReturn rootEntityReturn; private final LockMode lockMode; @@ -113,16 +119,14 @@ public void finish() { super.finish(); graphStack.removeLast(); //applying a little internal stack checking - if ( !graphStack.isEmpty() || !attributeStack.isEmpty() || !attributeNodeImplementorMap.isEmpty() ) { + if ( !graphStack.isEmpty() || !attributeStack.isEmpty() || !attributeMapStack.isEmpty() ) { throw new WalkingException( "Internal stack error" ); } } @Override public void startingEntity(final EntityDefinition entityDefinition) { - //TODO check if the passed in entity definition is the same as the root entity graph (a.k.a they are came from same entity class)? - //this maybe the root entity graph or a sub graph. - attributeNodeImplementorMap = buildAttributeNodeMap(); + attributeMapStack.addLast( buildAttributeNodeMap() ); super.startingEntity( entityDefinition ); } @@ -144,7 +148,7 @@ protected Map buildAttributeNodeMap() { @Override public void finishingEntity(final EntityDefinition entityDefinition) { - attributeNodeImplementorMap = Collections.emptyMap(); + attributeMapStack.removeLast(); super.finishingEntity( entityDefinition ); } @@ -161,12 +165,13 @@ public void finishingEntity(final EntityDefinition entityDefinition) { */ @Override public boolean startingAttribute(AttributeDefinition attributeDefinition) { + Map attributeMap = attributeMapStack.peekLast(); final String attrName = attributeDefinition.getName(); AttributeNodeImplementor attributeNode = NON_EXIST_ATTRIBUTE_NODE; GraphNodeImplementor subGraphNode = NON_EXIST_SUBGRAPH_NODE; //the attribute is in the EntityGraph, so, let's continue - if ( attributeNodeImplementorMap.containsKey( attrName ) ) { - attributeNode = attributeNodeImplementorMap.get( attrName ); + if ( attributeMap.containsKey( attrName ) ) { + attributeNode = attributeMap.get( attrName ); //here we need to check if there is a subgraph (or sub key graph if it is an indexed attribute ) Map subGraphs = attributeNode.getSubgraphs(); Class javaType = attributeDefinition.getType().getReturnedClass(); @@ -188,45 +193,18 @@ public void finishingAttribute(final AttributeDefinition attributeDefinition) { super.finishingAttribute( attributeDefinition ); } - @Override - protected boolean handleAssociationAttribute( - final AssociationAttributeDefinition attributeDefinition) { - return super.handleAssociationAttribute( attributeDefinition ); - } - - @Override - protected boolean handleCompositeAttribute( - final AttributeDefinition attributeDefinition) { - return super.handleCompositeAttribute( attributeDefinition ); - } - - - @Override - public void startingComposite(final CompositionDefinition compositionDefinition) { - super.startingComposite( compositionDefinition ); - } - - - @Override - public void finishingComposite(final CompositionDefinition compositionDefinition) { - super.finishingComposite( compositionDefinition ); - } - - - @Override - public void startingCollection(final CollectionDefinition collectionDefinition) { - super.startingCollection( collectionDefinition ); - } - - @Override - public void finishingCollection(final CollectionDefinition collectionDefinition) { - super.finishingCollection( collectionDefinition ); - } - @Override public void startingCollectionElements( final CollectionElementDefinition elementDefinition) { + AttributeNodeImplementor attributeNode = attributeStack.peekLast(); + GraphNodeImplementor subGraphNode = NON_EXIST_SUBGRAPH_NODE; + Map subGraphs = attributeNode.getSubgraphs(); + Class javaType = elementDefinition.getType().getReturnedClass(); + if ( !subGraphs.isEmpty() && subGraphs.containsKey( javaType ) ) { + subGraphNode = (GraphNodeImplementor) subGraphs.get( javaType ); + } + graphStack.addLast( subGraphNode ); super.startingCollectionElements( elementDefinition ); } @@ -234,6 +212,7 @@ public void startingCollectionElements( public void finishingCollectionElements( final CollectionElementDefinition elementDefinition) { super.finishingCollectionElements( elementDefinition ); + graphStack.removeLast(); } @@ -354,5 +333,30 @@ public List> attributeImplementorNodes() { public List> attributeNodes() { return Collections.emptyList(); } + + @Override + public boolean containsAttribute(String name) { + return false; + } }; + + @Override + public void foundCircularAssociation(AssociationAttributeDefinition attributeDefinition) { + final FetchStrategy fetchStrategy = determineFetchStrategy( attributeDefinition ); + if ( fetchStrategy.getStyle() != FetchStyle.JOIN ) { + return; // nothing to do + } + + // Bi-directional association & the owning side was already visited. If the current attribute node refers + // to it, fetch. + // ENTITY nature handled by super. + final GraphNodeImplementor graphNode = graphStack.peekLast(); + if ( attributeDefinition.getAssociationNature() == AssociationAttributeDefinition.AssociationNature.COLLECTION + && ! graphNode.equals( NON_EXIST_SUBGRAPH_NODE) + && graphNode.containsAttribute( attributeDefinition.getName() )) { + currentSource().buildCollectionAttributeFetch( attributeDefinition, fetchStrategy ); + } + + super.foundCircularAssociation( attributeDefinition ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractLoadPlanBuildingAssociationVisitationStrategy.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractLoadPlanBuildingAssociationVisitationStrategy.java index 55cc246cef3e..1cb48f09faf9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractLoadPlanBuildingAssociationVisitationStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/AbstractLoadPlanBuildingAssociationVisitationStrategy.java @@ -138,7 +138,7 @@ private ExpandingFetchSource popFromStack() { return last; } - private ExpandingFetchSource currentSource() { + protected ExpandingFetchSource currentSource() { return fetchSourceStack.peekFirst(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadPlanBasedLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadPlanBasedLoader.java index cf7fab193c02..e8b155e2e5c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadPlanBasedLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadPlanBasedLoader.java @@ -157,6 +157,7 @@ public int[] getNamedParameterLocations(String name) { wrapper.getResultSet(), wrapper.getStatement() ); + session.getTransactionCoordinator().getJdbcCoordinator().release( wrapper.getStatement() ); } persistenceContext.afterLoad(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/EntityLoadQueryDetails.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/EntityLoadQueryDetails.java index 9f05f2a5db06..befc8906cf34 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/EntityLoadQueryDetails.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/EntityLoadQueryDetails.java @@ -131,7 +131,7 @@ protected void applyRootReturnTableFragments(SelectStatementBuilder select) { } else if ( getQueryBuildingParameters().getLockMode() != null ) { fromTableFragment = getSessionFactory().getDialect().appendLockHint( - getQueryBuildingParameters().getLockMode(), + getQueryBuildingParameters().getLockOptions(), outerJoinLoadable.fromTableFragment( rootAlias ) ); select.setLockMode( getQueryBuildingParameters().getLockMode() ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/LoadQueryJoinAndFetchProcessor.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/LoadQueryJoinAndFetchProcessor.java index 3b2d05c3b6f9..8153255da0cf 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/LoadQueryJoinAndFetchProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/LoadQueryJoinAndFetchProcessor.java @@ -571,7 +571,7 @@ private void processCollectionFetch( ); // add SQL ORDER-BY fragments - final String manyToManyOrdering = queryableCollection.getManyToManyOrderByString( collectionTableAlias ); + final String manyToManyOrdering = queryableCollection.getManyToManyOrderByString( elementTableAlias ); if ( StringHelper.isNotEmpty( manyToManyOrdering ) ) { selectStatementBuilder.appendOrderByFragment( manyToManyOrdering ); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/query/internal/SelectStatementBuilder.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/query/internal/SelectStatementBuilder.java index 834e6d970b34..cbddf7c5da23 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/query/internal/SelectStatementBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/query/internal/SelectStatementBuilder.java @@ -125,10 +125,10 @@ public void appendRestrictions(String restrictions) { private String cleanRestrictions(String restrictions) { restrictions = restrictions.trim(); - if ( restrictions.startsWith( "and" ) ) { + if ( restrictions.startsWith( "and " ) ) { restrictions = restrictions.substring( 4 ); } - if ( restrictions.endsWith( "and" ) ) { + if ( restrictions.endsWith( " and" ) ) { restrictions = restrictions.substring( 0, restrictions.length()-4 ); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java index 6beab81c011c..8b75a28bb75a 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java @@ -523,14 +523,14 @@ public ExecuteUpdateResultCheckStyle getCustomSQLDeleteAllCheckStyle() { } public void addFilter(String name, String condition, boolean autoAliasInjection, java.util.Map aliasTableMap, java.util.Map aliasEntityMap) { - filters.add(new FilterConfiguration(name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap, null)); + filters.add(new FilterConfiguration( name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap ) ); } public java.util.List getFilters() { return filters; } public void addManyToManyFilter(String name, String condition, boolean autoAliasInjection, java.util.Map aliasTableMap, java.util.Map aliasEntityMap) { - manyToManyFilters.add(new FilterConfiguration(name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap, null)); + manyToManyFilters.add(new FilterConfiguration( name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap ) ); } public java.util.List getManyToManyFilters() { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Component.java b/hibernate-core/src/main/java/org/hibernate/mapping/Component.java index 1495f6be43c3..c3984810c862 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Component.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Component.java @@ -22,6 +22,7 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.mapping; + import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -40,9 +41,7 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.JoinedIterator; import org.hibernate.property.Setter; -import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.type.Type; -import org.hibernate.type.TypeFactory; /** * The mapping for a component, composite element, @@ -177,9 +176,10 @@ public void setDynamic(boolean dynamic) { @Override public Type getType() throws MappingException { // TODO : temporary initial step towards HHH-1907 - final ComponentMetamodel metamodel = new ComponentMetamodel( this ); - final TypeFactory factory = getMappings().getTypeResolver().getTypeFactory(); - return isEmbedded() ? factory.embeddedComponent( metamodel ) : factory.component( metamodel ); +// final ComponentMetamodel metamodel = new ComponentMetamodel( this ); +// final TypeFactory factory = getMappings().getTypeResolver().getTypeFactory(); +// return isEmbedded() ? factory.embeddedComponent( metamodel ) : factory.component( metamodel ); + return null; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java index 52565d068b36..d66b74d403bf 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java @@ -239,7 +239,7 @@ public Iterator getDirectSubclasses() { } public void addProperty(Property p) { - properties.add(p); + properties.add( p ); declaredProperties.add(p); p.setPersistentClass(this); } @@ -879,7 +879,7 @@ public Iterator getDeclaredPropertyIterator() { } public void addMappedsuperclassProperty(Property p) { - properties.add(p); + properties.add( p ); p.setPersistentClass(this); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java index 00aa77fcbbc3..043ea9c5c19d 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java @@ -423,8 +423,6 @@ public Iterator sqlAlterStrings(Dialect dialect, Mapping p, TableMetadata tableI String keyName = Constraint.generateName( "UK_", this, column ); UniqueKey uk = getOrCreateUniqueKey( keyName ); uk.addColumn( column ); - alter.append( dialect.getUniqueDelegate() - .getColumnDefinitionUniquenessFragment( column ) ); } if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) { @@ -528,8 +526,6 @@ public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog, String keyName = Constraint.generateName( "UK_", this, col ); UniqueKey uk = getOrCreateUniqueKey( keyName ); uk.addColumn( col ); - buf.append( dialect.getUniqueDelegate() - .getColumnDefinitionUniquenessFragment( col ) ); } if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) { @@ -553,8 +549,6 @@ public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog, .append( getPrimaryKey().sqlConstraintString( dialect ) ); } - buf.append( dialect.getUniqueDelegate().getTableCreationUniqueConstraintsFragment( this ) ); - if ( dialect.supportsTableCheck() ) { Iterator chiter = checkConstraints.iterator(); while ( chiter.hasNext() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java index 2cfb385bc5ad..c923a365082c 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java @@ -27,7 +27,6 @@ import java.util.Map; import org.hibernate.dialect.Dialect; -import org.hibernate.engine.spi.Mapping; import org.hibernate.internal.util.StringHelper; /** @@ -44,27 +43,10 @@ public String sqlConstraintString( String constraintName, String defaultCatalog, String defaultSchema) { -// return dialect.getUniqueDelegate().uniqueConstraintSql( this ); - // Not used. + // Not used -- generated by StandardUniqueKeyExporter return ""; } - @Override - public String sqlCreateString(Dialect dialect, Mapping p, - String defaultCatalog, String defaultSchema) { - return dialect.getUniqueDelegate().getAlterTableToAddUniqueKeyCommand( - this, defaultCatalog, defaultSchema - ); - } - - @Override - public String sqlDropString(Dialect dialect, String defaultCatalog, - String defaultSchema) { - return dialect.getUniqueDelegate().getAlterTableToDropUniqueKeyCommand( - this, defaultCatalog, defaultSchema - ); - } - public void addColumn(Column column, String order) { addColumn( column ); if ( StringHelper.isNotEmpty( order ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java index ce58902d7d51..d210ac986c43 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/Metadata.java @@ -21,80 +21,80 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ - package org.hibernate.metamodel; +import java.util.Collection; import java.util.Map; -import javax.persistence.SharedCacheMode; +import java.util.UUID; + +import javax.persistence.NamedStoredProcedureQuery; import org.hibernate.SessionFactory; -import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.engine.ResultSetMappingDefinition; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.NamedQueryDefinition; import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.relational.Identifier; /** * @author Steve Ebersole */ public interface Metadata { /** - * Exposes the options used to produce a {@link Metadata} instance. + * Get the builder for {@link SessionFactory} instances based on this metamodel, + * + * @return The builder for {@link SessionFactory} instances. */ - public static interface Options { - public StandardServiceRegistry getServiceRegistry(); - - public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder(); - public NamingStrategy getNamingStrategy(); - public SharedCacheMode getSharedCacheMode(); - public AccessType getDefaultAccessType(); - public boolean useNewIdentifierGenerators(); - public boolean isGloballyQuotedIdentifiers(); - public String getDefaultSchemaName(); - public String getDefaultCatalogName(); - } - - public Options getOptions(); - - public SessionFactoryBuilder getSessionFactoryBuilder(); + SessionFactoryBuilder getSessionFactoryBuilder(); - public SessionFactory buildSessionFactory(); + /** + * Short-hand form of building a {@link SessionFactory} through the builder without any additional + * option overrides. + * + * @return THe built SessionFactory. + */ + SessionFactory buildSessionFactory(); - public Iterable getEntityBindings(); + /** + * Gets the {@link UUID} for this metamodel. + * + * @return the UUID. + */ + UUID getUUID(); - public EntityBinding getEntityBinding(String entityName); + EntityBinding getEntityBinding(String entityName); /** * Get the "root" entity binding * @param entityName * @return the "root entity binding; simply returns entityBinding if it is the root entity binding */ - public EntityBinding getRootEntityBinding(String entityName); - - public Iterable getCollectionBindings(); - - public TypeDef getTypeDefinition(String name); - - public Iterable getTypeDefinitions(); - - public Iterable getFilterDefinitions(); - - public Iterable getNamedQueryDefinitions(); - - public Iterable getNamedNativeQueryDefinitions(); - - public Iterable getResultSetMappingDefinitions(); - - public Iterable> getImports(); - - public Iterable getFetchProfiles(); - - public IdGenerator getIdGenerator(String name); + EntityBinding getRootEntityBinding(String entityName); + IdentifierGeneratorDefinition getIdGenerator(String name); + boolean hasTypeDefinition(String name); + TypeDefinition getTypeDefinition(String name); + + Iterable getCollectionBindings(); + Iterable getEntityBindings(); + Iterable getTypeDefinitions(); + Iterable getFetchProfiles(); + + Map getSecondaryTables(); + Map getFilterDefinitions(); + Map getNamedEntityGraphs(); + + Map getImports(); + + NamedSQLQueryDefinition getNamedNativeQuery(String name); + Iterable getNamedQueryDefinitions(); + Iterable getNamedNativeQueryDefinitions(); + Collection getNamedStoredProcedureQueryDefinitions(); + Map getResultSetMappingDefinitions(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java index 1295a80923f2..c8ed401fefb7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataBuilder.java @@ -25,23 +25,216 @@ import javax.persistence.SharedCacheMode; +import org.hibernate.boot.spi.CacheRegionDefinition; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.spi.PersistentAttributeMemberResolver; +import org.hibernate.metamodel.spi.TypeContributor; +import org.hibernate.type.BasicType; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; + +import org.jboss.jandex.IndexView; + +import org.xml.sax.EntityResolver; /** + * Contract for specifying various overrides to be used in metamodel building. + * * @author Steve Ebersole * @author Hardy Ferentschik */ public interface MetadataBuilder { + /** + * Specify a specific NamingStrategy to use in building the metamodel. + * + * @param namingStrategy The naming strategy to use. + * + * @return {@code this}, for method chaining + */ public MetadataBuilder with(NamingStrategy namingStrategy); + /** + * Specify a specific XML EntityResolver to use in building the metamodel. + * + * @param entityResolver The entity resolver to use. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(EntityResolver entityResolver); + + /** + * Specify the order in which to process metadata sources. + * + * @param metadataSourceProcessingOrder The order. + * + * @return {@code this}, for method chaining + */ public MetadataBuilder with(MetadataSourceProcessingOrder metadataSourceProcessingOrder); + /** + * Specify the second-level cache mode to be used. This is the cache mode in terms of whether or + * not to cache. + * + * @param cacheMode The cache mode. + * + * @return {@code this}, for method chaining + * + * @see #with(org.hibernate.cache.spi.access.AccessType) + */ public MetadataBuilder with(SharedCacheMode cacheMode); + /** + * Specify the second-level access-type to be used by default for entities and collections that define second-level + * caching, but do not specify a granular access-type. + * + * @param accessType The access-type to use as default. + * + * @return {@code this}, for method chaining + * + * @see #with(javax.persistence.SharedCacheMode) + */ public MetadataBuilder with(AccessType accessType); + /** + * Allows specifying a specific Jandex index to use for reading annotation information. + *

    + * It is important to understand that if a Jandex index is passed in, it is expected that + * this Jandex index already contains all entries for all classes. No additional indexing will be + * done in this case. + * + * @param jandexView The Jandex index to use. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(IndexView jandexView); + + /** + * Should the new (well "new" since 3.2) identifier generators be used for + * {@link javax.persistence.GenerationType#SEQUENCE}, + * {@link javax.persistence.GenerationType#IDENTITY}, + * {@link javax.persistence.GenerationType#TABLE} and + * {@link javax.persistence.GenerationType#AUTO} handling? + * + * @param enabled {@code true} says to use the new generator mappings; {@code false} says to use the legacy + * generator mappings. + * + * @return {@code this}, for method chaining + */ public MetadataBuilder withNewIdentifierGeneratorsEnabled(boolean enabled); + /** + * Should we process or ignore explicitly defined discriminators in the case + * of joined-subclasses. The legacy behavior of Hibernate was to ignore the + * discriminator annotations because Hibernate (unlike some providers) does + * not need discriminators to determine the concrete type when it comes to + * joined inheritance. However, for portability reasons we do now allow using + * explicit discriminators along with joined inheritance. It is configurable + * though to support legacy apps. + * + * @param enabled Should processing (not ignoring) explicit discriminators be + * enabled? + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder withExplicitDiscriminatorsForJoinedSubclassSupport(boolean enabled); + + /** + * Similarly to {@link #withExplicitDiscriminatorsForJoinedSubclassSupport}, + * but here how should we treat joined inheritance when there is no explicitly + * defined discriminator annotations? If enabled, we will handle joined + * inheritance with no explicit discriminator annotations by implicitly + * creating one (following the JPA implicit naming rules). + *

    + * Again the premise here is JPA portability, bearing in mind that some + * JPA provider need these discriminators. + * + * @param enabled Should we implicitly create discriminator for joined + * inheritance if one is not explicitly mentioned? + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder withImplicitDiscriminatorsForJoinedSubclassSupport(boolean enabled); + + /** + * Specify an additional or overridden basic type mapping. + * + * @param type The type addition or override. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(BasicType type); + + /** + * Register an additional or overridden custom type mapping. + * + * @param type The custom type + * @param keys The keys under which to register the custom type. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(UserType type, String[] keys); + + /** + * Register an additional or overridden composite custom type mapping. + * + * @param type The composite custom type + * @param keys The keys under which to register the composite custom type. + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(CompositeUserType type, String[] keys); + + /** + * Apply an explicit TypeContributor (implicit application via ServiceLoader will still happen too) + * + * @param typeContributor The contributor to apply + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(TypeContributor typeContributor); + + /** + * Apply a CacheRegionDefinition to be applied to an entity, collection or query while building the + * Metadata object. + * + * @param cacheRegionDefinition The cache region definition to apply + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(CacheRegionDefinition cacheRegionDefinition); + + /** + * Apply a ClassLoader for use while building the Metadata. + *

    + * Ideally we should avoid accessing ClassLoaders when perform 1st phase of bootstrap. This + * is a ClassLoader that can be used in cases when we have to. IN EE managed environments, this + * is the ClassLoader mandated by + * {@link javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader()}. This ClassLoader + * is thrown away by the container afterwards. The idea being that the Class can still be enhanced + * in the application ClassLoader. In other environments, pass a ClassLoader that performs the + * same function if desired. + * + * @param tempClassLoader ClassLoader for use during building the Metadata + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(ClassLoader tempClassLoader); + + /** + * Specify the resolve to be used in identifying the backing members of a + * persistent attributes. + * + * @param resolver The resolver to use + * + * @return {@code this}, for method chaining + */ + public MetadataBuilder with(PersistentAttributeMemberResolver resolver); + + /** + * Actually build the metamodel + * + * @return The built metadata. + */ public Metadata build(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java index 01c2dbd63ffb..691a56970f42 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java @@ -26,67 +26,101 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.Serializable; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.jar.JarFile; import java.util.zip.ZipEntry; +import javax.persistence.AttributeConverter; +import org.hibernate.HibernateException; import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.EJB3DTDEntityResolver; -import org.hibernate.cfg.EJB3NamingStrategy; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.SourceType; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.MappingNotFoundException; -import org.hibernate.metamodel.source.internal.JaxbHelper; -import org.hibernate.metamodel.source.internal.MetadataBuilderImpl; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.SerializationHelper; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.MetadataBuilderImpl; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbConverter; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddable; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListener; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMappedSuperclass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitDefaults; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinedSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbUnionSubclassElement; +import org.hibernate.metamodel.source.spi.InvalidMappingException; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.MappingNotFoundException; import org.hibernate.service.ServiceRegistry; - +import org.hibernate.type.SerializationException; +import org.hibernate.xml.internal.jaxb.MappingXmlBinder; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; +import org.jboss.jandex.Type; import org.jboss.logging.Logger; import org.w3c.dom.Document; -import org.xml.sax.EntityResolver; /** + * Entry point into working with sources of metadata information ({@code hbm.xml}, annotations). Tell Hibernate + * about sources and then call {@link #buildMetadata()}. + * * @author Steve Ebersole + * @author Brett Meyer */ public class MetadataSources { - private static final Logger LOG = Logger.getLogger( MetadataSources.class ); + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( MetadataSources.class ); private final ServiceRegistry serviceRegistry; - - private List jaxbRootList = new ArrayList(); + private final MappingXmlBinder jaxbProcessor; + private List bindResultList = new ArrayList(); private LinkedHashSet> annotatedClasses = new LinkedHashSet>(); + private LinkedHashSet annotatedClassNames = new LinkedHashSet(); private LinkedHashSet annotatedPackages = new LinkedHashSet(); - private final JaxbHelper jaxbHelper; + private List> converterClasses; - private final EntityResolver entityResolver; - private final NamingStrategy namingStrategy; + private boolean hasOrmXmlJaxbRoots; - private final MetadataBuilderImpl metadataBuilder; - - public MetadataSources(ServiceRegistry serviceRegistry) { - this( serviceRegistry, EJB3DTDEntityResolver.INSTANCE, EJB3NamingStrategy.INSTANCE ); + public MetadataSources() { + this( new BootstrapServiceRegistryBuilder().build() ); } - public MetadataSources(ServiceRegistry serviceRegistry, EntityResolver entityResolver, NamingStrategy namingStrategy) { - this.serviceRegistry = serviceRegistry; - this.entityResolver = entityResolver; - this.namingStrategy = namingStrategy; - - this.jaxbHelper = new JaxbHelper( this ); - this.metadataBuilder = new MetadataBuilderImpl( this ); - + /** + * Create a metadata sources using the specified service registry. + * + * @param serviceRegistry The service registry to use. + */ + public MetadataSources(ServiceRegistry serviceRegistry) { // service registry really should be either BootstrapServiceRegistry or StandardServiceRegistry type... if ( ! isExpectedServiceRegistryType( serviceRegistry ) ) { LOG.debugf( @@ -95,6 +129,8 @@ public MetadataSources(ServiceRegistry serviceRegistry, EntityResolver entityRes serviceRegistry.getClass().getName() ); } + this.serviceRegistry = serviceRegistry; + this.jaxbProcessor = new MappingXmlBinder( serviceRegistry ); } protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRegistry) { @@ -102,8 +138,8 @@ protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRe || StandardServiceRegistry.class.isInstance( serviceRegistry ); } - public List getJaxbRootList() { - return jaxbRootList; + public List getBindResultList() { + return bindResultList; } public Iterable getAnnotatedPackages() { @@ -114,12 +150,12 @@ public Iterable> getAnnotatedClasses() { return annotatedClasses; } - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; + public Iterable getAnnotatedClassNames() { + return annotatedClassNames; } - public NamingStrategy getNamingStrategy() { - return namingStrategy; + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; } /** @@ -167,6 +203,18 @@ public MetadataSources addAnnotatedClass(Class annotatedClass) { return this; } + /** + * Read metadata from the annotations attached to the given class. + * + * @param annotatedClassName The name of a class containing annotations + * + * @return this (for method chaining) + */ + public MetadataSources addAnnotatedClassName(String annotatedClassName) { + annotatedClassNames.add( annotatedClassName ); + return this; + } + /** * Read package-level metadata. * @@ -209,11 +257,14 @@ private ClassLoaderService classLoaderService() { return serviceRegistry.getService( ClassLoaderService.class ); } - private JaxbRoot add(InputStream inputStream, Origin origin, boolean close) { + private BindResult add(InputStream inputStream, Origin origin, boolean close) { try { - JaxbRoot jaxbRoot = jaxbHelper.unmarshal( inputStream, origin ); - jaxbRootList.add( jaxbRoot ); - return jaxbRoot; + BindResult bindResult = jaxbProcessor.bind( inputStream, origin ); + addJaxbRoot( bindResult ); + return bindResult; + } + catch ( Exception e ) { + throw new InvalidMappingException( origin, e ); } finally { if ( close ) { @@ -234,7 +285,10 @@ private JaxbRoot add(InputStream inputStream, Origin origin, boolean close) { * @param entityClass The mapped class. Cannot be {@code null} null. * * @return this (for method chaining purposes) + * + * @deprecated hbm.xml is a legacy mapping format now considered deprecated. */ + @Deprecated public MetadataSources addClass(Class entityClass) { if ( entityClass == null ) { throw new IllegalArgumentException( "The specified class cannot be null" ); @@ -245,6 +299,21 @@ public MetadataSources addClass(Class entityClass) { return this; } + /** + * Adds an AttributeConverter by class. + * + * @param converterClass The AttributeConverter class. + * + * @return this (for method chaining purposes) + */ + public MetadataSources addAttributeConverter(Class converterClass) { + if ( converterClasses == null ) { + converterClasses = new ArrayList>(); + } + converterClasses.add( converterClass ); + return this; + } + /** * Read mappings from a particular XML file * @@ -288,7 +357,7 @@ public MetadataSources addFile(File file) { * @see #addCacheableFile(java.io.File) */ public MetadataSources addCacheableFile(String path) { - return this; // todo : implement method body + return addCacheableFile( new File( path ) ); } /** @@ -305,7 +374,72 @@ public MetadataSources addCacheableFile(String path) { * @return this (for method chaining purposes) */ public MetadataSources addCacheableFile(File file) { - return this; // todo : implement method body + Origin origin = new Origin( SourceType.FILE, file.getAbsolutePath() ); + File cachedFile = determineCachedDomFile( file ); + + try { + return addCacheableFileStrictly( file ); + } + catch ( SerializationException e ) { + LOG.unableToDeserializeCache( cachedFile.getName(), e ); + } + catch ( FileNotFoundException e ) { + LOG.cachedFileNotFound( cachedFile.getName(), e ); + } + + final FileInputStream inputStream; + try { + inputStream = new FileInputStream( file ); + } + catch ( FileNotFoundException e ) { + throw new MappingNotFoundException( origin ); + } + + LOG.readingMappingsFromFile( file.getPath() ); + BindResult metadataXml = add( inputStream, origin, true ); + + try { + LOG.debugf( "Writing cache file for: %s to: %s", file, cachedFile ); + SerializationHelper.serialize( ( Serializable ) metadataXml, new FileOutputStream( cachedFile ) ); + } + catch ( Exception e ) { + LOG.unableToWriteCachedFile( cachedFile.getName(), e.getMessage() ); + } + + return this; + } + + /** + * INTENDED FOR TESTSUITE USE ONLY! + *

    + * Much like {@link #addCacheableFile(File)} except that here we will fail immediately if + * the cache version cannot be found or used for whatever reason + * + * @param file The xml file, not the bin! + * + * @return The dom "deserialized" from the cached file. + * + * @throws SerializationException Indicates a problem deserializing the cached dom tree + * @throws FileNotFoundException Indicates that the cached file was not found or was not usable. + */ + public MetadataSources addCacheableFileStrictly(File file) throws SerializationException, FileNotFoundException { + File cachedFile = determineCachedDomFile( file ); + + final boolean useCachedFile = file.exists() + && cachedFile.exists() + && file.lastModified() < cachedFile.lastModified(); + + if ( ! useCachedFile ) { + throw new FileNotFoundException( "Cached file could not be found or could not be used" ); + } + + LOG.readingCachedMappings( cachedFile ); + addJaxbRoot( (BindResult) SerializationHelper.deserialize( new FileInputStream( cachedFile ) ) ); + return this; + } + + private File determineCachedDomFile(File xmlFile) { + return new File( xmlFile.getAbsolutePath() + ".bin" ); } /** @@ -316,7 +450,7 @@ public MetadataSources addCacheableFile(File file) { * @return this (for method chaining purposes) */ public MetadataSources addInputStream(InputStream xmlInputStream) { - add( xmlInputStream, new Origin( SourceType.INPUT_STREAM, "" ), false ); + add( xmlInputStream, new Origin( SourceType.INPUT_STREAM, Origin.UNKNOWN_FILE_PATH ), false ); return this; } @@ -349,12 +483,17 @@ public MetadataSources addURL(URL url) { * @return this (for method chaining purposes) */ public MetadataSources addDocument(Document document) { - final Origin origin = new Origin( SourceType.DOM, "" ); - JaxbRoot jaxbRoot = jaxbHelper.unmarshal( document, origin ); - jaxbRootList.add( jaxbRoot ); + final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH ); + BindResult bindResult = jaxbProcessor.bind( document, origin ); + addJaxbRoot( bindResult ); return this; } + private void addJaxbRoot(BindResult bindResult) { + hasOrmXmlJaxbRoots = hasOrmXmlJaxbRoots || JaxbEntityMappings.class.isInstance( bindResult.getRoot() ); + bindResultList.add( bindResult ); + } + /** * Read all mappings from a jar file. *

    @@ -412,14 +551,329 @@ public MetadataSources addJar(File jar) { */ public MetadataSources addDirectory(File dir) { File[] files = dir.listFiles(); - for ( File file : files ) { - if ( file.isDirectory() ) { - addDirectory( file ); - } - else if ( file.getName().endsWith( ".hbm.xml" ) ) { - addFile( file ); + if ( files != null && files.length > 0 ) { + for ( File file : files ) { + if ( file.isDirectory() ) { + addDirectory( file ); + } + else if ( file.getName().endsWith( ".hbm.xml" ) ) { + addFile( file ); + } } } return this; } + + public IndexView buildJandexView() { + return buildJandexView( false ); + } + + /** + * Create a Jandex IndexView from scratch given the sources information contained here. + * + * @param autoIndexMemberTypes Should the types of class members automatically be added to the built index? + * + * @return + */ + public IndexView buildJandexView(boolean autoIndexMemberTypes) { + return JandexIndexBuilder.process( autoIndexMemberTypes, this ); + } + + public static class JandexIndexBuilder { + private static final Logger log = Logger.getLogger( JandexIndexBuilder.class ); + + private final DotName OBJECT_DOT_NAME = DotName.createSimple( Object.class.getName() ); + + private final boolean autoIndexMemberTypes; + private final ClassLoaderService classLoaderService; + + private final Indexer indexer = new Indexer(); + private final Set processedClassNames = new HashSet(); + + private JandexIndexBuilder(boolean autoIndexMemberTypes, ServiceRegistry serviceRegistry) { + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + this.autoIndexMemberTypes = autoIndexMemberTypes; + } + + public static IndexView process(boolean autoIndexMemberTypes, MetadataSources sources) { + return new JandexIndexBuilder( autoIndexMemberTypes, sources.getServiceRegistry() ).process( sources ); + } + + private IndexView process(MetadataSources sources) { + // start off with any already-loaded Class references... + for ( Class clazz : sources.getAnnotatedClasses() ) { + indexLoadedClass( clazz ); + } + + if ( sources.converterClasses != null ) { + for ( Class converterClass : sources.converterClasses ) { + indexLoadedClass( converterClass ); + } + } + + for ( String className : sources.getAnnotatedClassNames() ) { + indexClassName( DotName.createSimple( className ) ); + } + + // add package-info from the configured packages + for ( String packageName : sources.getAnnotatedPackages() ) { + // older code seemed to simply ignore packages that did not have package-info, + // so do same + try { + indexResource( packageName.replace( '.', '/' ) + "/package-info.class" ); + } + catch (Exception e) { + log.debugf( "Skipping package [%s] which caused error indexing : %s", packageName, e.getMessage() ); + } + } + + // the classes referenced in any orm.xml bindings (unless it is "metadata complete") + for ( BindResult bindResult : sources.bindResultList ) { + if ( JaxbEntityMappings.class.isInstance( bindResult.getRoot() ) ) { + final JaxbEntityMappings ormXmlRoot = (JaxbEntityMappings) bindResult.getRoot(); + if ( !isMappingMetadataComplete( ormXmlRoot ) ) { + indexOrmXmlReferences( ormXmlRoot ); + } + } + } + + final Index jandexIndex = indexer.complete(); + if ( log.isTraceEnabled() ) { + jandexIndex.printSubclasses(); + jandexIndex.printAnnotations(); + } + return jandexIndex; + } + + private void indexLoadedClass(Class loadedClass) { + if ( loadedClass == null ) { + return; + } + + final DotName classDotName = DotName.createSimple( loadedClass.getName() ); + if ( !needsProcessing( classDotName ) ) { + return; + } + + // index super type first + indexLoadedClass( loadedClass.getSuperclass() ); + + // index any inner classes + for ( Class innerClass : loadedClass.getDeclaredClasses() ) { + indexLoadedClass( innerClass ); + } + + // then index the class itself + ClassInfo classInfo = indexResource( loadedClass.getName().replace( '.', '/' ) + ".class" ); + + if ( !autoIndexMemberTypes ) { + return; + } + + for ( Class fieldType : ReflectHelper.getMemberTypes( loadedClass ) ) { + if ( !fieldType.isPrimitive() && fieldType != Object.class ) { + indexLoadedClass( fieldType ); + } + } + + // Also check for classes within a @Target annotation. + // [steve] - not so sure about this. target would name an entity, which should be + // known to us somehow + for ( AnnotationInstance targetAnnotation : JandexHelper.getAnnotations( classInfo, HibernateDotNames.TARGET ) ) { + String targetClassName = targetAnnotation.value().asClass().name().toString(); + Class targetClass = classLoaderService.classForName( targetClassName ); + indexLoadedClass( targetClass ); + } + } + + + private boolean needsProcessing(DotName classDotName) { + if ( classDotName == null || OBJECT_DOT_NAME.equals( classDotName ) ) { + return false; + } + + if ( processedClassNames.contains( classDotName ) ) { + return false; + } + + processedClassNames.add( classDotName ); + return true; + } + + private ClassInfo indexResource(String resourceName) { + final URL resourceUrl = classLoaderService.locateResource( resourceName ); + + if ( resourceUrl == null ) { + throw new IllegalArgumentException( "Could not locate resource [" + resourceName + "]" ); + } + + try { + final InputStream stream = resourceUrl.openStream(); + try { + final ClassInfo classInfo = indexer.index( stream ); + furtherProcess( classInfo ); + return classInfo; + } + catch ( IOException e ) { + throw new HibernateException( "Unable to index from resource stream [" + resourceName + "]", e ); + } + finally { + try { + stream.close(); + } + catch ( IOException e ) { + log.debug( "Unable to close resource stream [" + resourceName + "] : " + e.getMessage() ); + } + } + } + catch ( IOException e ) { + throw new HibernateException( "Unable to open input stream for resource [" + resourceName + "]", e ); + } + } + + private void furtherProcess(ClassInfo classInfo) { + final List entityListenerAnnotations = classInfo.annotations().get( JPADotNames.ENTITY_LISTENERS ); + if ( entityListenerAnnotations != null ) { + for ( AnnotationInstance entityListenerAnnotation : entityListenerAnnotations ) { + final Type[] entityListenerClassTypes = entityListenerAnnotation.value().asClassArray(); + for ( Type entityListenerClassType : entityListenerClassTypes ) { + indexClassName( entityListenerClassType.name() ); + } + } + } + + // todo : others? + } + + private void indexClassName(DotName classDotName) { + if ( !needsProcessing( classDotName ) ) { + return; + } + + ClassInfo classInfo = indexResource( classDotName.toString().replace( '.', '/' ) + ".class" ); + if ( classInfo.superName() != null ) { + indexClassName( classInfo.superName() ); + } + } + + private void indexHbmReferences(JaxbHibernateMapping hbmRoot) { + final String packageName = hbmRoot.getPackage(); + + for ( JaxbClassElement hbmRootClass : hbmRoot.getClazz() ) { + if ( StringHelper.isNotEmpty( hbmRootClass.getName() ) ) { + indexClassName( toDotName( hbmRootClass.getName(), packageName ) ); + + for ( JaxbSubclassElement hbmSubclassElement : hbmRootClass.getSubclass() ) { + processHbmSubclass( hbmSubclassElement, packageName ); + } + + for ( JaxbJoinedSubclassElement hbmJoinedSubclass : hbmRootClass.getJoinedSubclass() ) { + processHbmJoinedSubclass( hbmJoinedSubclass, packageName ); + } + + for ( JaxbUnionSubclassElement hbmUnionSubclass : hbmRoot.getUnionSubclass() ) { + processHbmUnionSubclass( hbmUnionSubclass, packageName ); + } + } + } + + for ( JaxbSubclassElement hbmSubclassElement : hbmRoot.getSubclass() ) { + if ( StringHelper.isNotEmpty( hbmSubclassElement.getName() ) ) { + processHbmSubclass( hbmSubclassElement, packageName ); + } + } + + for ( JaxbJoinedSubclassElement hbmJoinedSubclass : hbmRoot.getJoinedSubclass() ) { + if ( StringHelper.isNotEmpty( hbmJoinedSubclass.getName() ) ) { + processHbmJoinedSubclass( hbmJoinedSubclass, packageName ); + } + } + + for ( JaxbUnionSubclassElement hbmUnionSubclass : hbmRoot.getUnionSubclass() ) { + if ( StringHelper.isNotEmpty( hbmUnionSubclass.getName() ) ) { + processHbmUnionSubclass( hbmUnionSubclass, packageName ); + } + } + } + + private DotName toDotName(String className, String packageName) { + if ( StringHelper.isNotEmpty( packageName ) ) { + if ( !className.contains( "." ) ) { + return DotName.createSimple( packageName + '.' + className ); + } + } + + return DotName.createSimple( className ); + } + + private void processHbmSubclass(JaxbSubclassElement hbmSubclassElement, String packageName) { + indexClassName( toDotName( hbmSubclassElement.getName(), packageName ) ); + + for ( JaxbSubclassElement hbmSubclassElement2 : hbmSubclassElement.getSubclass() ) { + processHbmSubclass( hbmSubclassElement2, packageName ); + } + } + + private void processHbmJoinedSubclass(JaxbJoinedSubclassElement hbmJoinedSubclass, String packageName) { + indexClassName( toDotName( hbmJoinedSubclass.getName(), packageName ) ); + + for ( JaxbJoinedSubclassElement hbmJoinedSubclass2 : hbmJoinedSubclass.getJoinedSubclass() ) { + processHbmJoinedSubclass( hbmJoinedSubclass2, packageName ); + } + } + + private void processHbmUnionSubclass(JaxbUnionSubclassElement hbmUnionSubclass, String packageName) { + indexClassName( toDotName( hbmUnionSubclass.getName(), packageName ) ); + + for ( JaxbUnionSubclassElement hbmUnionSubclass2 : hbmUnionSubclass.getUnionSubclass() ) { + processHbmUnionSubclass( hbmUnionSubclass2, packageName ); + } + } + + private boolean isMappingMetadataComplete(JaxbEntityMappings ormXmlRoot) { + return ormXmlRoot.getPersistenceUnitMetadata() != null + && ormXmlRoot.getPersistenceUnitMetadata().getXmlMappingMetadataComplete() != null; + } + + private void indexOrmXmlReferences(JaxbEntityMappings ormXmlRoot) { + final String packageName = ormXmlRoot.getPackage(); + + final JaxbPersistenceUnitMetadata puMetadata = ormXmlRoot.getPersistenceUnitMetadata(); + if ( puMetadata != null ) { + final JaxbPersistenceUnitDefaults puDefaults = puMetadata.getPersistenceUnitDefaults(); + if ( puDefaults != null ) { + indexEntityListeners( puDefaults.getEntityListeners(), packageName ); + } + } + + for ( JaxbConverter jaxbConverter : ormXmlRoot.getConverter() ) { + indexClassName( toDotName( jaxbConverter.getClazz(), packageName ) ); + } + + for ( JaxbEmbeddable jaxbEmbeddable : ormXmlRoot.getEmbeddable() ) { + indexClassName( toDotName( jaxbEmbeddable.getClazz(), packageName ) ); + } + + for ( JaxbMappedSuperclass jaxbMappedSuperclass : ormXmlRoot.getMappedSuperclass() ) { + indexClassName( toDotName( jaxbMappedSuperclass.getClazz(), packageName ) ); + } + + for ( JaxbEntity jaxbEntity : ormXmlRoot.getEntity() ) { + indexClassName( toDotName( jaxbEntity.getClazz(), packageName ) ); + indexEntityListeners( jaxbEntity.getEntityListeners(), packageName ); + } + } + + private void indexEntityListeners(JaxbEntityListeners listeners, String packageName) { + if ( listeners == null ) { + return; + } + + for ( JaxbEntityListener listener : listeners.getEntityListener() ) { + if ( StringHelper.isNotEmpty( listener.getClazz() ) ) { + indexClassName( toDotName( listener.getClazz(), packageName ) ); + } + } + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/NamedStoredProcedureQueryDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/NamedStoredProcedureQueryDefinition.java new file mode 100644 index 000000000000..e4dd140b4493 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/NamedStoredProcedureQueryDefinition.java @@ -0,0 +1,204 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.ParameterMode; + +import org.hibernate.MappingException; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.procedure.spi.ParameterStrategy; + +/** + * Models the information about a {@link javax.persistence.NamedStoredProcedureQuery} + * + * @author Steve Ebersole + */ +public class NamedStoredProcedureQueryDefinition { + private final String name; + private final String procedureName; + + private final ParameterStrategy parameterStrategy; + private final List parameters; + + private final Map queryHints; + + private final List classNames; + private final List resultSetMappingNames; + + private NamedStoredProcedureQueryDefinition( + String name, + String procedureName, + ParameterStrategy parameterStrategy, + List parameters, + Map queryHints, + List classNames, + List resultSetMappingNames) { + if ( name == null ) { + throw new IllegalArgumentException( "Name cannot be null" ); + } + if ( procedureName == null ) { + throw new IllegalArgumentException( "Procedure-name cannot be null" ); + } + final boolean specifiesResultClasses = classNames.size() > 0; + final boolean specifiesResultSetMappings = resultSetMappingNames.size() > 0; + + if ( specifiesResultClasses && specifiesResultSetMappings ) { + throw new MappingException( + String.format( + "NamedStoredProcedureQuery [" + name + "] specified both resultClasses and resultSetMappings", + name + ) + ); + } + + this.name = name; + this.procedureName = procedureName; + this.parameterStrategy = parameterStrategy; + this.parameters = Collections.unmodifiableList( parameters ); + this.queryHints = Collections.unmodifiableMap( queryHints ); + this.classNames = Collections.unmodifiableList( classNames ); + this.resultSetMappingNames = Collections.unmodifiableList( resultSetMappingNames ); + } + + public String getName() { + return name; + } + + public String getProcedureName() { + return procedureName; + } + + public ParameterStrategy getParameterStrategy() { + return parameterStrategy; + } + + public List getParameters() { + return parameters; + } + + public Map getQueryHints() { + return queryHints; + } + + public List getClassNames() { + return classNames; + } + + public List getResultSetMappingNames() { + return resultSetMappingNames; + } + + public static class Parameter { + private final String name; + private final ParameterMode mode; + private final String javaType; + + private Parameter(String name, ParameterMode mode, String javaType) { + this.name = name; + this.mode = mode; + this.javaType = javaType; + } + + public String getName() { + return name; + } + + public ParameterMode getMode() { + return mode; + } + + public String getJavaType() { + return javaType; + } + } + + public static class Builder { + private final String name; + private final String procedureName; + private final List parameters = new ArrayList(); + private final Map queryHints = new HashMap(); + private final List classNames = new ArrayList(); + private final List resultSetMappingNames = new ArrayList(); + + private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN; + + public Builder(String name, String procedureName) { + this.name = name; + this.procedureName = procedureName; + } + + public void addParameter(String name, ParameterMode mode, String javaType) { + final ParameterStrategy incomingParameterStrategy; + if ( StringHelper.isNotEmpty( name ) ) { + incomingParameterStrategy = ParameterStrategy.NAMED; + } + else { + incomingParameterStrategy = ParameterStrategy.POSITIONAL; + } + + if ( parameterStrategy == ParameterStrategy.UNKNOWN ) { + parameterStrategy = incomingParameterStrategy; + } + else { + if ( parameterStrategy != incomingParameterStrategy ) { + throw new IllegalArgumentException( + "Attempt to mix named and position parameters for " + + "@NamedStoredProcedureQuery(name=" + name + ")" + ); + } + } + parameters.add( new Parameter( name, mode, javaType ) ); + } + + public void addHint(String hintKey, String value) { + queryHints.put( hintKey, value ); + } + + public void addResultClassName(String name) { + classNames.add( name ); + } + + public void addResultSetMappingName(String name) { + resultSetMappingNames.add( name ); + } + + public NamedStoredProcedureQueryDefinition buildDefinition() { + return new NamedStoredProcedureQueryDefinition( + name, + procedureName, + parameterStrategy, + parameters, + queryHints, + classNames, + resultSetMappingNames + ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java index c3cb204e36d7..20733318d98b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/SessionFactoryBuilder.java @@ -23,18 +23,117 @@ */ package org.hibernate.metamodel; +import org.hibernate.CustomEntityDirtinessStrategy; +import org.hibernate.EntityMode; +import org.hibernate.EntityNameResolver; import org.hibernate.Interceptor; import org.hibernate.SessionFactory; +import org.hibernate.SessionFactoryObserver; +import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.tuple.entity.EntityTuplizer; /** + * The contract for building a {@link SessionFactory} given a number of options. + * + * @author Steve Ebersole * @author Gail Badner */ public interface SessionFactoryBuilder { + /** + * Names an interceptor to be applied to the SessionFactory, which in turn means it will be used by all + * Sessions unless one is explicitly specified in {@link org.hibernate.SessionBuilder#interceptor} + * + * @param interceptor The interceptor + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.cfg.AvailableSettings#INTERCEPTOR + */ public SessionFactoryBuilder with(Interceptor interceptor); + /** + * Specifies a custom entity dirtiness strategy to be applied to the SessionFactory. See the contract + * of {@link CustomEntityDirtinessStrategy} for details. + * + * @param customEntityDirtinessStrategy The custom strategy to be used. + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.cfg.AvailableSettings#CUSTOM_ENTITY_DIRTINESS_STRATEGY + */ + public SessionFactoryBuilder with(CustomEntityDirtinessStrategy customEntityDirtinessStrategy); + + /** + * Specifies a strategy for resolving the notion of a "current" tenant-identifier when using multi-tenancy + * together with current sessions + * + * @param currentTenantIdentifierResolver The resolution strategy to use. + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.cfg.AvailableSettings#MULTI_TENANT_IDENTIFIER_RESOLVER + */ + public SessionFactoryBuilder with(CurrentTenantIdentifierResolver currentTenantIdentifierResolver); + + /** + * Specifies one or more observers to be applied to the SessionFactory. Can be called multiple times to add + * additional observers. + * + * @param observers The observers to add + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder add(SessionFactoryObserver... observers); + + /** + * Specifies one or more entity name resolvers to be applied to the SessionFactory (see the {@link EntityNameResolver} + * contract for more information.. Can be called multiple times to add additional resolvers.. + * + * @param entityNameResolvers The entityNameResolvers to add + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder add(EntityNameResolver... entityNameResolvers); + + /** + * Names the {@link EntityNotFoundDelegate} to be applied to the SessionFactory. EntityNotFoundDelegate is a + * strategy that accounts for different exceptions thrown between Hibernate and JPA when an entity cannot be found. + * + * @param entityNotFoundDelegate The delegate/strategy to use. + * + * @return {@code this}, for method chaining + */ public SessionFactoryBuilder with(EntityNotFoundDelegate entityNotFoundDelegate); + /** + * Register the default {@link EntityTuplizer} to be applied to the SessionFactory. + * + * @param entityMode The entity mode that which this tuplizer will be applied. + * @param tuplizerClass The custom tuplizer class. + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder with(EntityMode entityMode, Class tuplizerClass); + + /** + * Apply a BeanValidation ValidatorFactory to the SessionFactory being built + * + * @param validatorFactory The ValidatorFactory to use + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder withValidatorFactory(Object validatorFactory); + + /** + * Apply a CDI BeanManager to the SessionFactory being built + * + * @param beanManager The BeanManager to use + * + * @return {@code this}, for method chaining + */ + public SessionFactoryBuilder withBeanManager(Object beanManager); + /** * After all options have been set, build the SessionFactory. * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java deleted file mode 100644 index 4ae33f270aff..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.hibernate.metamodel.domain.Attribute; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * Basic support for {@link AttributeBinding} implementors - * - * @author Steve Ebersole - */ -public abstract class AbstractAttributeBinding implements AttributeBinding { - private final AttributeBindingContainer container; - private final Attribute attribute; - - private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); - private final Set entityReferencingAttributeBindings = new HashSet(); - - private boolean includedInOptimisticLocking; - - private boolean isLazy; - private String propertyAccessorName; - private boolean isAlternateUniqueKey; - - private MetaAttributeContext metaAttributeContext; - - protected AbstractAttributeBinding(AttributeBindingContainer container, Attribute attribute) { - this.container = container; - this.attribute = attribute; - } - - @Override - public AttributeBindingContainer getContainer() { - return container; - } - - @Override - public Attribute getAttribute() { - return attribute; - } - - @Override - public HibernateTypeDescriptor getHibernateTypeDescriptor() { - return hibernateTypeDescriptor; - } - - @Override - public boolean isBasicPropertyAccessor() { - return propertyAccessorName == null || "property".equals( propertyAccessorName ); - } - - @Override - public String getPropertyAccessorName() { - return propertyAccessorName; - } - - public void setPropertyAccessorName(String propertyAccessorName) { - this.propertyAccessorName = propertyAccessorName; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return includedInOptimisticLocking; - } - - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking) { - this.includedInOptimisticLocking = includedInOptimisticLocking; - } - - @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - @Override - public boolean isAlternateUniqueKey() { - return isAlternateUniqueKey; - } - - public void setAlternateUniqueKey(boolean alternateUniqueKey) { - this.isAlternateUniqueKey = alternateUniqueKey; - } - - @Override - public boolean isLazy() { - return isLazy; - } - - public void setLazy(boolean isLazy) { - this.isLazy = isLazy; - } - - public void addEntityReferencingAttributeBinding(SingularAssociationAttributeBinding referencingAttributeBinding) { - entityReferencingAttributeBindings.add( referencingAttributeBinding ); - } - - public Set getEntityReferencingAttributeBindings() { - return Collections.unmodifiableSet( entityReferencingAttributeBindings ); - } - - public void validate() { - if ( !entityReferencingAttributeBindings.isEmpty() ) { - // TODO; validate that this AttributeBinding can be a target of an entity reference - // (e.g., this attribute is the primary key or there is a unique-key) - // can a unique attribute be used as a target? if so, does it need to be non-null? - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractCollectionElement.java deleted file mode 100644 index 1b922133cf4c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractCollectionElement.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.relational.Value; - -/** - * Basic contract describing the commonality between the various types of collection element mappings. - * - * @author Steve Ebersole - */ -public abstract class AbstractCollectionElement { - private final AbstractPluralAttributeBinding collectionBinding; - - private Value elementValue; - - AbstractCollectionElement(AbstractPluralAttributeBinding collectionBinding) { - this.collectionBinding = collectionBinding; - } - - public abstract CollectionElementNature getCollectionElementNature(); - - public AbstractPluralAttributeBinding getCollectionBinding() { - return collectionBinding; - } - - public Value getElementValue() { - return elementValue; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java deleted file mode 100644 index b80066a8a0c5..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractPluralAttributeBinding.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.persister.collection.CollectionPersister; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBinding implements PluralAttributeBinding { - private final CollectionKey collectionKey; - private final AbstractCollectionElement collectionElement; - - private Table collectionTable; - - private FetchTiming fetchTiming; - private FetchStyle fetchStyle; - private int batchSize = -1; - - private CascadeStyle cascadeStyle; - private boolean orphanDelete; - - private Caching caching; - - private boolean inverse; - private boolean mutable = true; - - private Class collectionPersisterClass; - - private String where; - private String orderBy; - private boolean sorted; - private Comparator comparator; - private String comparatorClassName; - - private String customLoaderName; - private CustomSQL customSqlInsert; - private CustomSQL customSqlUpdate; - private CustomSQL customSqlDelete; - private CustomSQL customSqlDeleteAll; - - private String referencedPropertyName; - - private final java.util.Map filters = new HashMap(); - private final java.util.Set synchronizedTables = new HashSet(); - - protected AbstractPluralAttributeBinding( - AttributeBindingContainer container, - PluralAttribute attribute, - CollectionElementNature collectionElementNature) { - super( container, attribute ); - this.collectionKey = new CollectionKey( this ); - this.collectionElement = interpretNature( collectionElementNature ); - } - - private AbstractCollectionElement interpretNature(CollectionElementNature collectionElementNature) { - switch ( collectionElementNature ) { - case BASIC: { - return new BasicCollectionElement( this ); - } - case COMPOSITE: { - return new CompositeCollectionElement( this ); - } - case ONE_TO_MANY: { - return new OneToManyCollectionElement( this ); - } - case MANY_TO_MANY: { - return new ManyToManyCollectionElement( this ); - } - case MANY_TO_ANY: { - return new ManyToAnyCollectionElement( this ); - } - default: { - throw new AssertionFailure( "Unknown collection element nature : " + collectionElementNature ); - } - } - } - -// protected void initializeBinding(PluralAttributeBindingState state) { -// super.initialize( state ); -// fetchMode = state.getFetchMode(); -// extraLazy = state.isExtraLazy(); -// collectionElement.setNodeName( state.getElementNodeName() ); -// collectionElement.setTypeName( state.getElementTypeName() ); -// inverse = state.isInverse(); -// mutable = state.isMutable(); -// subselectLoadable = state.isSubselectLoadable(); -// if ( isSubselectLoadable() ) { -// getEntityBinding().setSubselectLoadableCollections( true ); -// } -// cacheConcurrencyStrategy = state.getCacheConcurrencyStrategy(); -// cacheRegionName = state.getCacheRegionName(); -// orderBy = state.getOrderBy(); -// where = state.getWhere(); -// referencedPropertyName = state.getReferencedPropertyName(); -// sorted = state.isSorted(); -// comparator = state.getComparator(); -// comparatorClassName = state.getComparatorClassName(); -// orphanDelete = state.isOrphanDelete(); -// batchSize = state.getBatchSize(); -// embedded = state.isEmbedded(); -// optimisticLocked = state.isOptimisticLocked(); -// collectionPersisterClass = state.getCollectionPersisterClass(); -// filters.putAll( state.getFilters() ); -// synchronizedTables.addAll( state.getSynchronizedTables() ); -// customSQLInsert = state.getCustomSQLInsert(); -// customSQLUpdate = state.getCustomSQLUpdate(); -// customSQLDelete = state.getCustomSQLDelete(); -// customSQLDeleteAll = state.getCustomSQLDeleteAll(); -// loaderName = state.getLoaderName(); -// } - - @Override - public PluralAttribute getAttribute() { - return (PluralAttribute) super.getAttribute(); - } - - @Override - public boolean isAssociation() { - return collectionElement.getCollectionElementNature() == CollectionElementNature.MANY_TO_ANY - || collectionElement.getCollectionElementNature() == CollectionElementNature.MANY_TO_MANY - || collectionElement.getCollectionElementNature() == CollectionElementNature.ONE_TO_MANY; - } - - @Override - public TableSpecification getCollectionTable() { - return collectionTable; - } - - public void setCollectionTable(Table collectionTable) { - this.collectionTable = collectionTable; - } - - @Override - public CollectionKey getCollectionKey() { - return collectionKey; - } - - @Override - public AbstractCollectionElement getCollectionElement() { - return collectionElement; - } - - @Override - public CascadeStyle getCascadeStyle() { - return cascadeStyle; - } - - @Override - public void setCascadeStyles(Iterable cascadeStyles) { - List cascadeStyleList = new ArrayList(); - for ( CascadeStyle style : cascadeStyles ) { - if ( style != CascadeStyles.NONE ) { - cascadeStyleList.add( style ); - } - if ( style == CascadeStyles.DELETE_ORPHAN || - style == CascadeStyles.ALL_DELETE_ORPHAN ) { - orphanDelete = true; - } - } - - if ( cascadeStyleList.isEmpty() ) { - cascadeStyle = CascadeStyles.NONE; - } - else if ( cascadeStyleList.size() == 1 ) { - cascadeStyle = cascadeStyleList.get( 0 ); - } - else { - cascadeStyle = new CascadeStyles.MultipleCascadeStyle( - cascadeStyleList.toArray( new CascadeStyle[ cascadeStyleList.size() ] ) - ); - } - } - - @Override - public boolean isOrphanDelete() { - return orphanDelete; - } - - @Override - public FetchMode getFetchMode() { - if ( getFetchStyle() == FetchStyle.JOIN ) { - return FetchMode.JOIN; - } - else { - return FetchMode.SELECT; - } - } - - @Override - public FetchTiming getFetchTiming() { - return fetchTiming; - } - - @Override - public void setFetchTiming(FetchTiming fetchTiming) { - this.fetchTiming = fetchTiming; - } - - @Override - public FetchStyle getFetchStyle() { - return fetchStyle; - } - - @Override - public void setFetchStyle(FetchStyle fetchStyle) { - this.fetchStyle = fetchStyle; - } - - @Override - public String getCustomLoaderName() { - return customLoaderName; - } - - public void setCustomLoaderName(String customLoaderName) { - this.customLoaderName = customLoaderName; - } - - @Override - public CustomSQL getCustomSqlInsert() { - return customSqlInsert; - } - - public void setCustomSqlInsert(CustomSQL customSqlInsert) { - this.customSqlInsert = customSqlInsert; - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return customSqlUpdate; - } - - public void setCustomSqlUpdate(CustomSQL customSqlUpdate) { - this.customSqlUpdate = customSqlUpdate; - } - - @Override - public CustomSQL getCustomSqlDelete() { - return customSqlDelete; - } - - public void setCustomSqlDelete(CustomSQL customSqlDelete) { - this.customSqlDelete = customSqlDelete; - } - - @Override - public CustomSQL getCustomSqlDeleteAll() { - return customSqlDeleteAll; - } - - public void setCustomSqlDeleteAll(CustomSQL customSqlDeleteAll) { - this.customSqlDeleteAll = customSqlDeleteAll; - } - - public Class getCollectionPersisterClass() { - return collectionPersisterClass; - } - - public void setCollectionPersisterClass(Class collectionPersisterClass) { - this.collectionPersisterClass = collectionPersisterClass; - } - - public Caching getCaching() { - return caching; - } - - public void setCaching(Caching caching) { - this.caching = caching; - } - - @Override - public String getOrderBy() { - return orderBy; - } - - public void setOrderBy(String orderBy) { - this.orderBy = orderBy; - } - - @Override - public String getWhere() { - return where; - } - - public void setWhere(String where) { - this.where = where; - } - - @Override - public boolean isInverse() { - return inverse; - } - - public void setInverse(boolean inverse) { - this.inverse = inverse; - } - - @Override - public boolean isMutable() { - return mutable; - } - - public void setMutable(boolean mutable) { - this.mutable = mutable; - } - - @Override - public int getBatchSize() { - return batchSize; - } - - public void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - - - - - - - - - - - public String getReferencedPropertyName() { - return referencedPropertyName; - } - - @Override - public boolean isSorted() { - return sorted; - } - - @Override - public Comparator getComparator() { - return comparator; - } - - public void setComparator(Comparator comparator) { - this.comparator = comparator; - } - - public String getComparatorClassName() { - return comparatorClassName; - } - - public void addFilter(String name, String condition) { - filters.put( name, condition ); - } - - @Override - public java.util.Map getFilterMap() { - return filters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java deleted file mode 100644 index ef7fb1fdede1..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractSingularAttributeBinding.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Tuple; -import org.hibernate.metamodel.relational.Value; - -/** - * @author Steve Ebersole - */ -public abstract class AbstractSingularAttributeBinding - extends AbstractAttributeBinding - implements SingularAttributeBinding { - - private Value value; - private List simpleValueBindings = new ArrayList(); - - private boolean hasDerivedValue; - private boolean isNullable = true; - - protected AbstractSingularAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute ); - } - - @Override - public SingularAttribute getAttribute() { - return (SingularAttribute) super.getAttribute(); - } - - public Value getValue() { - return value; - } - - public void setSimpleValueBindings(Iterable simpleValueBindings) { - List values = new ArrayList(); - for ( SimpleValueBinding simpleValueBinding : simpleValueBindings ) { - this.simpleValueBindings.add( simpleValueBinding ); - values.add( simpleValueBinding.getSimpleValue() ); - this.hasDerivedValue = this.hasDerivedValue || simpleValueBinding.isDerived(); - this.isNullable = this.isNullable && simpleValueBinding.isNullable(); - } - if ( values.size() == 1 ) { - this.value = values.get( 0 ); - } - else { - final Tuple tuple = values.get( 0 ).getTable().createTuple( getRole() ); - for ( SimpleValue value : values ) { - tuple.addValue( value ); - } - this.value = tuple; - } - } - - private String getRole() { - return getContainer().getPathBase() + '.' + getAttribute().getName(); - } - - @Override - public int getSimpleValueSpan() { - checkValueBinding(); - return simpleValueBindings.size(); - } - - protected void checkValueBinding() { - if ( value == null ) { - throw new AssertionFailure( "No values yet bound!" ); - } - } - - @Override - public Iterable getSimpleValueBindings() { - return simpleValueBindings; - } - - @Override - public boolean hasDerivedValue() { - checkValueBinding(); - return hasDerivedValue; - } - - @Override - public boolean isNullable() { - checkValueBinding(); - return isNullable; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java deleted file mode 100644 index 3224be343e7c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AssociationAttributeBinding.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; - -/** - * Contract describing a binding for attributes which model associations. - * - * @author Steve Ebersole - */ -public interface AssociationAttributeBinding extends AttributeBinding { - /** - * Obtain the cascade style in effect for this association. - * - * @return The (potentially aggregated) cascade style. - */ - public CascadeStyle getCascadeStyle(); - - /** - * Set the cascade styles in effect for this association. - * - * @param cascadeStyles The cascade styles. - */ - public void setCascadeStyles(Iterable cascadeStyles); - - public FetchTiming getFetchTiming(); - public void setFetchTiming(FetchTiming fetchTiming); - - public FetchStyle getFetchStyle(); - public void setFetchStyle(FetchStyle fetchStyle); - - - /** - * Temporary. Needed for integration with legacy org.hibernate.mapping configuration of persisters. - * - * @deprecated - */ - @Deprecated - @SuppressWarnings( {"JavaDoc"}) - public FetchMode getFetchMode(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java deleted file mode 100644 index c208c3911c8a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBindingContainer.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.domain.AttributeContainer; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * Common contract for {@link EntityBinding} and {@link ComponentAttributeBinding} in so far as they are both - * containers for {@link AttributeBinding} descriptors - * - * @author Steve Ebersole - */ -public interface AttributeBindingContainer { - /** - * Obtain the path base of this container. Intended to help uniquely identify each attribute binding. - * - * @return The path base for this container. - */ - public String getPathBase(); - - /** - * Obtain the underlying domain attribute container. - * - * @return The attribute container - */ - public AttributeContainer getAttributeContainer(); - - /** - * Obtain all attribute bindings - * - * @return All attribute bindings - */ - public Iterable attributeBindings(); - - /** - * Locate a specific attribute binding, by its local name. - * - * @param name The name of the attribute, local to this container. - * - * @return The attribute binding. - */ - public AttributeBinding locateAttributeBinding(String name); - - /** - * Factory method for basic attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * - * @return The attribute binding instance. - */ - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute); - - /** - * Factory method for component attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * - * @return The attribute binding instance. - */ - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute); - - /** - * Factory method for many-to-one attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * - * @return The attribute binding instance. - */ - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute); - - /** - * Factory method for bag attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * @param nature The nature of the collection elements. - * - * @return The attribute binding instance. - */ - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature); - - /** - * Factory method for bag attribute bindings. - * - * @param attribute The attribute for which to make a binding. - * @param nature The nature of the collection elements. - * - * @return The attribute binding instance. - */ - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature); - - /** - * Seeks out the entity binding that is the root of this component path. - * - * @return The entity binding - */ - public EntityBinding seekEntityBinding(); - - /** - * Obtain the {@link Class} reference for this attribute container. Generally this is used to perform reflection - * on the attributes. - * - * @return The {@link Class} reference - */ - public Class getClassReference(); - - /** - * Obtain the meta-attribute context for this container. - * - * @return The meta-attribute context. - */ - public MetaAttributeContext getMetaAttributeContext(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BagBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BagBinding.java deleted file mode 100644 index 099fb5110c88..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BagBinding.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.domain.PluralAttribute; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public class BagBinding extends AbstractPluralAttributeBinding { - protected BagBinding(AttributeBindingContainer container, PluralAttribute attribute, CollectionElementNature nature) { - super( container, attribute, nature ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java deleted file mode 100644 index c867c7b49456..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicAttributeBinding.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Properties; - -import org.hibernate.MappingException; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public class BasicAttributeBinding - extends AbstractSingularAttributeBinding - implements KeyValueBinding { - - private String unsavedValue; - private PropertyGeneration generation; - private boolean includedInOptimisticLocking; - - private boolean forceNonNullable; - private boolean forceUnique; - private boolean keyCascadeDeleteEnabled; - - private MetaAttributeContext metaAttributeContext; - - BasicAttributeBinding( - AttributeBindingContainer container, - SingularAttribute attribute, - boolean forceNonNullable, - boolean forceUnique) { - super( container, attribute ); - this.forceNonNullable = forceNonNullable; - this.forceUnique = forceUnique; - } - - @Override - public boolean isAssociation() { - return false; - } - - @Override - public String getUnsavedValue() { - return unsavedValue; - } - - public void setUnsavedValue(String unsavedValue) { - this.unsavedValue = unsavedValue; - } - - @Override - public PropertyGeneration getGeneration() { - return generation; - } - - public void setGeneration(PropertyGeneration generation) { - this.generation = generation; - } - - public boolean isIncludedInOptimisticLocking() { - return includedInOptimisticLocking; - } - - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking) { - this.includedInOptimisticLocking = includedInOptimisticLocking; - } - - @Override - public boolean isKeyCascadeDeleteEnabled() { - return keyCascadeDeleteEnabled; - } - - public void setKeyCascadeDeleteEnabled(boolean keyCascadeDeleteEnabled) { - this.keyCascadeDeleteEnabled = keyCascadeDeleteEnabled; - } - - public boolean forceNonNullable() { - return forceNonNullable; - } - - public boolean forceUnique() { - return forceUnique; - } - - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - IdentifierGenerator createIdentifierGenerator( - IdGenerator idGenerator, - IdentifierGeneratorFactory identifierGeneratorFactory, - Properties properties) { - Properties params = new Properties(); - params.putAll( properties ); - - // use the schema/catalog specified by getValue().getTable() - but note that - // if the schema/catalog were specified as params, they will already be initialized and - //will override the values set here (they are in idGenerator.getParameters().) - Schema schema = getValue().getTable().getSchema(); - if ( schema != null ) { - if ( schema.getName().getSchema() != null ) { - params.setProperty( PersistentIdentifierGenerator.SCHEMA, schema.getName().getSchema().getName() ); - } - if ( schema.getName().getCatalog() != null ) { - params.setProperty( PersistentIdentifierGenerator.CATALOG, schema.getName().getCatalog().getName() ); - } - } - - // TODO: not sure how this works for collection IDs... - //pass the entity-name, if not a collection-id - //if ( rootClass!=null) { - params.setProperty( IdentifierGenerator.ENTITY_NAME, getContainer().seekEntityBinding().getEntity().getName() ); - //} - - //init the table here instead of earlier, so that we can get a quoted table name - //TODO: would it be better to simply pass the qualified table name, instead of - // splitting it up into schema/catalog/table names - String tableName = getValue().getTable().getQualifiedName( identifierGeneratorFactory.getDialect() ); - params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); - - //pass the column name (a generated id almost always has a single column) - if ( getSimpleValueSpan() > 1 ) { - throw new MappingException( - "A SimpleAttributeBinding used for an identifier has more than 1 Value: " + getAttribute().getName() - ); - } - SimpleValue simpleValue = (SimpleValue) getValue(); - if ( !Column.class.isInstance( simpleValue ) ) { - throw new MappingException( - "Cannot create an IdentifierGenerator because the value is not a column: " + - simpleValue.toLoggableString() - ); - } - params.setProperty( - PersistentIdentifierGenerator.PK, - ( (Column) simpleValue ).getColumnName().encloseInQuotesIfQuoted( - identifierGeneratorFactory.getDialect() - ) - ); - - // TODO: is this stuff necessary for SimpleValue??? - //if (rootClass!=null) { - // StringBuffer tables = new StringBuffer(); - // Iterator iter = rootClass.getIdentityTables().iterator(); - // while ( iter.hasNext() ) { - // Table table= (Table) iter.next(); - // tables.append( table.getQuotedName(dialect) ); - // if ( iter.hasNext() ) tables.append(", "); - // } - // params.setProperty( PersistentIdentifierGenerator.TABLES, tables.toString() ); - //} - //else { - params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); - //} - - params.putAll( idGenerator.getParameters() ); - - return identifierGeneratorFactory.createIdentifierGenerator( - idGenerator.getStrategy(), getHibernateTypeDescriptor().getResolvedTypeMapping(), params - ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicCollectionElement.java deleted file mode 100644 index 5d0f84c21684..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/BasicCollectionElement.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class BasicCollectionElement extends AbstractCollectionElement { - private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); - - public BasicCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } - - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.BASIC; - } - - public HibernateTypeDescriptor getHibernateTypeDescriptor() { - return hibernateTypeDescriptor; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Caching.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Caching.java deleted file mode 100644 index e4a9e0ed1231..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Caching.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.cache.spi.access.AccessType; - -/** - * Defines the caching settings for an entity. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class Caching { - private String region; - private AccessType accessType; - private boolean cacheLazyProperties; - - public Caching() { - } - - public Caching(String region, AccessType accessType, boolean cacheLazyProperties) { - this.region = region; - this.accessType = accessType; - this.cacheLazyProperties = cacheLazyProperties; - } - - public String getRegion() { - return region; - } - - public void setRegion(String region) { - this.region = region; - } - - public AccessType getAccessType() { - return accessType; - } - - public void setAccessType(AccessType accessType) { - this.accessType = accessType; - } - - public boolean isCacheLazyProperties() { - return cacheLazyProperties; - } - - public void setCacheLazyProperties(boolean cacheLazyProperties) { - this.cacheLazyProperties = cacheLazyProperties; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "Caching" ); - sb.append( "{region='" ).append( region ).append( '\'' ); - sb.append( ", accessType=" ).append( accessType ); - sb.append( ", cacheLazyProperties=" ).append( cacheLazyProperties ); - sb.append( '}' ); - return sb.toString(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElementNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElementNature.java deleted file mode 100644 index 69fc83a7a79b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElementNature.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * Describes the nature of persistent collection elements. - * - * @author Steve Ebersole - * @author Gail Badner - * - * @todo Merge with {@link org.hibernate.metamodel.source.binder.PluralAttributeNature} ? package separation kept me from doing that initially - */ -public enum CollectionElementNature { - BASIC, - COMPOSITE, - ONE_TO_MANY, - MANY_TO_MANY, - MANY_TO_ANY -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java deleted file mode 100644 index 81661e8e2321..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionKey.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.relational.ForeignKey; -import org.hibernate.metamodel.relational.TableSpecification; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public class CollectionKey { - private final AbstractPluralAttributeBinding pluralAttributeBinding; - - private ForeignKey foreignKey; - private boolean inverse; - private HibernateTypeDescriptor hibernateTypeDescriptor; - -// todo : this would be nice to have but we do not always know it, especially in HBM case. -// private BasicAttributeBinding otherSide; - - public CollectionKey(AbstractPluralAttributeBinding pluralAttributeBinding) { - this.pluralAttributeBinding = pluralAttributeBinding; - } - - public AbstractPluralAttributeBinding getPluralAttributeBinding() { - return pluralAttributeBinding; - } - - public void prepareForeignKey(String foreignKeyName, String targetTableName) { - if ( foreignKey != null ) { - throw new AssertionFailure( "Foreign key already initialized" ); - } - final TableSpecification collectionTable = pluralAttributeBinding.getCollectionTable(); - if ( collectionTable == null ) { - throw new AssertionFailure( "Collection table not yet bound" ); - } - - final TableSpecification targetTable = pluralAttributeBinding.getContainer() - .seekEntityBinding() - .locateTable( targetTableName ); - - // todo : handle implicit fk names... - - foreignKey = collectionTable.createForeignKey( targetTable, foreignKeyName ); - } - - public ForeignKey getForeignKey() { - return foreignKey; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java deleted file mode 100644 index b64b79eabe25..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ComponentAttributeBinding.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.domain.AttributeContainer; -import org.hibernate.metamodel.domain.Component; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.PluralAttributeNature; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.source.MetaAttributeContext; - -/** - * @author Steve Ebersole - */ -public class ComponentAttributeBinding extends AbstractSingularAttributeBinding implements AttributeBindingContainer { - private final String path; - private Map attributeBindingMap = new HashMap(); - private SingularAttribute parentReference; - private MetaAttributeContext metaAttributeContext; - - public ComponentAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute ); - this.path = container.getPathBase() + '.' + attribute.getName(); - } - - @Override - public EntityBinding seekEntityBinding() { - return getContainer().seekEntityBinding(); - } - - @Override - public String getPathBase() { - return path; - } - - @Override - public AttributeContainer getAttributeContainer() { - return getComponent(); - } - - public Component getComponent() { - return (Component) getAttribute().getSingularAttributeType(); - } - - @Override - public boolean isAssociation() { - return false; - } - - @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - @Override - public AttributeBinding locateAttributeBinding(String name) { - return attributeBindingMap.get( name ); - } - - @Override - public Iterable attributeBindings() { - return attributeBindingMap.values(); - } - - @Override - protected void checkValueBinding() { - // do nothing here... - } - - @Override - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) { - final BasicAttributeBinding binding = new BasicAttributeBinding( - this, - attribute, - isNullable(), - isAlternateUniqueKey() // todo : is this accurate? - ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - protected void registerAttributeBinding(String name, AttributeBinding attributeBinding) { - // todo : hook this into the EntityBinding notion of "entity referencing attribute bindings" - attributeBindingMap.put( name, attributeBinding ); - } - - @Override - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) { - final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) { - final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); - final BagBinding binding = new BagBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); - final SetBinding binding = new SetBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public Class getClassReference() { - return getComponent().getClassReference(); - } - - public SingularAttribute getParentReference() { - return parentReference; - } - - public void setParentReference(SingularAttribute parentReference) { - this.parentReference = parentReference; - } - - @Override - public PropertyGeneration getGeneration() { - // todo : not sure the correct thing to return here since it essentially relies on the simple sub-attributes. - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CompositeCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CompositeCollectionElement.java deleted file mode 100644 index e39886d055d3..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CompositeCollectionElement.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class CompositeCollectionElement extends AbstractCollectionElement { - public CompositeCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } - - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.COMPOSITE; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java deleted file mode 100644 index 967e2a627a45..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.internal.util.collections.JoinedIterable; -import org.hibernate.metamodel.domain.AttributeContainer; -import org.hibernate.metamodel.domain.Entity; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.PluralAttributeNature; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.tuple.entity.EntityTuplizer; - -/** - * Provides the link between the domain and the relational model for an entity. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - * @author Gail Badner - */ -public class EntityBinding implements AttributeBindingContainer { - private static final String NULL_DISCRIMINATOR_MATCH_VALUE = "null"; - private static final String NOT_NULL_DISCRIMINATOR_MATCH_VALUE = "not null"; - - private final EntityBinding superEntityBinding; - private final List subEntityBindings = new ArrayList(); - private final HierarchyDetails hierarchyDetails; - - private Entity entity; - private TableSpecification primaryTable; - private String primaryTableName; - private Map secondaryTables = new HashMap(); - - private ValueHolder> proxyInterfaceType; - - private String jpaEntityName; - - private Class customEntityPersisterClass; - private Class customEntityTuplizerClass; - - private String discriminatorMatchValue; - - private Set filterDefinitions = new HashSet(); - private Set entityReferencingAttributeBindings = new HashSet(); - - private MetaAttributeContext metaAttributeContext; - - private boolean lazy; - private boolean mutable; - private String whereFilter; - private String rowId; - - private boolean dynamicUpdate; - private boolean dynamicInsert; - - private int batchSize; - private boolean selectBeforeUpdate; - private boolean hasSubselectLoadableCollections; - - private Boolean isAbstract; - - private String customLoaderName; - private CustomSQL customInsert; - private CustomSQL customUpdate; - private CustomSQL customDelete; - - private Set synchronizedTableNames = new HashSet(); - private Map attributeBindingMap = new HashMap(); - - private List jpaCallbackClasses = new ArrayList(); - - /** - * Used to instantiate the EntityBinding for an entity that is the root of an inheritance hierarchy - * - * @param inheritanceType The inheritance type for the hierarchy - * @param entityMode The entity mode used in this hierarchy. - */ - public EntityBinding(InheritanceType inheritanceType, EntityMode entityMode) { - this.superEntityBinding = null; - this.hierarchyDetails = new HierarchyDetails( this, inheritanceType, entityMode ); - } - - /** - * Used to instantiate the EntityBinding for an entity that is a subclass (sub-entity) in an inheritance hierarchy - * - * @param superEntityBinding The entity binding of this binding's super - */ - public EntityBinding(EntityBinding superEntityBinding) { - this.superEntityBinding = superEntityBinding; - this.superEntityBinding.subEntityBindings.add( this ); - this.hierarchyDetails = superEntityBinding.getHierarchyDetails(); - } - - public HierarchyDetails getHierarchyDetails() { - return hierarchyDetails; - } - - public EntityBinding getSuperEntityBinding() { - return superEntityBinding; - } - - public boolean isRoot() { - return superEntityBinding == null; - } - - public boolean isPolymorphic() { - return superEntityBinding != null || - hierarchyDetails.getEntityDiscriminator() != null || - ! subEntityBindings.isEmpty(); - } - - public boolean hasSubEntityBindings() { - return subEntityBindings.size() > 0; - } - - public int getSubEntityBindingClosureSpan() { - int n = subEntityBindings.size(); - for ( EntityBinding subEntityBinding : subEntityBindings ) { - n += subEntityBinding.getSubEntityBindingClosureSpan(); - } - return n; - } - - /* used for testing */ - public Iterable getDirectSubEntityBindings() { - return subEntityBindings; - } - - /** - * Returns sub-EntityBinding objects in a special 'order', most derived subclasses - * first. Specifically, the sub-entity bindings follow a depth-first, - * post-order traversal - * - * Note that the returned value excludes this entity binding. - * - * @return sub-entity bindings ordered by those entity bindings that are most derived. - */ - public Iterable getPostOrderSubEntityBindingClosure() { - // TODO: why this order? - List> subclassIterables = new ArrayList>( subEntityBindings.size() + 1 ); - for ( EntityBinding subEntityBinding : subEntityBindings ) { - Iterable subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure(); - if ( subSubEntityBindings.iterator().hasNext() ) { - subclassIterables.add( subSubEntityBindings ); - } - } - if ( ! subEntityBindings.isEmpty() ) { - subclassIterables.add( subEntityBindings ); - } - return new JoinedIterable( subclassIterables ); - } - - /** - * Returns sub-EntityBinding ordered as a depth-first, - * pre-order traversal (a subclass precedes its own subclasses). - * - * Note that the returned value specifically excludes this entity binding. - * - * @return sub-entity bindings ordered as a depth-first, - * pre-order traversal - */ - public Iterable getPreOrderSubEntityBindingClosure() { - return getPreOrderSubEntityBindingClosure( false ); - } - - private Iterable getPreOrderSubEntityBindingClosure(boolean includeThis) { - List> iterables = new ArrayList>(); - if ( includeThis ) { - iterables.add( java.util.Collections.singletonList( this ) ); - } - for ( EntityBinding subEntityBinding : subEntityBindings ) { - Iterable subSubEntityBindingClosure = subEntityBinding.getPreOrderSubEntityBindingClosure( true ); - if ( subSubEntityBindingClosure.iterator().hasNext() ) { - iterables.add( subSubEntityBindingClosure ); - } - } - return new JoinedIterable( iterables ); - } - - public Entity getEntity() { - return entity; - } - - public void setEntity(Entity entity) { - this.entity = entity; - } - - public TableSpecification getPrimaryTable() { - return primaryTable; - } - - public void setPrimaryTable(TableSpecification primaryTable) { - this.primaryTable = primaryTable; - } - - public TableSpecification locateTable(String tableName) { - if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) { - return primaryTable; - } - TableSpecification tableSpec = secondaryTables.get( tableName ); - if ( tableSpec == null ) { - throw new AssertionFailure( - String.format( - "Unable to find table %s amongst tables %s", - tableName, - secondaryTables.keySet() - ) - ); - } - return tableSpec; - } - public String getPrimaryTableName() { - return primaryTableName; - } - - public void setPrimaryTableName(String primaryTableName) { - this.primaryTableName = primaryTableName; - } - - public void addSecondaryTable(String tableName, TableSpecification table) { - secondaryTables.put( tableName, table ); - } - - public boolean isVersioned() { - return getHierarchyDetails().getVersioningAttributeBinding() != null; - } - - public boolean isDiscriminatorMatchValueNull() { - return NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); - } - - public boolean isDiscriminatorMatchValueNotNull() { - return NOT_NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); - } - - public String getDiscriminatorMatchValue() { - return discriminatorMatchValue; - } - - public void setDiscriminatorMatchValue(String discriminatorMatchValue) { - this.discriminatorMatchValue = discriminatorMatchValue; - } - - public Iterable getFilterDefinitions() { - return filterDefinitions; - } - - public void addFilterDefinition(FilterDefinition filterDefinition) { - filterDefinitions.add( filterDefinition ); - } - - public Iterable getEntityReferencingAttributeBindings() { - return entityReferencingAttributeBindings; - } - - @Override - public EntityBinding seekEntityBinding() { - return this; - } - - @Override - public String getPathBase() { - return getEntity().getName(); - } - - @Override - public Class getClassReference() { - return getEntity().getClassReference(); - } - - @Override - public AttributeContainer getAttributeContainer() { - return getEntity(); - } - - protected void registerAttributeBinding(String name, AttributeBinding attributeBinding) { - if ( SingularAssociationAttributeBinding.class.isInstance( attributeBinding ) ) { - entityReferencingAttributeBindings.add( (SingularAssociationAttributeBinding) attributeBinding ); - } - attributeBindingMap.put( name, attributeBinding ); - } - - @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - - public boolean isMutable() { - return mutable; - } - - public void setMutable(boolean mutable) { - this.mutable = mutable; - } - - public boolean isLazy() { - return lazy; - } - - public void setLazy(boolean lazy) { - this.lazy = lazy; - } - - public ValueHolder> getProxyInterfaceType() { - return proxyInterfaceType; - } - - public void setProxyInterfaceType(ValueHolder> proxyInterfaceType) { - this.proxyInterfaceType = proxyInterfaceType; - } - - public String getWhereFilter() { - return whereFilter; - } - - public void setWhereFilter(String whereFilter) { - this.whereFilter = whereFilter; - } - - public String getRowId() { - return rowId; - } - - public void setRowId(String rowId) { - this.rowId = rowId; - } - - public boolean isDynamicUpdate() { - return dynamicUpdate; - } - - public void setDynamicUpdate(boolean dynamicUpdate) { - this.dynamicUpdate = dynamicUpdate; - } - - public boolean isDynamicInsert() { - return dynamicInsert; - } - - public void setDynamicInsert(boolean dynamicInsert) { - this.dynamicInsert = dynamicInsert; - } - - public int getBatchSize() { - return batchSize; - } - - public void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - public boolean isSelectBeforeUpdate() { - return selectBeforeUpdate; - } - - public void setSelectBeforeUpdate(boolean selectBeforeUpdate) { - this.selectBeforeUpdate = selectBeforeUpdate; - } - - public boolean hasSubselectLoadableCollections() { - return hasSubselectLoadableCollections; - } - - /* package-protected */ - void setSubselectLoadableCollections(boolean hasSubselectLoadableCollections) { - this.hasSubselectLoadableCollections = hasSubselectLoadableCollections; - } - - public Class getCustomEntityPersisterClass() { - return customEntityPersisterClass; - } - - public void setCustomEntityPersisterClass(Class customEntityPersisterClass) { - this.customEntityPersisterClass = customEntityPersisterClass; - } - - public Class getCustomEntityTuplizerClass() { - return customEntityTuplizerClass; - } - - public void setCustomEntityTuplizerClass(Class customEntityTuplizerClass) { - this.customEntityTuplizerClass = customEntityTuplizerClass; - } - - public Boolean isAbstract() { - return isAbstract; - } - - public void setAbstract(Boolean isAbstract) { - this.isAbstract = isAbstract; - } - - public Set getSynchronizedTableNames() { - return synchronizedTableNames; - } - - public void addSynchronizedTableNames(java.util.Collection synchronizedTableNames) { - this.synchronizedTableNames.addAll( synchronizedTableNames ); - } - - public String getJpaEntityName() { - return jpaEntityName; - } - - public void setJpaEntityName(String jpaEntityName) { - this.jpaEntityName = jpaEntityName; - } - - public String getCustomLoaderName() { - return customLoaderName; - } - - public void setCustomLoaderName(String customLoaderName) { - this.customLoaderName = customLoaderName; - } - - public CustomSQL getCustomInsert() { - return customInsert; - } - - public void setCustomInsert(CustomSQL customInsert) { - this.customInsert = customInsert; - } - - public CustomSQL getCustomUpdate() { - return customUpdate; - } - - public void setCustomUpdate(CustomSQL customUpdate) { - this.customUpdate = customUpdate; - } - - public CustomSQL getCustomDelete() { - return customDelete; - } - - public void setCustomDelete(CustomSQL customDelete) { - this.customDelete = customDelete; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "EntityBinding" ); - sb.append( "{entity=" ).append( entity != null ? entity.getName() : "not set" ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) { - return makeSimpleAttributeBinding( attribute, false, false ); - } - - private BasicAttributeBinding makeSimpleAttributeBinding(SingularAttribute attribute, boolean forceNonNullable, boolean forceUnique) { - final BasicAttributeBinding binding = new BasicAttributeBinding( - this, - attribute, - forceNonNullable, - forceUnique - ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) { - final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) { - final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); - final BagBinding binding = new BagBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, CollectionElementNature nature) { - Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); - final SetBinding binding = new SetBinding( this, attribute, nature ); - registerAttributeBinding( attribute.getName(), binding ); - return binding; - } - - @Override - public AttributeBinding locateAttributeBinding(String name) { - return attributeBindingMap.get( name ); - } - - @Override - public Iterable attributeBindings() { - return attributeBindingMap.values(); - } - - /** - * Gets the number of attribute bindings defined on this class, including the - * identifier attribute binding and attribute bindings defined - * as part of a join. - * - * @return The number of attribute bindings - */ - public int getAttributeBindingClosureSpan() { - // TODO: update account for join attribute bindings - return superEntityBinding != null ? - superEntityBinding.getAttributeBindingClosureSpan() + attributeBindingMap.size() : - attributeBindingMap.size(); - } - - /** - * Gets the attribute bindings defined on this class, including the - * identifier attribute binding and attribute bindings defined - * as part of a join. - * - * @return The attribute bindings. - */ - public Iterable getAttributeBindingClosure() { - // TODO: update size to account for joins - Iterable iterable; - if ( superEntityBinding != null ) { - List> iterables = new ArrayList>( 2 ); - iterables.add( superEntityBinding.getAttributeBindingClosure() ); - iterables.add( attributeBindings() ); - iterable = new JoinedIterable( iterables ); - } - else { - iterable = attributeBindings(); - } - return iterable; - } - - /** - * Gets the attribute bindings for this EntityBinding and all of its - * sub-EntityBinding, starting from the root of the hierarchy; includes - * the identifier and attribute bindings defined as part of a join. - * @return - */ - public Iterable getSubEntityAttributeBindingClosure() { - List> iterables = new ArrayList>(); - iterables.add( getAttributeBindingClosure() ); - for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) { - // only add attribute bindings declared for the subEntityBinding - iterables.add( subEntityBinding.attributeBindings() ); - // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here - } - return new JoinedIterable( iterables ); - } - - public void setJpaCallbackClasses( List jpaCallbackClasses ) { - this.jpaCallbackClasses = jpaCallbackClasses; - } - - public Iterable getJpaCallbackClasses() { - return jpaCallbackClasses; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java deleted file mode 100644 index fba5b3c6c4e2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityIdentifier.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Properties; - -import org.hibernate.AssertionFailure; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; - -/** - * Binds the entity identifier. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class EntityIdentifier { - private final EntityBinding entityBinding; - private BasicAttributeBinding attributeBinding; - private IdentifierGenerator identifierGenerator; - private IdGenerator idGenerator; - private boolean isIdentifierMapper = false; - // todo : mappers, etc - - /** - * Create an identifier - * - * @param entityBinding the entity binding for which this instance is the id - */ - public EntityIdentifier(EntityBinding entityBinding) { - this.entityBinding = entityBinding; - } - - public BasicAttributeBinding getValueBinding() { - return attributeBinding; - } - - public void setValueBinding(BasicAttributeBinding attributeBinding) { - if ( this.attributeBinding != null ) { - throw new AssertionFailure( - String.format( - "Identifier value binding already existed for %s", - entityBinding.getEntity().getName() - ) - ); - } - this.attributeBinding = attributeBinding; - } - - public void setIdGenerator(IdGenerator idGenerator) { - this.idGenerator = idGenerator; - } - - public boolean isEmbedded() { - return attributeBinding.getSimpleValueSpan() > 1; - } - - public boolean isIdentifierMapper() { - return isIdentifierMapper; - } - - // todo do we really need this createIdentifierGenerator and how do we make sure the getter is not called too early - // maybe some sort of visitor pattern here!? (HF) - public IdentifierGenerator createIdentifierGenerator(IdentifierGeneratorFactory factory, Properties properties) { - if ( idGenerator != null ) { - identifierGenerator = attributeBinding.createIdentifierGenerator( idGenerator, factory, properties ); - } - return identifierGenerator; - } - - public IdentifierGenerator getIdentifierGenerator() { - return identifierGenerator; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Helper.java deleted file mode 100644 index 1bd2427d81d2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/Helper.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.PluralAttributeNature; - -/** - * Helper utilities specific to the binding package. - * - * @author Steve Ebersole - */ -public class Helper { - public static void checkPluralAttributeNature(PluralAttribute attribute, PluralAttributeNature expected) { - if ( attribute.getNature() != expected ) { - throw new AssertionFailure( - String.format( - "Mismatched collection natures; expecting %s, but found %s", - expected.getName(), - attribute.getNature().getName() - ) - ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HibernateTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HibernateTypeDescriptor.java deleted file mode 100644 index 6629783f50d0..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HibernateTypeDescriptor.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.type.Type; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public class HibernateTypeDescriptor { - private String explicitTypeName; - private String javaTypeName; - private boolean isToOne; - private Map typeParameters = new HashMap( ); - - private Type resolvedTypeMapping; - - public String getExplicitTypeName() { - return explicitTypeName; - } - - public void setExplicitTypeName(String explicitTypeName) { - this.explicitTypeName = explicitTypeName; - } - - public String getJavaTypeName() { - return javaTypeName; - } - - public void setJavaTypeName(String javaTypeName) { - this.javaTypeName = javaTypeName; - } - - public boolean isToOne() { - return isToOne; - } - - public void setToOne(boolean toOne) { - isToOne = toOne; - } - - public Map getTypeParameters() { - return typeParameters; - } - - public void setTypeParameters(Map typeParameters) { - this.typeParameters = typeParameters; - } - - public Type getResolvedTypeMapping() { - return resolvedTypeMapping; - } - - public void setResolvedTypeMapping(Type resolvedTypeMapping) { - this.resolvedTypeMapping = resolvedTypeMapping; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HierarchyDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HierarchyDetails.java deleted file mode 100644 index 3b3149547211..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/HierarchyDetails.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.EntityMode; -import org.hibernate.engine.OptimisticLockStyle; - -/** - * @author Steve Ebersole - */ -public class HierarchyDetails { - private final EntityBinding rootEntityBinding; - private final InheritanceType inheritanceType; - private final EntityMode entityMode; - - private final EntityIdentifier entityIdentifier; - - private EntityDiscriminator entityDiscriminator; - - private OptimisticLockStyle optimisticLockStyle; - private BasicAttributeBinding versioningAttributeBinding; - - private Caching caching; - - private boolean explicitPolymorphism; - - public HierarchyDetails(EntityBinding rootEntityBinding, InheritanceType inheritanceType, EntityMode entityMode) { - this.rootEntityBinding = rootEntityBinding; - this.inheritanceType = inheritanceType; - this.entityMode = entityMode; - this.entityIdentifier = new EntityIdentifier( rootEntityBinding ); - } - - public EntityBinding getRootEntityBinding() { - return rootEntityBinding; - } - - public InheritanceType getInheritanceType() { - return inheritanceType; - } - - public EntityMode getEntityMode() { - return entityMode; - } - - public EntityIdentifier getEntityIdentifier() { - return entityIdentifier; - } - - public EntityDiscriminator getEntityDiscriminator() { - return entityDiscriminator; - } - - public OptimisticLockStyle getOptimisticLockStyle() { - return optimisticLockStyle; - } - - public void setOptimisticLockStyle(OptimisticLockStyle optimisticLockStyle) { - this.optimisticLockStyle = optimisticLockStyle; - } - - public void setEntityDiscriminator(EntityDiscriminator entityDiscriminator) { - this.entityDiscriminator = entityDiscriminator; - } - - public BasicAttributeBinding getVersioningAttributeBinding() { - return versioningAttributeBinding; - } - - public void setVersioningAttributeBinding(BasicAttributeBinding versioningAttributeBinding) { - this.versioningAttributeBinding = versioningAttributeBinding; - } - - public Caching getCaching() { - return caching; - } - - public void setCaching(Caching caching) { - this.caching = caching; - } - - public boolean isExplicitPolymorphism() { - return explicitPolymorphism; - } - - public void setExplicitPolymorphism(boolean explicitPolymorphism) { - this.explicitPolymorphism = explicitPolymorphism; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java deleted file mode 100644 index 007b3b305a66..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/IdGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; - -import org.hibernate.internal.util.collections.CollectionHelper; - -/** - * Identifier generator container, Useful to keep named generator in annotations - * - * @author Emmanuel Bernard - */ -public class IdGenerator implements Serializable { - private final String name; - private final String strategy; - private final Map parameters; - - public IdGenerator( String name, - String strategy, - Map parameters ) { - this.name = name; - this.strategy = strategy; - if ( CollectionHelper.isEmpty( parameters ) ) { - this.parameters = Collections.emptyMap(); - } - else { - this.parameters = Collections.unmodifiableMap( parameters ); - } - } - - /** - * @return identifier generator strategy - */ - public String getStrategy() { - return strategy; - } - - /** - * @return generator name - */ - public String getName() { - return name; - } - - /** - * @return generator configuration parameters - */ - public Map getParameters() { - return parameters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/KeyValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/KeyValueBinding.java deleted file mode 100644 index cc48595d02b9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/KeyValueBinding.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public interface KeyValueBinding extends AttributeBinding { - public boolean isKeyCascadeDeleteEnabled(); - - public String getUnsavedValue(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToAnyCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToAnyCollectionElement.java deleted file mode 100644 index 50e5edd4433f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToAnyCollectionElement.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class ManyToAnyCollectionElement extends AbstractCollectionElement { - ManyToAnyCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } - - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.MANY_TO_ANY; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java deleted file mode 100644 index ee5b93464a5a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.HashMap; - -import org.dom4j.Element; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class ManyToManyCollectionElement extends AbstractCollectionElement { - - private final java.util.Map manyToManyFilters = new HashMap(); - private String manyToManyWhere; - private String manyToManyOrderBy; - - - ManyToManyCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } - - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.MANY_TO_MANY; - } - - public void fromHbmXml(Element node){ - /* - - - - - - - - - - - - - - - - - */ - } - - public String getManyToManyWhere() { - return manyToManyWhere; - } - - public void setManyToManyWhere(String manyToManyWhere) { - this.manyToManyWhere = manyToManyWhere; - } - - public String getManyToManyOrderBy() { - return manyToManyOrderBy; - } - - public void setManyToManyOrderBy(String manyToManyOrderBy) { - this.manyToManyOrderBy = manyToManyOrderBy; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java deleted file mode 100644 index 66a9f5376b1a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToOneAttributeBinding.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.metamodel.domain.SingularAttribute; - -/** - * TODO : javadoc - * - * @author Gail Badner - * @author Steve Ebersole - */ -public class ManyToOneAttributeBinding extends BasicAttributeBinding implements SingularAssociationAttributeBinding { - private String referencedEntityName; - private String referencedAttributeName; - private AttributeBinding referencedAttributeBinding; - - private boolean isLogicalOneToOne; - private String foreignKeyName; - - private CascadeStyle cascadeStyle; - private FetchTiming fetchTiming; - private FetchStyle fetchStyle; - - ManyToOneAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute, false, false ); - } - - @Override - public boolean isAssociation() { - return true; - } - - @Override - public final boolean isPropertyReference() { - return referencedAttributeName != null; - } - - @Override - public final String getReferencedEntityName() { - return referencedEntityName; - } - - @Override - public void setReferencedEntityName(String referencedEntityName) { - this.referencedEntityName = referencedEntityName; - } - - @Override - public final String getReferencedAttributeName() { - return referencedAttributeName; - } - - @Override - public void setReferencedAttributeName(String referencedEntityAttributeName) { - this.referencedAttributeName = referencedEntityAttributeName; - } - - @Override - public CascadeStyle getCascadeStyle() { - return cascadeStyle; - } - - @Override - public void setCascadeStyles(Iterable cascadeStyles) { - List cascadeStyleList = new ArrayList(); - for ( CascadeStyle style : cascadeStyles ) { - if ( style != CascadeStyles.NONE ) { - cascadeStyleList.add( style ); - } - } - if ( cascadeStyleList.isEmpty() ) { - cascadeStyle = CascadeStyles.NONE; - } - else if ( cascadeStyleList.size() == 1 ) { - cascadeStyle = cascadeStyleList.get( 0 ); - } - else { - cascadeStyle = new CascadeStyles.MultipleCascadeStyle( - cascadeStyleList.toArray( new CascadeStyle[ cascadeStyleList.size() ] ) - ); - } - } - - @Override - public FetchTiming getFetchTiming() { - return fetchTiming; - } - - @Override - public void setFetchTiming(FetchTiming fetchTiming) { - this.fetchTiming = fetchTiming; - } - - @Override - public FetchStyle getFetchStyle() { - return fetchStyle; - } - - @Override - public void setFetchStyle(FetchStyle fetchStyle) { - if ( fetchStyle == FetchStyle.SUBSELECT ) { - throw new AssertionFailure( "Subselect fetching not yet supported for singular associations" ); - } - this.fetchStyle = fetchStyle; - } - - @Override - public FetchMode getFetchMode() { - if ( fetchStyle == FetchStyle.JOIN ) { - return FetchMode.JOIN; - } - else if ( fetchStyle == FetchStyle.SELECT ) { - return FetchMode.SELECT; - } - else if ( fetchStyle == FetchStyle.BATCH ) { - // we need the subsequent select... - return FetchMode.SELECT; - } - - throw new AssertionFailure( "Unexpected fetch style : " + fetchStyle.name() ); - } - - @Override - public final boolean isReferenceResolved() { - return referencedAttributeBinding != null; - } - - @Override - public final void resolveReference(AttributeBinding referencedAttributeBinding) { - if ( ! EntityBinding.class.isInstance( referencedAttributeBinding.getContainer() ) ) { - throw new AssertionFailure( "Illegal attempt to resolve many-to-one reference based on non-entity attribute" ); - } - final EntityBinding entityBinding = (EntityBinding) referencedAttributeBinding.getContainer(); - if ( !referencedEntityName.equals( entityBinding.getEntity().getName() ) ) { - throw new IllegalStateException( - "attempt to set EntityBinding with name: [" + - entityBinding.getEntity().getName() + - "; entity name should be: " + referencedEntityName - ); - } - if ( referencedAttributeName == null ) { - referencedAttributeName = referencedAttributeBinding.getAttribute().getName(); - } - else if ( !referencedAttributeName.equals( referencedAttributeBinding.getAttribute().getName() ) ) { - throw new IllegalStateException( - "Inconsistent attribute name; expected: " + referencedAttributeName + - "actual: " + referencedAttributeBinding.getAttribute().getName() - ); - } - this.referencedAttributeBinding = referencedAttributeBinding; -// buildForeignKey(); - } - - @Override - public AttributeBinding getReferencedAttributeBinding() { - if ( !isReferenceResolved() ) { - throw new IllegalStateException( "Referenced AttributeBiding has not been resolved." ); - } - return referencedAttributeBinding; - } - - @Override - public final EntityBinding getReferencedEntityBinding() { - return (EntityBinding) referencedAttributeBinding.getContainer(); - } - -// private void buildForeignKey() { -// // TODO: move this stuff to relational model -// ForeignKey foreignKey = getValue().getTable() -// .createForeignKey( referencedAttributeBinding.getValue().getTable(), foreignKeyName ); -// Iterator referencingValueIterator = getSimpleValues().iterator(); -// Iterator targetValueIterator = referencedAttributeBinding.getSimpleValues().iterator(); -// while ( referencingValueIterator.hasNext() ) { -// if ( !targetValueIterator.hasNext() ) { -// // TODO: improve this message -// throw new MappingException( -// "number of values in many-to-one reference is greater than number of values in target" -// ); -// } -// SimpleValue referencingValue = referencingValueIterator.next(); -// SimpleValue targetValue = targetValueIterator.next(); -// if ( Column.class.isInstance( referencingValue ) ) { -// if ( !Column.class.isInstance( targetValue ) ) { -// // TODO improve this message -// throw new MappingException( "referencing value is a column, but target is not a column" ); -// } -// foreignKey.addColumnMapping( Column.class.cast( referencingValue ), Column.class.cast( targetValue ) ); -// } -// else if ( Column.class.isInstance( targetValue ) ) { -// // TODO: improve this message -// throw new MappingException( "referencing value is not a column, but target is a column." ); -// } -// } -// if ( targetValueIterator.hasNext() ) { -// throw new MappingException( "target value has more simple values than referencing value" ); -// } -// } -// -// public void validate() { -// // can't check this until both the domain and relational states are initialized... -// if ( getCascadeTypes().contains( CascadeType.DELETE_ORPHAN ) ) { -// if ( !isLogicalOneToOne ) { -// throw new MappingException( -// "many-to-one attribute [" + locateAttribute().getName() + "] does not support orphan delete as it is not unique" -// ); -// } -// } -// //TODO: validate that the entity reference is resolved -// } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java deleted file mode 100644 index a2b38037fd4e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/OneToManyCollectionElement.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class OneToManyCollectionElement extends AbstractCollectionElement { - - OneToManyCollectionElement(AbstractPluralAttributeBinding binding) { - super( binding ); - } - - @Override - public CollectionElementNature getCollectionElementNature() { - return CollectionElementNature.ONE_TO_MANY; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java deleted file mode 100644 index df48c1e2296d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Comparator; - -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.persister.collection.CollectionPersister; - -/** - * @author Steve Ebersole - */ -public interface PluralAttributeBinding extends AssociationAttributeBinding { - // todo : really it is the element (and/or index) that can be associative not the collection itself... - - @Override - public PluralAttribute getAttribute(); - - public CollectionKey getCollectionKey(); - - public AbstractCollectionElement getCollectionElement(); - - public TableSpecification getCollectionTable(); - - public boolean isMutable(); - - public Caching getCaching(); - - public Class getCollectionPersisterClass(); - - public String getCustomLoaderName(); - - public CustomSQL getCustomSqlInsert(); - - public CustomSQL getCustomSqlUpdate(); - - public CustomSQL getCustomSqlDelete(); - - public CustomSQL getCustomSqlDeleteAll(); - - public boolean isOrphanDelete(); - - String getWhere(); - - boolean isSorted(); - - Comparator getComparator(); - - int getBatchSize(); - - java.util.Map getFilterMap(); - - boolean isInverse(); - - String getOrderBy(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SetBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SetBinding.java deleted file mode 100644 index 98a0b05d0273..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SetBinding.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.Comparator; - -import org.hibernate.metamodel.domain.PluralAttribute; - -/** - * @author Steve Ebersole - */ -public class SetBinding extends AbstractPluralAttributeBinding { - private Comparator comparator; - - protected SetBinding( - AttributeBindingContainer container, - PluralAttribute attribute, - CollectionElementNature collectionElementNature) { - super( container, attribute, collectionElementNature ); - } - - public Comparator getComparator() { - return comparator; - } - - public void setComparator(Comparator comparator) { - this.comparator = comparator; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java deleted file mode 100644 index 0a8dd1afc314..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleValueBinding.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.SimpleValue; - -/** - * @author Steve Ebersole - */ -public class SimpleValueBinding { - private SimpleValue simpleValue; - private boolean includeInInsert; - private boolean includeInUpdate; - - public SimpleValueBinding() { - this( true, true ); - } - - public SimpleValueBinding(SimpleValue simpleValue) { - this(); - setSimpleValue( simpleValue ); - } - - public SimpleValueBinding(SimpleValue simpleValue, boolean includeInInsert, boolean includeInUpdate) { - this( includeInInsert, includeInUpdate ); - setSimpleValue( simpleValue ); - } - - public SimpleValueBinding(boolean includeInInsert, boolean includeInUpdate) { - this.includeInInsert = includeInInsert; - this.includeInUpdate = includeInUpdate; - } - - public SimpleValue getSimpleValue() { - return simpleValue; - } - - public void setSimpleValue(SimpleValue simpleValue) { - this.simpleValue = simpleValue; - if ( DerivedValue.class.isInstance( simpleValue ) ) { - includeInInsert = false; - includeInUpdate = false; - } - } - - public boolean isDerived() { - return DerivedValue.class.isInstance( simpleValue ); - } - - public boolean isNullable() { - return isDerived() || Column.class.cast( simpleValue ).isNullable(); - } - - /** - * Is the value to be inserted as part of its binding here? - *

    - * NOTE that a column may be bound to multiple attributes. The purpose of this value is to track this - * notion of "insertability" for this particular binding. - * - * @return {@code true} indicates the value should be included; {@code false} indicates it should not - */ - public boolean isIncludeInInsert() { - return includeInInsert; - } - - public void setIncludeInInsert(boolean includeInInsert) { - this.includeInInsert = includeInInsert; - } - - public boolean isIncludeInUpdate() { - return includeInUpdate; - } - - public void setIncludeInUpdate(boolean includeInUpdate) { - this.includeInUpdate = includeInUpdate; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAssociationAttributeBinding.java deleted file mode 100644 index eb1e60c88dc9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAssociationAttributeBinding.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -/** - * Contract describing the attribute binding for singular associations ({@code many-to-one}, {@code one-to-one}). - * - * @author Gail Badner - * @author Steve Ebersole - */ -@SuppressWarnings( {"JavaDoc", "UnusedDeclaration"}) -public interface SingularAssociationAttributeBinding extends SingularAttributeBinding, AssociationAttributeBinding { - /** - * Is this association based on a property reference (non PK column(s) as target of FK)? - *

    - * Convenience form of checking {@link #getReferencedAttributeName()} for {@code null}. - * - * @return - */ - public boolean isPropertyReference(); - - /** - * Obtain the name of the referenced entity. - * - * @return The referenced entity name - */ - public String getReferencedEntityName(); - - /** - * Set the name of the - * @param referencedEntityName - */ - public void setReferencedEntityName(String referencedEntityName); - - public String getReferencedAttributeName(); - public void setReferencedAttributeName(String referencedAttributeName); - - - // "resolvable" - public void resolveReference(AttributeBinding attributeBinding); - public boolean isReferenceResolved(); - public EntityBinding getReferencedEntityBinding(); - public AttributeBinding getReferencedAttributeBinding(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java deleted file mode 100644 index 6baf951010d6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.relational.Value; - -/** - * Specialized binding contract for singular (non-collection) attributes - * - * @author Steve Ebersole - */ -public interface SingularAttributeBinding extends AttributeBinding { - /** - * Obtain the value bound here. This could potentially be a {@link org.hibernate.metamodel.relational.Tuple} - * indicating multiple database values are bound, in which case access to the individual values can be achieved by - * either casting this return to {@link org.hibernate.metamodel.relational.Tuple} and using its - * {@link org.hibernate.metamodel.relational.Tuple#values()} method or using the {@link #getSimpleValueBindings()} - * method here and accessing each bindings {@link SimpleValueBinding#getSimpleValue simple value} - * - * @return The bound value - */ - public Value getValue(); - - /** - * Returns the number of {@link SimpleValueBinding} objects that will be returned by - * {@link #getSimpleValueBindings()} - * - * @return the number of {@link SimpleValueBinding simple value bindings} - * - * @see #getSimpleValueBindings() - */ - public int getSimpleValueSpan(); - - public Iterable getSimpleValueBindings(); - - public void setSimpleValueBindings(Iterable simpleValueBindings); - - /** - * Convenience method to determine if any {@link SimpleValueBinding simple value bindings} are derived values - * (formula mappings). - * - * @return {@code true} indicates that the binding contains a derived value; {@code false} indicates it does not. - */ - public boolean hasDerivedValue(); - - /** - * Convenience method to determine if all {@link SimpleValueBinding simple value bindings} allow nulls. - * - * @return {@code true} indicates that all values allow {@code null}; {@code false} indicates one or more do not - */ - public boolean isNullable(); - - /** - * Obtain the generation strategy for this attribute/value. - * - * @return The generation strategy - */ - public PropertyGeneration getGeneration(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/TypeDef.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/TypeDef.java deleted file mode 100644 index a272eec5adf5..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/TypeDef.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; - -/** - * Represents the metamodel view of a typedef (type definition). - * - * @author John Verhaeg - */ -public class TypeDef implements Serializable { - private final String name; - private final String typeClass; - private final Map parameters; - - public TypeDef(String name, String typeClass, Map parameters) { - this.name = name; - this.typeClass = typeClass; - this.parameters = parameters; - } - - public String getName() { - return name; - } - - public String getTypeClass() { - return typeClass; - } - - public Map getParameters() { - return Collections.unmodifiableMap(parameters); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AbstractAttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AbstractAttributeContainer.java deleted file mode 100644 index 3258f7de7071..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AbstractAttributeContainer.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; - -/** - * Convenient base class for {@link AttributeContainer}. Because in our model all - * {@link AttributeContainer AttributeContainers} are also {@link Hierarchical} we also implement that here - * as well. - * - * @author Steve Ebersole - */ -public abstract class AbstractAttributeContainer implements AttributeContainer, Hierarchical { - private final String name; - private final String className; - private final ValueHolder> classReference; - private final Hierarchical superType; - private LinkedHashSet attributeSet = new LinkedHashSet(); - private HashMap attributeMap = new HashMap(); - - public AbstractAttributeContainer(String name, String className, ValueHolder> classReference, Hierarchical superType) { - this.name = name; - this.className = className; - this.classReference = classReference; - this.superType = superType; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getClassName() { - return className; - } - - @Override - public Class getClassReference() { - return classReference.getValue(); - } - - @Override - public ValueHolder> getClassReferenceUnresolved() { - return classReference; - } - - @Override - public Hierarchical getSuperType() { - return superType; - } - - @Override - public Set attributes() { - return Collections.unmodifiableSet( attributeSet ); - } - - @Override - public String getRoleBaseName() { - return getClassName(); - } - - @Override - public Attribute locateAttribute(String name) { - return attributeMap.get( name ); - } - - @Override - public SingularAttribute locateSingularAttribute(String name) { - return (SingularAttribute) locateAttribute( name ); - } - - @Override - public SingularAttribute createSingularAttribute(String name) { - SingularAttribute attribute = new SingularAttributeImpl( name, this ); - addAttribute( attribute ); - return attribute; - } - - @Override - public SingularAttribute createVirtualSingularAttribute(String name) { - throw new NotYetImplementedException(); - } - - @Override - public SingularAttribute locateComponentAttribute(String name) { - return (SingularAttributeImpl) locateAttribute( name ); - } - - @Override - public SingularAttribute createComponentAttribute(String name, Component component) { - SingularAttributeImpl attribute = new SingularAttributeImpl( name, this ); - attribute.resolveType( component ); - addAttribute( attribute ); - return attribute; - } - - @Override - public PluralAttribute locatePluralAttribute(String name) { - return (PluralAttribute) locateAttribute( name ); - } - - protected PluralAttribute createPluralAttribute(String name, PluralAttributeNature nature) { - PluralAttribute attribute = nature.isIndexed() - ? new IndexedPluralAttributeImpl( name, nature, this ) - : new PluralAttributeImpl( name, nature, this ); - addAttribute( attribute ); - return attribute; - } - - @Override - public PluralAttribute locateBag(String name) { - return locatePluralAttribute( name ); - } - - @Override - public PluralAttribute createBag(String name) { - return createPluralAttribute( name, PluralAttributeNature.BAG ); - } - - @Override - public PluralAttribute locateSet(String name) { - return locatePluralAttribute( name ); - } - - @Override - public PluralAttribute createSet(String name) { - return createPluralAttribute( name, PluralAttributeNature.SET ); - } - - @Override - public IndexedPluralAttribute locateList(String name) { - return (IndexedPluralAttribute) locatePluralAttribute( name ); - } - - @Override - public IndexedPluralAttribute createList(String name) { - return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.LIST ); - } - - @Override - public IndexedPluralAttribute locateMap(String name) { - return (IndexedPluralAttribute) locatePluralAttribute( name ); - } - - @Override - public IndexedPluralAttribute createMap(String name) { - return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.MAP ); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "AbstractAttributeContainer" ); - sb.append( "{name='" ).append( name ).append( '\'' ); - sb.append( ", superType=" ).append( superType ); - sb.append( '}' ); - return sb.toString(); - } - - protected void addAttribute(Attribute attribute) { - // todo : how to best "secure" this? - if ( attributeMap.put( attribute.getName(), attribute ) != null ) { - throw new IllegalArgumentException( "Attribute with name [" + attribute.getName() + "] already registered" ); - } - attributeSet.add( attribute ); - } - - // todo : inner classes for now.. - - public static class SingularAttributeImpl implements SingularAttribute { - private final AttributeContainer attributeContainer; - private final String name; - private Type type; - - public SingularAttributeImpl(String name, AttributeContainer attributeContainer) { - this.name = name; - this.attributeContainer = attributeContainer; - } - - public boolean isTypeResolved() { - return type != null; - } - - public void resolveType(Type type) { - if ( type == null ) { - throw new IllegalArgumentException( "Attempt to resolve with null type" ); - } - this.type = type; - } - - @Override - public Type getSingularAttributeType() { - return type; - } - - @Override - public String getName() { - return name; - } - - @Override - public AttributeContainer getAttributeContainer() { - return attributeContainer; - } - - @Override - public boolean isSingular() { - return true; - } - } - - public static class PluralAttributeImpl implements PluralAttribute { - private final AttributeContainer attributeContainer; - private final PluralAttributeNature nature; - private final String name; - - private Type elementType; - - public PluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { - this.name = name; - this.nature = nature; - this.attributeContainer = attributeContainer; - } - - @Override - public AttributeContainer getAttributeContainer() { - return attributeContainer; - } - - @Override - public boolean isSingular() { - return false; - } - - @Override - public PluralAttributeNature getNature() { - return nature; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getRole() { - return StringHelper.qualify( attributeContainer.getRoleBaseName(), name ); - } - - @Override - public Type getElementType() { - return elementType; - } - - @Override - public void setElementType(Type elementType) { - this.elementType = elementType; - } - } - - public static class IndexedPluralAttributeImpl extends PluralAttributeImpl implements IndexedPluralAttribute { - private Type indexType; - - public IndexedPluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { - super( name, nature, attributeContainer ); - } - - @Override - public Type getIndexType() { - return indexType; - } - - @Override - public void setIndexType(Type indexType) { - this.indexType = indexType; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/BasicType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/BasicType.java deleted file mode 100644 index 682ce46afd89..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/BasicType.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.internal.util.ValueHolder; - -/** - * Models a basic type. - * - * @author Steve Ebersole - */ -public class BasicType implements Type { - private final String name; - private final ValueHolder> classReference; - - public BasicType(String name, ValueHolder> classReference) { - this.name = name; - this.classReference = classReference; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getClassName() { - return name; - } - - @Override - public Class getClassReference() { - return classReference.getValue(); - } - - @Override - public ValueHolder> getClassReferenceUnresolved() { - return classReference; - } - - @Override - public boolean isAssociation() { - return false; - } - - @Override - public boolean isComponent() { - return false; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Component.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Component.java deleted file mode 100644 index e300355a43a9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Component.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.internal.util.ValueHolder; - -/** - * Models the notion of a component (what JPA calls an Embeddable). - *

    - * NOTE : Components are not currently really hierarchical. But that is a feature I want to add. - * - * @author Steve Ebersole - */ -public class Component extends AbstractAttributeContainer { - public Component(String name, String className, ValueHolder> classReference, Hierarchical superType) { - super( name, className, classReference, superType ); - } - - @Override - public boolean isAssociation() { - return false; - } - - @Override - public boolean isComponent() { - return true; - } - - @Override - public String getRoleBaseName() { - // todo : this is not really completely accurate atm - // the role base here should really be the role of the component attribute. - return getClassName(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Entity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Entity.java deleted file mode 100644 index fc6b41f6a35e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Entity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.internal.util.ValueHolder; - -/** - * Models the notion of an entity - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class Entity extends AbstractAttributeContainer { - /** - * Constructor for the entity - * - * @param entityName The name of the entity - * @param className The name of this entity's java class - * @param classReference The reference to this entity's {@link Class} - * @param superType The super type for this entity. If there is not super type {@code null} needs to be passed. - */ - public Entity(String entityName, String className, ValueHolder> classReference, Hierarchical superType) { - super( entityName, className, classReference, superType ); - } - - @Override - public boolean isAssociation() { - return true; - } - - @Override - public boolean isComponent() { - return false; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/JavaType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/JavaType.java deleted file mode 100644 index 1b896069891e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/JavaType.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.util.ValueHolder; - -/** - * Models the naming of a Java type where we may not have access to that type's {@link Class} reference. Generally - * speaking this is the case in various hibernate-tools and reverse-engineering use cases. - * - * @author Steve Ebersole - */ -public class JavaType { - private final String name; - private final ValueHolder> classReference; - - public JavaType(final String name, final ClassLoaderService classLoaderService) { - this.name = name; - this.classReference = new ValueHolder>( - new ValueHolder.DeferredInitializer>() { - @Override - public Class initialize() { - return classLoaderService.classForName( name ); - } - } - ); - } - - public JavaType(Class theClass) { - this.name = theClass.getName(); - this.classReference = new ValueHolder>( theClass ); - } - - public String getName() { - return name; - } - - public Class getClassReference() { - return classReference.getValue(); - } - - @Override - public String toString() { - return new StringBuilder( super.toString() ) - .append( "[name=" ).append( name ).append( "]" ) - .toString(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/NonEntity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/NonEntity.java deleted file mode 100644 index 973dc8af6e49..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/NonEntity.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.internal.util.ValueHolder; - -/** - * Models the concept class in the hierarchy with no persistent attributes. - * - * @author Hardy Ferentschik - */ -public class NonEntity extends AbstractAttributeContainer { - /** - * Constructor for the non-entity - * - * @param entityName The name of the non-entity - * @param className The name of this non-entity's java class - * @param classReference The reference to this non-entity's {@link Class} - * @param superType The super type for this non-entity. If there is not super type {@code null} needs to be passed. - */ - public NonEntity(String entityName, String className, ValueHolder> classReference, Hierarchical superType) { - super( entityName, className, classReference, superType ); - } - - @Override - public boolean isAssociation() { - return true; - } - - @Override - public boolean isComponent() { - return false; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttribute.java deleted file mode 100644 index 4914f05da1ff..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttribute.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -/** - * TODO : javadoc - * - * @author Steve Ebersole - */ -public interface PluralAttribute extends Attribute { - public String getRole(); - public PluralAttributeNature getNature(); - public Type getElementType(); - public void setElementType(Type elementType); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttributeNature.java deleted file mode 100644 index 492299ad68d0..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/PluralAttributeNature.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Identifies the specific semantic of a plural valued attribute. - * - * @author Steve Ebersole - */ -public enum PluralAttributeNature { - BAG( "bag", Collection.class ), - IDBAG( "idbag", Collection.class ), - SET( "set", Set.class ), - LIST( "list", List.class ), - MAP( "map", Map.class ); - - private final String name; - private final Class javaContract; - private final boolean indexed; - - PluralAttributeNature(String name, Class javaContract) { - this.name = name; - this.javaContract = javaContract; - this.indexed = Map.class.isAssignableFrom( javaContract ) || List.class.isAssignableFrom( javaContract ); - } - - public String getName() { - return name; - } - - public Class getJavaContract() { - return javaContract; - } - - public boolean isIndexed() { - return indexed; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/SingularAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/SingularAttribute.java deleted file mode 100644 index f27b61fced26..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/SingularAttribute.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -/** - * A single valued (non-collection) attribute - * - * @author Steve Ebersole - */ -public interface SingularAttribute extends Attribute { - /** - * Retrieve the attribute type descriptor. - * - * @return THe attribute type. - */ - public Type getSingularAttributeType(); - - public boolean isTypeResolved(); - - public void resolveType(Type type); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Superclass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Superclass.java deleted file mode 100644 index 4a5a09533900..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Superclass.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.internal.util.ValueHolder; - -/** - * Models the concept of a (intermediate) superclass - * - * @author Steve Ebersole - */ -public class Superclass extends AbstractAttributeContainer { - /** - * Constructor for the entity - * - * @param entityName The name of the entity - * @param className The name of this entity's java class - * @param classReference The reference to this entity's {@link Class} - * @param superType The super type for this entity. If there is not super type {@code null} needs to be passed. - */ - public Superclass(String entityName, String className, ValueHolder> classReference, Hierarchical superType) { - super( entityName, className, classReference, superType ); - } - - @Override - public boolean isAssociation() { - return true; - } - - @Override - public boolean isComponent() { - return false; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Type.java b/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Type.java deleted file mode 100644 index 58d0f9592a53..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Type.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.domain; - -import org.hibernate.internal.util.ValueHolder; - -/** - * Basic information about a Java type, in regards to its role in particular set of mappings. - * - * @author Steve Ebersole - */ -public interface Type { - /** - * Obtain the name of the type. - * - * @return The name - */ - public String getName(); - - /** - * Obtain the java class name for this type. - * - * @return The class name - */ - public String getClassName(); - - /** - * Obtain the java {@link Class} reference for this type - * - * @return The {@link Class} reference - * - * @throws org.hibernate.boot.registry.classloading.spi.ClassLoadingException Indicates the class reference - * could not be determined. Generally this is the case in reverse-engineering scenarios where the specified - * domain model classes do not yet exist. - */ - public Class getClassReference(); - - public ValueHolder> getClassReferenceUnresolved(); - - public boolean isAssociation(); - - public boolean isComponent(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java new file mode 100644 index 000000000000..2a30722c7215 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.metamodel.spi.ClassLoaderAccess; + +import org.jboss.logging.Logger; + +/** + * @author Steve Ebersole + */ +public class ClassLoaderAccessImpl implements ClassLoaderAccess { + private static final Logger log = Logger.getLogger( ClassLoaderAccessImpl.class ); + + private final ClassLoader jpaTempClassLoader; + private final ClassLoaderService classLoaderService; + + public ClassLoaderAccessImpl( + ClassLoader jpaTempClassLoader, + ClassLoaderService classLoaderService) { + this.jpaTempClassLoader = jpaTempClassLoader; + this.classLoaderService = classLoaderService; + } + + public ClassLoaderAccessImpl(ClassLoader tempClassLoader, StandardServiceRegistry serviceRegistry) { + this( tempClassLoader, serviceRegistry.getService( ClassLoaderService.class ) ); + } + + @Override + public Class classForName(String name) { + if ( isSafeClass( name ) ) { + return classLoaderService.classForName( name ); + } + else { + log.debugf( "Not known whether passed class name [%s] is safe", name ); + if ( jpaTempClassLoader == null ) { + log.debugf( + "No temp ClassLoader provided; using live ClassLoader " + + "for loading potentially unsafe class : %s", + name + ); + return classLoaderService.classForName( name ); + } + else { + log.debugf( + "Temp ClassLoader was provided, so we will use that : %s", + name + ); + try { + return jpaTempClassLoader.loadClass( name ); + } + catch (ClassNotFoundException e) { + throw new ClassLoadingException( name ); + } + } + } + } + + private boolean isSafeClass(String name) { + // classes in any of these packages are safe to load through the "live" ClassLoader + return name.startsWith( "java." ) + || name.startsWith( "javax." ) + || name.startsWith( "org.hibernate" ); + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuilderImpl.java new file mode 100644 index 000000000000..a120a1b338ac --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuilderImpl.java @@ -0,0 +1,425 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.SharedCacheMode; + +import org.hibernate.HibernateException; +import org.hibernate.MultiTenancyStrategy; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.EJB3DTDEntityResolver; +import org.hibernate.cfg.EJB3NamingStrategy; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSourceProcessingOrder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataSourcesContributor; +import org.hibernate.metamodel.spi.PersistentAttributeMemberResolver; +import org.hibernate.metamodel.spi.StandardPersistentAttributeMemberResolver; +import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.spi.TypeContributor; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.type.BasicType; +import org.hibernate.type.CompositeCustomType; +import org.hibernate.type.CustomType; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; + +import org.jboss.jandex.IndexView; +import org.jboss.logging.Logger; + +import org.xml.sax.EntityResolver; + +/** + * The implementation of the {@link MetadataBuilder} contract. + * + * @author Steve Ebersole + */ +public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions { + private static final Logger log = Logger.getLogger( MetadataBuilderImpl.class ); + + private final MetadataSources sources; + private final Options options; + + public MetadataBuilderImpl(MetadataSources sources) { + this( + sources, + getStandardServiceRegistry( sources.getServiceRegistry() ) + ); + } + + private static StandardServiceRegistry getStandardServiceRegistry(ServiceRegistry serviceRegistry) { + if ( serviceRegistry == null ) { + throw new HibernateException( "ServiceRegistry passed to MetadataBuilder cannot be null" ); + } + + if ( StandardServiceRegistry.class.isInstance( serviceRegistry ) ) { + return ( StandardServiceRegistry ) serviceRegistry; + } + else if ( BootstrapServiceRegistry.class.isInstance( serviceRegistry ) ) { + log.debugf( + "ServiceRegistry passed to MetadataBuilder was a BootstrapServiceRegistry; this likely wont end well" + + "if attempt is made to build SessionFactory" + ); + return new StandardServiceRegistryBuilder( (BootstrapServiceRegistry) serviceRegistry ).build(); + } + else { + throw new HibernateException( + String.format( + "Unexpected type of ServiceRegistry [%s] encountered in attempt to build MetadataBuilder", + serviceRegistry.getClass().getName() + ) + ); + } + } + + public MetadataBuilderImpl(MetadataSources sources, StandardServiceRegistry serviceRegistry) { + this.sources = sources; + + for ( MetadataSourcesContributor contributor : + sources.getServiceRegistry().getService( ClassLoaderService.class ) + .loadJavaServices( MetadataSourcesContributor.class ) ) { + contributor.contribute( sources, null ); + } + this.options = new Options( serviceRegistry ); + } + + @Override + public MetadataBuilder with(NamingStrategy namingStrategy) { + this.options.namingStrategy = namingStrategy; + return this; + } + + @Override + public MetadataBuilder with(EntityResolver entityResolver) { + this.options.entityResolver = entityResolver; + return this; + } + + @Override + public MetadataBuilder with(MetadataSourceProcessingOrder metadataSourceProcessingOrder) { + this.options.metadataSourceProcessingOrder = metadataSourceProcessingOrder; + return this; + } + + @Override + public MetadataBuilder with(SharedCacheMode sharedCacheMode) { + this.options.sharedCacheMode = sharedCacheMode; + return this; + } + + @Override + public MetadataBuilder with(AccessType accessType) { + this.options.defaultCacheAccessType = accessType; + return this; + } + + @Override + public MetadataBuilder with(IndexView jandexView) { + this.options.jandexView = jandexView; + return this; + } + + @Override + public MetadataBuilder withNewIdentifierGeneratorsEnabled(boolean enabled) { + this.options.useNewIdentifierGenerators = enabled; + return this; + } + + @Override + public MetadataBuilder withExplicitDiscriminatorsForJoinedSubclassSupport(boolean supported) { + options.explicitDiscriminatorsForJoinedInheritanceSupported = supported; + return this; + } + + @Override + public MetadataBuilder withImplicitDiscriminatorsForJoinedSubclassSupport(boolean supported) { + options.implicitDiscriminatorsForJoinedInheritanceSupported = supported; + return this; + } + + @Override + public MetadataBuilder with(BasicType type) { + options.basicTypeRegistrations.add( type ); + return this; + } + + @Override + public MetadataBuilder with(UserType type, String[] keys) { + options.basicTypeRegistrations.add( new CustomType( type, keys ) ); + return this; + } + + @Override + public MetadataBuilder with(CompositeUserType type, String[] keys) { + options.basicTypeRegistrations.add( new CompositeCustomType( type, keys ) ); + return this; + } + + @Override + public MetadataBuilder with(TypeContributor typeContributor) { + typeContributor.contribute( this, options.serviceRegistry ); + return this; + } + + @Override + public void contributeType(BasicType type) { + options.basicTypeRegistrations.add( type ); + } + + @Override + public void contributeType(UserType type, String[] keys) { + options.basicTypeRegistrations.add( new CustomType( type, keys ) ); + } + + @Override + public void contributeType(CompositeUserType type, String[] keys) { + options.basicTypeRegistrations.add( new CompositeCustomType( type, keys ) ); + } + + @Override + public MetadataBuilder with(CacheRegionDefinition cacheRegionDefinition) { + if ( options.cacheRegionDefinitions == null ) { + options.cacheRegionDefinitions = new ArrayList(); + } + options.cacheRegionDefinitions.add( cacheRegionDefinition ); + return this; + } + + @Override + public MetadataBuilder with(ClassLoader tempClassLoader) { + options.tempClassLoader = tempClassLoader; + return this; + } + + @Override + public MetadataBuilder with(PersistentAttributeMemberResolver resolver) { + options.persistentAttributeMemberResolver = resolver; + return this; + } + + @Override + public MetadataImpl build() { + return MetadataBuildingProcess.build( sources, options ); + } + + /** + * Implementation of the Database.Defaults contract + */ + public static class DatabaseDefaults implements Database.Defaults { + private boolean globallyQuotedIdentifiers; + private String defaultSchemaName; + private String defaultCatalogName; + + public DatabaseDefaults(ConfigurationService configurationService) { + defaultSchemaName = configurationService.getSetting( + AvailableSettings.DEFAULT_SCHEMA, + StandardConverters.STRING, + null + ); + + defaultCatalogName = configurationService.getSetting( + AvailableSettings.DEFAULT_CATALOG, + StandardConverters.STRING, + null + ); + + globallyQuotedIdentifiers = configurationService.getSetting( + AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, + StandardConverters.BOOLEAN, + false + ); + } + + @Override + public String getDefaultSchemaName() { + return defaultSchemaName; + } + + @Override + public String getDefaultCatalogName() { + return defaultCatalogName; + } + + @Override + public boolean isGloballyQuotedIdentifiers() { + return globallyQuotedIdentifiers; + } + } + + public static class Options implements org.hibernate.metamodel.spi.MetadataBuildingOptions { + private final StandardServiceRegistry serviceRegistry; + private final DatabaseDefaults databaseDefaults; + + private List basicTypeRegistrations = new ArrayList(); + + private IndexView jandexView; + private ClassLoader tempClassLoader; + private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE; + private SharedCacheMode sharedCacheMode = SharedCacheMode.ENABLE_SELECTIVE; + private AccessType defaultCacheAccessType; + private boolean useNewIdentifierGenerators; + private MultiTenancyStrategy multiTenancyStrategy; + private List cacheRegionDefinitions; + private boolean explicitDiscriminatorsForJoinedInheritanceSupported; + private boolean implicitDiscriminatorsForJoinedInheritanceSupported; + + private PersistentAttributeMemberResolver persistentAttributeMemberResolver = + StandardPersistentAttributeMemberResolver.INSTANCE; + + // todo : go away + private MetadataSourceProcessingOrder metadataSourceProcessingOrder = MetadataSourceProcessingOrder.HBM_FIRST; + private EntityResolver entityResolver = EJB3DTDEntityResolver.INSTANCE; + + public Options(StandardServiceRegistry serviceRegistry) { + this.serviceRegistry = serviceRegistry; + + final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class ); + this.databaseDefaults = new DatabaseDefaults( configService ); + + // cache access type + defaultCacheAccessType = configService.getSetting( + AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY, + new ConfigurationService.Converter() { + @Override + public AccessType convert(Object value) { + return AccessType.fromExternalName( value.toString() ); + } + } + ); + + useNewIdentifierGenerators = configService.getSetting( + AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, + StandardConverters.BOOLEAN, + false + ); + + multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configService.getSettings() ); + + implicitDiscriminatorsForJoinedInheritanceSupported = configService.getSetting( + AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, + StandardConverters.BOOLEAN, + false + ); + + explicitDiscriminatorsForJoinedInheritanceSupported = !configService.getSetting( + AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, + StandardConverters.BOOLEAN, + false + ); + } + + @Override + public StandardServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + @Override + public DatabaseDefaults getDatabaseDefaults() { + return databaseDefaults; + } + + @Override + public List getBasicTypeRegistrations() { + return basicTypeRegistrations; + } + + @Override + public IndexView getJandexView() { + return jandexView; + } + + @Override + public ClassLoader getTempClassLoader() { + return tempClassLoader; + } + + @Override + public NamingStrategy getNamingStrategy() { + return namingStrategy; + } + + @Override + public SharedCacheMode getSharedCacheMode() { + return sharedCacheMode; + } + + @Override + public AccessType getDefaultCacheAccessType() { + return defaultCacheAccessType; + } + + @Override + public boolean isUseNewIdentifierGenerators() { + return useNewIdentifierGenerators; + } + + @Override + public MultiTenancyStrategy getMultiTenancyStrategy() { + return multiTenancyStrategy; + } + + @Override + public List getCacheRegionDefinitions() { + return cacheRegionDefinitions; + } + + @Override + public boolean ignoreExplicitDiscriminatorsForJoinedInheritance() { + return !explicitDiscriminatorsForJoinedInheritanceSupported; + } + + @Override + public boolean createImplicitDiscriminatorsForJoinedInheritance() { + return implicitDiscriminatorsForJoinedInheritanceSupported; + } + + @Override + public PersistentAttributeMemberResolver getPersistentAttributeMemberResolver() { + return persistentAttributeMemberResolver; + } + + @Override + public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder() { + return metadataSourceProcessingOrder; + } + + @Override + public EntityResolver getEntityResolver() { + return entityResolver; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java new file mode 100644 index 000000000000..9e9d390445ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java @@ -0,0 +1,1197 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.hibernate.AssertionFailure; +import org.hibernate.DuplicateMappingException; +import org.hibernate.EntityMode; +import org.hibernate.MappingException; +import org.hibernate.SessionFactory; +import org.hibernate.annotations.common.util.StringHelper; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.engine.spi.NamedQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.SyntheticAttributeHelper; +import org.hibernate.id.factory.IdentifierGeneratorFactory; +import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.MetadataSourceProcessingOrder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.NamedStoredProcedureQueryDefinition; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.reflite.internal.JavaTypeDescriptorRepositoryImpl; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.internal.annotations.AnnotationMetadataSourceProcessorImpl; +import org.hibernate.metamodel.source.internal.annotations.JandexAccess; +import org.hibernate.metamodel.source.internal.annotations.JandexAccessImpl; +import org.hibernate.metamodel.source.internal.hbm.HbmMetadataSourceProcessorImpl; +import org.hibernate.metamodel.source.internal.jandex.Unifier; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.FilterParameterSource; +import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource; +import org.hibernate.metamodel.source.spi.MappingDefaults; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; +import org.hibernate.metamodel.spi.AdditionalJaxbRootProducer; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.ClassLoaderAccess; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.MetadataBuildingOptions; +import org.hibernate.metamodel.spi.MetadataContributor; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.spi.TypeContributor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BackRefAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.domain.BasicType; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.type.BasicTypeRegistry; +import org.hibernate.type.TypeFactory; +import org.hibernate.type.TypeResolver; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; +import org.hibernate.xml.spi.BindResult; + +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; +import org.jboss.logging.Logger; + +import static org.hibernate.metamodel.spi.AdditionalJaxbRootProducer.AdditionalJaxbRootProducerContext; + +/** + * Represents the process of building a Metadata object. The main entry point is the + * static {@link #build} + * + * @author Steve Ebersole + */ +public class MetadataBuildingProcess { + private static final Logger log = Logger.getLogger( MetadataBuildingProcess.class ); + + public static MetadataImpl build(MetadataSources sources, final MetadataBuildingOptions options) { + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // preliminary phases + final IndexView jandexView = handleJandex( options, sources ); + final BasicTypeRegistry basicTypeRegistry = handleTypes( options ); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // prep to start handling binding in earnest + final MappingDefaultsImpl mappingDefaults = new MappingDefaultsImpl( options ); + final ClassLoaderAccess classLoaderAccess = new ClassLoaderAccessImpl( + options.getTempClassLoader(), + options.getServiceRegistry() + ); + final JandexAccessImpl jandexAccess = new JandexAccessImpl( + jandexView, + classLoaderAccess + + ); + final JavaTypeDescriptorRepository javaTypeDescriptorRepository = new JavaTypeDescriptorRepositoryImpl( + jandexAccess, + classLoaderAccess + ); + final InFlightMetadataCollectorImpl metadataCollector = new InFlightMetadataCollectorImpl( + options, + new TypeResolver( basicTypeRegistry, new TypeFactory() ) + ); + final RootBindingContextImpl rootBindingContext = new RootBindingContextImpl( + options, + mappingDefaults, + javaTypeDescriptorRepository, + jandexAccess, + classLoaderAccess, + metadataCollector + ); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Set up the processors and start binding + // NOTE : this becomes even more simplified after we move purely + // to unified model + + final MetadataSourceProcessor[] metadataSourceProcessors; + if ( options.getMetadataSourceProcessingOrder() == MetadataSourceProcessingOrder.HBM_FIRST ) { + metadataSourceProcessors = new MetadataSourceProcessor[] { + new HbmMetadataSourceProcessorImpl( rootBindingContext, sources ), + new AnnotationMetadataSourceProcessorImpl( rootBindingContext, jandexView ) + }; + } + else { + metadataSourceProcessors = new MetadataSourceProcessor[] { + new AnnotationMetadataSourceProcessorImpl( rootBindingContext, jandexView ), + new HbmMetadataSourceProcessorImpl( rootBindingContext, sources ) + }; + } + + processTypeDefinitions( metadataSourceProcessors, rootBindingContext ); + processFilterDefinitions( metadataSourceProcessors, rootBindingContext ); + processIdentifierGenerators( metadataSourceProcessors, rootBindingContext ); + processMappings( metadataSourceProcessors, rootBindingContext ); + bindMappingDependentMetadata( metadataSourceProcessors, rootBindingContext ); + + final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class ); + + for ( MetadataContributor contributor : classLoaderService.loadJavaServices( MetadataContributor.class ) ) { + contributor.contribute( metadataCollector, jandexView ); + } + + final List bindResults = new ArrayList(); + final AdditionalJaxbRootProducerContext jaxbRootProducerContext = new AdditionalJaxbRootProducerContext() { + @Override + public IndexView getJandexIndex() { + return jandexView; + } + + @Override + public StandardServiceRegistry getServiceRegistry() { + return options.getServiceRegistry(); + } + }; + for ( AdditionalJaxbRootProducer producer : classLoaderService.loadJavaServices( AdditionalJaxbRootProducer.class ) ) { + bindResults.addAll( producer.produceRoots( metadataCollector, jaxbRootProducerContext ) ); + } + final HbmMetadataSourceProcessorImpl processor = new HbmMetadataSourceProcessorImpl( rootBindingContext, bindResults ); + final Binder binder = new Binder( rootBindingContext ); + binder.addEntityHierarchies( processor.extractEntityHierarchies() ); + binder.bindEntityHierarchies(); + + secondPass( rootBindingContext ); + + return metadataCollector.buildMetadataInstance(); + } + + private static IndexView handleJandex(MetadataBuildingOptions options, MetadataSources sources) { + final ConfigurationService configurationService = options.getServiceRegistry().getService( ConfigurationService.class ); + + final IndexView baseJandexIndex; + if ( options.getJandexView() != null ) { + baseJandexIndex = options.getJandexView(); + } + else { + final boolean autoIndexMemberTypes = configurationService.getSetting( + AvailableSettings.ENABLE_AUTO_INDEX_MEMBER_TYPES, + StandardConverters.BOOLEAN, + false + ); + baseJandexIndex = sources.buildJandexView( autoIndexMemberTypes ); + } + + final List> jpaXmlBindings = new ArrayList>(); + for ( BindResult bindResult : sources.getBindResultList() ) { + if ( JaxbEntityMappings.class.isInstance( bindResult.getRoot() ) ) { + // todo : this will be checked after hbm transformation is in place. + //noinspection unchecked + jpaXmlBindings.add( bindResult ); + } + } + + return Unifier.unify( baseJandexIndex, jpaXmlBindings, options.getServiceRegistry() ); + } + + private static BasicTypeRegistry handleTypes(MetadataBuildingOptions options) { + final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class ); + + // ultimately this needs to change a little bit to account for HHH-7792 + final BasicTypeRegistry basicTypeRegistry = new BasicTypeRegistry(); + + final TypeContributions typeContributions = new TypeContributions() { + @Override + public void contributeType(org.hibernate.type.BasicType type) { + basicTypeRegistry.register( type ); + } + + @Override + public void contributeType(UserType type, String[] keys) { + basicTypeRegistry.register( type, keys ); + } + + @Override + public void contributeType(CompositeUserType type, String[] keys) { + basicTypeRegistry.register( type, keys ); + } + }; + + // add Dialect contributed types + final Dialect dialect = options.getServiceRegistry().getService( JdbcServices.class ).getDialect(); + dialect.contributeTypes( typeContributions, options.getServiceRegistry() ); + + // add TypeContributor contributed types. + for ( TypeContributor contributor : classLoaderService.loadJavaServices( TypeContributor.class ) ) { + contributor.contribute( typeContributions, options.getServiceRegistry() ); + } + + // add explicit application registered types + for ( org.hibernate.type.BasicType basicType : options.getBasicTypeRegistrations() ) { + basicTypeRegistry.register( basicType ); + } + + return basicTypeRegistry; + } + + private static void processTypeDefinitions( + MetadataSourceProcessor[] metadataSourceProcessors, + RootBindingContextImpl bindingContext) { + final ClassLoaderService cls = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + for ( TypeDescriptorSource typeDescriptorSource : processor.extractTypeDefinitionSources() ) { + bindingContext.getMetadataCollector().addTypeDefinition( + new TypeDefinition( + typeDescriptorSource.getName(), + cls.classForName( typeDescriptorSource.getTypeImplementationClassName() ), + typeDescriptorSource.getRegistrationKeys(), + typeDescriptorSource.getParameters() + ) + ); + } + } + } + + private static void processFilterDefinitions( + MetadataSourceProcessor[] metadataSourceProcessors, + RootBindingContextImpl bindingContext) { + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + for ( FilterDefinitionSource filterDefinitionSource : processor.extractFilterDefinitionSources() ) { + bindingContext.getMetadataCollector().addFilterDefinition( + new FilterDefinition( + filterDefinitionSource.getName(), + filterDefinitionSource.getCondition(), + resolveFilterDefinitionParamType( + filterDefinitionSource.getParameterSources(), + bindingContext + ) + ) + ); + } + } + } + + private static Map resolveFilterDefinitionParamType( + Iterable filterParameterSources, + RootBindingContextImpl bindingContext){ + if ( CollectionHelper.isEmpty( filterParameterSources ) ) { + return Collections.emptyMap(); + } + + Map params = new HashMap( ); + for(final FilterParameterSource parameterSource : filterParameterSources){ + final String name = parameterSource.getParameterName(); + final String typeName = parameterSource.getParameterValueTypeName(); + final org.hibernate.type.Type type = bindingContext.getMetadataCollector().getTypeResolver().heuristicType( + typeName + ); + params.put( name, type ); + } + return params; + } + + private static void processIdentifierGenerators( + MetadataSourceProcessor[] metadataSourceProcessors, + RootBindingContextImpl bindingContext) { + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + for ( IdentifierGeneratorSource identifierGeneratorSource : processor.extractGlobalIdentifierGeneratorSources() ) { + bindingContext.getMetadataCollector().addIdGenerator( + new IdentifierGeneratorDefinition( + identifierGeneratorSource.getGeneratorName(), + identifierGeneratorSource.getGeneratorImplementationName(), + identifierGeneratorSource.getParameters() + ) + ); + } + } + } + + private static void processMappings( + MetadataSourceProcessor[] metadataSourceProcessors, + RootBindingContextImpl bindingContext) { + final Binder binder = new Binder( bindingContext ); + // Add all hierarchies first, before binding. + for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { + binder.addEntityHierarchies( processor.extractEntityHierarchies() ); + } + binder.bindEntityHierarchies(); + } + + private static void bindMappingDependentMetadata( + MetadataSourceProcessor[] metadataSourceProcessors, + RootBindingContextImpl bindingContext) { + // Create required back references, which are required for one-to-many associations with key bindings that are non-inverse, + // non-nullable, and unidirectional + for ( PluralAttributeBinding pluralAttributeBinding : bindingContext.getMetadataCollector().getCollectionBindings() ) { + // Find one-to-many associations with key bindings that are non-inverse and non-nullable + PluralAttributeKeyBinding keyBinding = pluralAttributeBinding.getPluralAttributeKeyBinding(); + if ( keyBinding.isInverse() || keyBinding.isNullable() || + pluralAttributeBinding.getPluralAttributeElementBinding().getNature() != + PluralAttributeElementNature.ONE_TO_MANY ) { + continue; + } + // Ensure this isn't a bidirectional association by ensuring FK columns don't match relational columns of any + // many-to-one on opposite side + EntityBinding referencedEntityBinding = bindingContext.getMetadataCollector().getEntityBinding( + pluralAttributeBinding.getPluralAttributeElementBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping() + .getName() + ); + List keyValueBindings = keyBinding.getRelationalValueBindings(); + boolean bidirectional = false; + for ( AttributeBinding attributeBinding : referencedEntityBinding.attributeBindings() ) { + if ( !(attributeBinding instanceof ManyToOneAttributeBinding ) ) { + continue; + } + // Check if the opposite many-to-one attribute binding references the one-to-many attribute binding being processed + ManyToOneAttributeBinding manyToOneAttributeBinding = ( ManyToOneAttributeBinding ) attributeBinding; + if ( !manyToOneAttributeBinding.getReferencedEntityBinding().equals( + pluralAttributeBinding.getContainer().seekEntityBinding() ) ) { + continue; + } + // Check if the many-to-one attribute binding's columns match the one-to-many attribute binding's FK columns + // (meaning this is a bidirectional association, and no back reference should be created) + List valueBindings = manyToOneAttributeBinding.getRelationalValueBindings(); + if ( keyValueBindings.size() != valueBindings.size() ) { + continue; + } + bidirectional = true; + for ( int ndx = valueBindings.size(); --ndx >= 0; ) { + if ( keyValueBindings.get(ndx) != valueBindings.get( ndx ) ) { + bidirectional = false; + break; + } + } + if ( bidirectional ) { + break; + } + } + if ( bidirectional ) continue; + + // Create the synthetic back reference attribute + SingularAttribute syntheticAttribute = + referencedEntityBinding.getEntity().createSyntheticSingularAttribute( + SyntheticAttributeHelper.createBackRefAttributeName( + pluralAttributeBinding.getAttribute() + .getRole() + ) ); + // Create the back reference attribute binding. + BackRefAttributeBinding backRefAttributeBinding = referencedEntityBinding.makeBackRefAttributeBinding( + syntheticAttribute, pluralAttributeBinding, false + ); + backRefAttributeBinding.getHibernateTypeDescriptor().copyFrom( keyBinding.getHibernateTypeDescriptor() ); + backRefAttributeBinding.getAttribute().resolveType( + keyBinding.getReferencedAttributeBinding().getAttribute().getSingularAttributeType() ); + if ( pluralAttributeBinding.hasIndex() ) { + SingularAttribute syntheticIndexAttribute = + referencedEntityBinding.getEntity().createSyntheticSingularAttribute( + SyntheticAttributeHelper.createIndexBackRefAttributeName( pluralAttributeBinding.getAttribute().getRole() ) ); + BackRefAttributeBinding indexBackRefAttributeBinding = referencedEntityBinding.makeBackRefAttributeBinding( + syntheticIndexAttribute, pluralAttributeBinding, true + ); + final PluralAttributeIndexBinding indexBinding = + ( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding(); + indexBackRefAttributeBinding.getHibernateTypeDescriptor().copyFrom( + indexBinding.getHibernateTypeDescriptor() + ); + indexBackRefAttributeBinding.getAttribute().resolveType( + indexBinding.getPluralAttributeIndexType() + ); + } + } + + for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { + metadataSourceProcessor.processMappingDependentMetadata(); + } + } + + private static void secondPass(RootBindingContextImpl bindingContext) { + // This must be done outside of Table, rather than statically, to ensure + // deterministic alias names. See HHH-2448. + int uniqueInteger = 0; + for ( Schema schema : bindingContext.getMetadataCollector().getDatabase().getSchemas() ) { + for ( Table table : schema.getTables() ) { + table.setTableNumber( uniqueInteger++ ); + } + } + + + if ( bindingContext.getBuildingOptions().getCacheRegionDefinitions() == null + || bindingContext.getBuildingOptions().getCacheRegionDefinitions().isEmpty() ) { + return; + } + + for ( CacheRegionDefinition override : bindingContext.getBuildingOptions().getCacheRegionDefinitions() ) { + final String role = override.getRole(); + + // NOTE : entity region overrides are already handled when building the + if ( override.getRegionType() == CacheRegionDefinition.CacheRegionType.ENTITY ) { +// final EntityBinding entityBinding = bindingContext.getMetadataCollector().getEntityBinding( role ); +// if ( entityBinding != null ) { +// entityBinding.getHierarchyDetails().getCaching().setRegion( override.getRegion() ); +// entityBinding.getHierarchyDetails().getCaching().setAccessType( AccessType.fromExternalName( override.getUsage() ) ); +// entityBinding.getHierarchyDetails().getCaching().setCacheLazyProperties( override.isCacheLazy() ); +// } +// else { +// //logging? +// throw new MappingException( "Can't find entitybinding for role " + role +" to apply cache configuration" ); +// } + + } + else if ( override.getRegionType() == CacheRegionDefinition.CacheRegionType.COLLECTION ) { + String collectionRole = role; + if ( !role.contains( "#" ) ) { + final int pivotPosition = role.lastIndexOf( '.' ); + if ( pivotPosition > 0 ) { + collectionRole = role.substring( 0, pivotPosition ) + '#' + role.substring( pivotPosition + 1 ); + } + } + final PluralAttributeBinding pluralAttributeBinding = bindingContext.getMetadataCollector().getCollection( + collectionRole + ); + if ( pluralAttributeBinding != null ) { + pluralAttributeBinding.getCaching().overlay( override ); + } + else { + //logging? + throw new MappingException( "Can't find entitybinding for role " + role +" to apply cache configuration" ); + } + } + } + + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // BindingContext impl + + public static class RootBindingContextImpl implements BindingContext { + private final MetadataBuildingOptions options; + private final MappingDefaults mappingDefaults; + private final JavaTypeDescriptorRepository javaTypeDescriptorRepository; + private final JandexAccessImpl jandexAccess; + private final ClassLoaderAccess classLoaderAccess; + private final InFlightMetadataCollectorImpl metadataCollector; + private final MetaAttributeContext globalMetaAttributeContext = new MetaAttributeContext(); + + public RootBindingContextImpl( + MetadataBuildingOptions options, + MappingDefaultsImpl mappingDefaults, + JavaTypeDescriptorRepository javaTypeDescriptorRepository, + JandexAccessImpl jandexAccess, + ClassLoaderAccess classLoaderAccess, + InFlightMetadataCollectorImpl metadataCollector) { + this.options = options; + this.mappingDefaults = mappingDefaults; + this.javaTypeDescriptorRepository = javaTypeDescriptorRepository; + this.jandexAccess = jandexAccess; + this.classLoaderAccess = classLoaderAccess; + this.metadataCollector = metadataCollector; + } + + @Override + public MetadataBuildingOptions getBuildingOptions() { + return options; + } + + @Override + public MappingDefaults getMappingDefaults() { + return mappingDefaults; + } + + @Override + public JandexAccess getJandexAccess() { + return jandexAccess; + } + + @Override + public JavaTypeDescriptorRepository getJavaTypeDescriptorRepository() { + return javaTypeDescriptorRepository; + } + + @Override + public String qualifyClassName(String name) { + // see comments on MappingDefaultsImpl.getPackageName() + return name; + } + + @Override + public InFlightMetadataCollector getMetadataCollector() { + return metadataCollector; + } + + @Override + public MetaAttributeContext getGlobalMetaAttributeContext() { + return globalMetaAttributeContext; + } + + + @Override + public ServiceRegistry getServiceRegistry() { + return options.getServiceRegistry(); + } + + @Override + public ClassLoaderAccess getClassLoaderAccess() { + return classLoaderAccess; + } + + @Override + public boolean quoteIdentifiersInContext() { + return options.getDatabaseDefaults().isGloballyQuotedIdentifiers(); + } + + @Override + public JavaTypeDescriptor typeDescriptor(String name) { + return javaTypeDescriptorRepository.getType( javaTypeDescriptorRepository.buildName( qualifyClassName( name ) ) ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // BindingContext deprecated impls + + @Override + public Type makeDomainType(String className) { + return new BasicType( className, typeDescriptor( className ) ); + } + + @Override + public Type makeDomainType(DotName typeName) { + return new BasicType( + typeName.toString(), + typeDescriptor( typeName.toString() ) + ); + } + } + + public static class MappingDefaultsImpl implements MappingDefaults { + private static final String DEFAULT_IDENTIFIER_COLUMN_NAME = "id"; + private static final String DEFAULT_TENANT_IDENTIFIER_COLUMN_NAME = "tenant_id"; + private static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class"; + private static final String DEFAULT_CASCADE = "none"; + private static final String DEFAULT_PROPERTY_ACCESS = "property"; + + private final MetadataBuildingOptions options; + + public MappingDefaultsImpl(MetadataBuildingOptions options) { + this.options = options; + } + + @Override + public String getPackageName() { + // default package name is only relevant within processing XML mappings. Here + // at the root, there is no default + return null; + } + + @Override + public String getSchemaName() { + return options.getDatabaseDefaults().getDefaultSchemaName(); + } + + @Override + public String getCatalogName() { + return options.getDatabaseDefaults().getDefaultCatalogName(); + } + + @Override + public String getIdColumnName() { + return DEFAULT_IDENTIFIER_COLUMN_NAME; + } + + @Override + public String getTenantIdColumnName() { + return DEFAULT_TENANT_IDENTIFIER_COLUMN_NAME; + } + + @Override + public String getDiscriminatorColumnName() { + return DEFAULT_DISCRIMINATOR_COLUMN_NAME; + } + + @Override + public String getCascadeStyle() { + return DEFAULT_CASCADE; + } + + @Override + public String getPropertyAccessorName() { + return DEFAULT_PROPERTY_ACCESS; + } + + @Override + public boolean areAssociationsLazy() { + return true; + } + + @Override + public AccessType getCacheAccessType() { + return options.getDefaultCacheAccessType(); + } + } + + public static class InFlightMetadataCollectorImpl implements InFlightMetadataCollector { + private final MetadataBuildingOptions options; + private final TypeResolver typeResolver; + + private final UUID uuid; + private final Database database; + private final ObjectNameNormalizer nameNormalizer; + private final MutableIdentifierGeneratorFactory identifierGeneratorFactory; + + private final Map typeDefinitionMap = new HashMap(); + private final Map filterDefinitionMap = new HashMap(); + + private final Map entityBindingMap = + new HashMap(); + private final Map collectionBindingMap = + new HashMap(); + private final Map fetchProfiles = + new HashMap(); + private final Map imports = + new HashMap(); + private final Map idGenerators = + new HashMap(); + private final Map namedQueryDefs = + new HashMap(); + private final Map namedNativeQueryDefs = + new HashMap(); + private final Map namedStoredProcedureQueryDefinitionMap = + new HashMap(); + private final Map resultSetMappings = + new HashMap(); + private final Map namedEntityGraphMap = + new HashMap( ); + private final Map secondaryTableMap = + new HashMap(); + + public InFlightMetadataCollectorImpl(MetadataBuildingOptions options, TypeResolver typeResolver) { + this.uuid = UUID.randomUUID(); + this.options = options; + this.typeResolver = typeResolver; + + this.database = new Database( + options.getDatabaseDefaults(), + options.getServiceRegistry().getService( JdbcServices.class ).getJdbcEnvironment() + ); + + this.nameNormalizer = new ObjectNameNormalizer() { + @Override + protected NamingStrategy getNamingStrategy() { + return InFlightMetadataCollectorImpl.this.options.getNamingStrategy(); + } + + @Override + protected boolean isUseQuotedIdentifiersGlobally() { + return InFlightMetadataCollectorImpl.this.options.getDatabaseDefaults().isGloballyQuotedIdentifiers(); + } + }; + + this.identifierGeneratorFactory = options.getServiceRegistry().getService( MutableIdentifierGeneratorFactory.class ); + } + + @Override + public Database getDatabase() { + return database; + } + + @Override + public TypeResolver getTypeResolver() { + return typeResolver; + } + + @Override + public ObjectNameNormalizer getObjectNameNormalizer() { + return nameNormalizer; + } + + @Override + public void setGloballyQuotedIdentifiers(boolean b) { + // hmmm... + } + + @Override + public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { + return identifierGeneratorFactory; + } + + @Override + public SessionFactoryBuilder getSessionFactoryBuilder() { + throw new UnsupportedOperationException( + "You should not be building a SessionFactory from an in-flight metadata collector; and of course " + + "we should better segment this in the API :)" + ); + } + + @Override + public SessionFactory buildSessionFactory() { + throw new UnsupportedOperationException( + "You should not be building a SessionFactory from an in-flight metadata collector; and of course " + + "we should better segment this in the API :)" + ); + } + + @Override + public UUID getUUID() { + return null; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Hibernate Type handling + + @Override + public void addTypeDefinition( TypeDefinition typeDefinition ) { + if ( typeDefinition == null ) { + throw new IllegalArgumentException( "Type definition is null" ); + } + + // Need to register both by name and registration keys. + if ( !StringHelper.isEmpty( typeDefinition.getName() ) ) { + addTypeDefinition( typeDefinition.getName(), typeDefinition ); + } + + for ( String registrationKey : typeDefinition.getRegistrationKeys() ) { + addTypeDefinition( registrationKey, typeDefinition ); + } + } + + private void addTypeDefinition( String registrationKey, TypeDefinition typeDefinition ) { + final TypeDefinition previous = typeDefinitionMap.put( + registrationKey, typeDefinition ); + if ( previous != null ) { + log.debugf( + "Duplicate typedef name [%s] now -> %s", + registrationKey, + typeDefinition.getTypeImplementorClass().getName() + ); + } + } + + @Override + public Iterable getTypeDefinitions() { + return typeDefinitionMap.values(); + } + + @Override + public boolean hasTypeDefinition(String registrationKey) { + return typeDefinitionMap.containsKey( registrationKey ); + } + + @Override + public TypeDefinition getTypeDefinition(String registrationKey) { + return typeDefinitionMap.get( registrationKey ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // filter definitions + + @Override + public void addFilterDefinition(FilterDefinition filterDefinition) { + if ( filterDefinition == null || filterDefinition.getFilterName() == null ) { + throw new IllegalArgumentException( "Filter definition object or name is null: " + filterDefinition ); + } + filterDefinitionMap.put( filterDefinition.getFilterName(), filterDefinition ); + } + @Override + public Map getFilterDefinitions() { + return filterDefinitionMap; + } + + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // fetch profiles + + @Override + public void addFetchProfile(FetchProfile profile) { + if ( profile == null || profile.getName() == null ) { + throw new IllegalArgumentException( "Fetch profile object or name is null: " + profile ); + } + FetchProfile old = fetchProfiles.put( profile.getName(), profile ); + if ( old != null ) { + log.warn( "Duplicated fetch profile with same name [" + profile.getName() + "] found." ); + } + } + + @Override + public Iterable getFetchProfiles() { + return fetchProfiles.values(); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // identifier generators + + @Override + public void addIdGenerator(IdentifierGeneratorDefinition generator) { + if ( generator == null || generator.getName() == null ) { + throw new IllegalArgumentException( "ID generator object or name is null." ); + } + idGenerators.put( generator.getName(), generator ); + } + + @Override + public IdentifierGeneratorDefinition getIdGenerator(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "null is not a valid generator name" ); + } + return idGenerators.get( name ); + } + + @Override + public void registerIdentifierGenerator(String name, String generatorClassName) { + identifierGeneratorFactory.register( + name, + options.getServiceRegistry() + .getService( ClassLoaderService.class ) + .classForName( generatorClassName ) + ); + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Named EntityGraph handling + + @Override + public void addNamedEntityGraph(NamedEntityGraphDefinition definition) { + final String name = definition.getRegisteredName(); + final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition ); + if ( previous != null ) { + throw new DuplicateMappingException( "NamedEntityGraph", name ); + } + } + + @Override + public Map getNamedEntityGraphs() { + return namedEntityGraphMap; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Named query handling + + @Override + public void addNamedNativeQuery(NamedSQLQueryDefinition def) { + if ( def == null ) { + throw new IllegalArgumentException( "Named native query definition object is null" ); + } + if ( def.getName() == null ) { + throw new IllegalArgumentException( "Named native query definition name is null: " + def.getQueryString() ); + } + NamedSQLQueryDefinition old = namedNativeQueryDefs.put( def.getName(), def ); + if ( old != null ) { + log.warn( "Duplicated named query with same name["+ old.getName() +"] found" ); + //todo mapping exception?? + // in the old metamodel, the NamedQueryDefinition.name actually not is not + // always the one defined in the hbm. there are two cases: + // 1) if this or is a sub-element of then, + // then name is as it is + // 2) if defined inside a class mapping, then the query name is actually + // prefixed with the entity name (entityName.query_name), and the referenced sql + // resultset mapping's name should also in this form. + } + } + + @Override + public Iterable getNamedNativeQueryDefinitions() { + return namedNativeQueryDefs.values(); + } + + @Override + public void addNamedQuery(NamedQueryDefinition def) { + if ( def == null ) { + throw new IllegalArgumentException( "Named query definition is null" ); + } + else if ( def.getName() == null ) { + throw new IllegalArgumentException( "Named query definition name is null: " + def.getQueryString() ); + } + NamedQueryDefinition old = namedQueryDefs.put( def.getName(), def ); + if ( old != null ) { + log.warn( "Duplicated named query with same name["+ old.getName() +"] found" ); + //todo mapping exception?? + // see lengthy comment above + } + } + + + @Override + public void addNamedStoredProcedureQueryDefinition(NamedStoredProcedureQueryDefinition definition) { + if ( definition == null ) { + throw new IllegalArgumentException( "Named query definition is null" ); + } + + namedStoredProcedureQueryDefinitionMap.put( definition.getName(), definition ); + } + + @Override + public Collection getNamedStoredProcedureQueryDefinitions() { + return namedStoredProcedureQueryDefinitionMap.values(); + } + + public NamedQueryDefinition getNamedQuery(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "null is not a valid query name" ); + } + return namedQueryDefs.get( name ); + } + + @Override + public Iterable getNamedQueryDefinitions() { + return namedQueryDefs.values(); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // result-set mapping handling + + @Override + public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition) { + if ( resultSetMappingDefinition == null || resultSetMappingDefinition.getName() == null ) { + throw new IllegalArgumentException( "Result-set mapping object or name is null: " + resultSetMappingDefinition ); + } + ResultSetMappingDefinition old = resultSetMappings.put( + resultSetMappingDefinition.getName(), + resultSetMappingDefinition + ); + if ( old != null ) { + log.warn( "Duplicated sql result set mapping with same name["+ resultSetMappingDefinition.getName() +"] found" ); + //todo mapping exception?? + } + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // imports + + @Override + public Map getResultSetMappingDefinitions() { + return resultSetMappings; + } + + @Override + public void addImport(String importName, String entityName) { + if ( importName == null || entityName == null ) { + throw new IllegalArgumentException( "Import name or entity name is null" ); + } + log.tracev( "Import: {0} -> {1}", importName, entityName ); + String old = imports.put( importName, entityName ); + if ( old != null ) { + log.debug( "import name [" + importName + "] overrode previous [{" + old + "}]" ); + } + } + + @Override + public Map getImports() { + return imports; + } + + @Override + public NamedSQLQueryDefinition getNamedNativeQuery(String name) { + return namedNativeQueryDefs.get( name ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // entity bindings + + public EntityBinding getEntityBinding(String entityName) { + return entityBindingMap.get( entityName ); + } + + @Override + public EntityBinding getRootEntityBinding(String entityName) { + EntityBinding binding = entityBindingMap.get( entityName ); + if ( binding == null ) { + throw new IllegalStateException( "Unknown entity binding: " + entityName ); + } + + do { + if ( binding.isRoot() ) { + return binding; + } + binding = binding.getSuperEntityBinding(); + } while ( binding != null ); + + throw new AssertionFailure( "Entity binding has no root: " + entityName ); + } + + @Override + public Iterable getEntityBindings() { + return entityBindingMap.values(); + } + + @Override + public void addEntity(EntityBinding entityBinding) { + final String entityName = entityBinding.getEntityName(); + if ( entityBindingMap.containsKey( entityName ) ) { + throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, entityName ); + } + entityBindingMap.put( entityName, entityBinding ); + final boolean isPOJO = entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO; + final String className = isPOJO ? entityBinding.getEntity().getDescriptor().getName().toString() : null; + if ( isPOJO && StringHelper.isEmpty( className ) ) { + throw new MappingException( "Entity[" + entityName + "] is mapped as pojo but don't have a class name" ); + } + if ( StringHelper.isNotEmpty( className ) && !entityBindingMap.containsKey( className ) ) { + entityBindingMap.put( className, entityBinding ); + } + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // secondary table handling + + @Override + public void addSecondaryTable(SecondaryTable secondaryTable) { + secondaryTableMap.put( secondaryTable.getSecondaryTableReference().getLogicalName(), secondaryTable ); + } + + @Override + public Map getSecondaryTables() { + return secondaryTableMap; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // collection binding handling + + public PluralAttributeBinding getCollection(String collectionRole) { + return collectionBindingMap.get( collectionRole ); + } + + @Override + public Iterable getCollectionBindings() { + return collectionBindingMap.values(); + } + + @Override + public void addCollection(PluralAttributeBinding pluralAttributeBinding) { + final String collectionRole = pluralAttributeBinding.getAttributeRole().getFullPath(); + if ( collectionBindingMap.containsKey( collectionRole ) ) { + throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, collectionRole ); + } + collectionBindingMap.put( pluralAttributeBinding.getAttributeRole().getFullPath(), pluralAttributeBinding ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Mapping impl + + @Override + public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + @Override + public String getIdentifierPropertyName(String entityName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + return idBinding == null ? null : idBinding.getAttribute().getName(); + } + + @Override + public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + AttributeBinding attributeBinding = entityBinding.locateAttributeBindingByPath( propertyName, true ); + if ( attributeBinding == null ) { + throw new MappingException( "unknown property: " + entityName + '.' + propertyName ); + } + return attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + } + + public MetadataImpl buildMetadataInstance() { + return new MetadataImpl( + options.getServiceRegistry(), + database, + typeResolver, + uuid, + identifierGeneratorFactory, + typeDefinitionMap, + filterDefinitionMap, + entityBindingMap, + collectionBindingMap, + fetchProfiles, + imports, + idGenerators, + namedQueryDefs, + namedNativeQueryDefs, + namedStoredProcedureQueryDefinitionMap, + resultSetMappings, + namedEntityGraphMap, + secondaryTableMap + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java new file mode 100644 index 000000000000..c80a9a3bb092 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java @@ -0,0 +1,330 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.hibernate.AssertionFailure; +import org.hibernate.MappingException; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.engine.spi.NamedQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.id.factory.IdentifierGeneratorFactory; +import org.hibernate.metamodel.NamedStoredProcedureQueryDefinition; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.type.TypeResolver; + +/** + * Container for configuration data collected during binding the metamodel. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class MetadataImpl implements MetadataImplementor, Serializable { + private final StandardServiceRegistry serviceRegistry; + + private final Database database; + private final TypeResolver typeResolver; + private final IdentifierGeneratorFactory identifierGeneratorFactory; + + private final UUID uuid; + + private final Map typeDefinitionMap = new HashMap(); + private final Map filterDefinitionMap = new HashMap(); + private final Map entityBindingMap = new HashMap(); + private final Map collectionBindingMap = new HashMap(); + private final Map fetchProfiles = new HashMap(); + private final Map imports = new HashMap(); + private final Map idGenerators = new HashMap(); + private final Map namedQueryDefs = new HashMap(); + private final Map namedNativeQueryDefs = new HashMap(); + private final Map namedStoredProcedureQueryDefinitionMap = new HashMap(); + private final Map resultSetMappings = new HashMap(); + private final Map namedEntityGraphMap = new HashMap( ); + private final Map secondaryTableMap = new HashMap( ); + + MetadataImpl( + StandardServiceRegistry serviceRegistry, + Database database, + TypeResolver typeResolver, + UUID uuid, + IdentifierGeneratorFactory identifierGeneratorFactory, + Map typeDefinitionMap, + Map filterDefinitionMap, + Map entityBindingMap, + Map collectionBindingMap, + Map fetchProfiles, + Map imports, + Map idGenerators, + Map namedQueryDefs, + Map namedNativeQueryDefs, + Map namedStoredProcedureQueryDefinitionMap, + Map resultSetMappings, + Map namedEntityGraphMap, + Map secondaryTableMap) { + this.serviceRegistry = serviceRegistry; + this.database = database; + this.typeResolver = typeResolver; + this.uuid = uuid; + this.identifierGeneratorFactory = identifierGeneratorFactory; + + if ( typeDefinitionMap != null ) { + this.typeDefinitionMap.putAll( typeDefinitionMap ); + } + if ( filterDefinitionMap != null ) { + this.filterDefinitionMap.putAll( filterDefinitionMap ); + } + if ( entityBindingMap != null ) { + this.entityBindingMap.putAll( entityBindingMap ); + } + if ( collectionBindingMap != null ) { + this.collectionBindingMap.putAll( collectionBindingMap ); + } + if ( fetchProfiles != null ) { + this.fetchProfiles.putAll( fetchProfiles ); + } + if ( imports != null ) { + this.imports.putAll( imports ); + } + if ( idGenerators != null ) { + this.idGenerators.putAll( idGenerators ); + } + if ( namedQueryDefs != null ) { + this.namedQueryDefs.putAll( namedQueryDefs ); + } + if ( namedNativeQueryDefs != null ) { + this.namedNativeQueryDefs.putAll( namedNativeQueryDefs ); + } + if ( resultSetMappings != null ) { + this.resultSetMappings.putAll( resultSetMappings ); + } + if ( namedStoredProcedureQueryDefinitionMap != null ) { + this.namedStoredProcedureQueryDefinitionMap.putAll( namedStoredProcedureQueryDefinitionMap ); + } + if ( namedEntityGraphMap != null ) { + this.namedEntityGraphMap.putAll( namedEntityGraphMap ); + } + if ( secondaryTableMap != null ) { + this.secondaryTableMap.putAll( secondaryTableMap ); + } + } + + @Override + public Database getDatabase() { + return database; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + @Override + public TypeResolver getTypeResolver() { + return typeResolver; + } + + @Override + public Iterable getTypeDefinitions() { + return typeDefinitionMap.values(); + } + + @Override + public boolean hasTypeDefinition(String registrationKey) { + return typeDefinitionMap.containsKey( registrationKey ); + } + + @Override + public TypeDefinition getTypeDefinition(String registrationKey) { + return typeDefinitionMap.get( registrationKey ); + } + + @Override + public Map getNamedEntityGraphs() { + return namedEntityGraphMap; + } + + @Override + public Map getFilterDefinitions() { + return filterDefinitionMap; + } + + @Override + public IdentifierGeneratorDefinition getIdGenerator(String name) { + if ( name == null ) { + throw new IllegalArgumentException( "null is not a valid generator name" ); + } + return idGenerators.get( name ); + } + + @Override + public Iterable getNamedNativeQueryDefinitions() { + return namedNativeQueryDefs.values(); + } + + @Override + public Collection getNamedStoredProcedureQueryDefinitions() { + return namedStoredProcedureQueryDefinitionMap.values(); + } + + @Override + public Iterable getNamedQueryDefinitions() { + return namedQueryDefs.values(); + } + + @Override + public NamedSQLQueryDefinition getNamedNativeQuery(String name) { + return namedNativeQueryDefs.get( name ); + } + + @Override + public Map getResultSetMappingDefinitions() { + return resultSetMappings; + } + + @Override + public EntityBinding getEntityBinding(String entityName) { + return entityBindingMap.get( entityName ); + } + + @Override + public EntityBinding getRootEntityBinding(String entityName) { + EntityBinding binding = entityBindingMap.get( entityName ); + if ( binding == null ) { + throw new IllegalStateException( "Unknown entity binding: " + entityName ); + } + + do { + if ( binding.isRoot() ) { + return binding; + } + binding = binding.getSuperEntityBinding(); + } while ( binding != null ); + + throw new AssertionFailure( "Entity binding has no root: " + entityName ); + } + + @Override + public Iterable getEntityBindings() { + return entityBindingMap.values(); + } + + @Override + public Map getSecondaryTables() { + return secondaryTableMap; + } + + @Override + public Iterable getCollectionBindings() { + return collectionBindingMap.values(); + } + + public PluralAttributeBinding getCollection(String role) { + return collectionBindingMap.get( role ); + } + + @Override + public Map getImports() { + return imports; + } + + @Override + public Iterable getFetchProfiles() { + return fetchProfiles.values(); + } + + @Override + public SessionFactoryBuilder getSessionFactoryBuilder() { + return new SessionFactoryBuilderImpl( this, serviceRegistry ); + } + + @Override + public SessionFactory buildSessionFactory() { + return getSessionFactoryBuilder().build(); + } + + @Override + public UUID getUUID() { + return null; + } + + @Override + public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { + return identifierGeneratorFactory; + } + + @Override + public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + @Override + public String getIdentifierPropertyName(String entityName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + return idBinding == null ? null : idBinding.getAttribute().getName(); + } + + @Override + public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { + EntityBinding entityBinding = getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "Entity binding not known: " + entityName ); + } + AttributeBinding attributeBinding = entityBinding.locateAttributeBindingByPath( propertyName, true ); + if ( attributeBinding == null ) { + throw new MappingException( "unknown property: " + entityName + '.' + propertyName ); + } + return attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java new file mode 100644 index 000000000000..0aa56f8397d2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/SessionFactoryBuilderImpl.java @@ -0,0 +1,224 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.hibernate.CustomEntityDirtinessStrategy; +import org.hibernate.EmptyInterceptor; +import org.hibernate.EntityMode; +import org.hibernate.EntityNameResolver; +import org.hibernate.Interceptor; +import org.hibernate.SessionFactory; +import org.hibernate.SessionFactoryObserver; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Settings; +import org.hibernate.cfg.SettingsFactory; +import org.hibernate.context.spi.CurrentTenantIdentifierResolver; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.internal.DefaultCustomEntityDirtinessStrategy; +import org.hibernate.internal.SessionFactoryImpl; +import org.hibernate.internal.StandardEntityNotFoundDelegate; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.tuple.entity.EntityTuplizer; + +/** + * @author Gail Badner + * @author Steve Ebersole + */ +public class SessionFactoryBuilderImpl implements SessionFactoryBuilder { + private final MetadataImplementor metadata; + private final SessionFactoryOptionsImpl options; + + SessionFactoryBuilderImpl(MetadataImplementor metadata, StandardServiceRegistry serviceRegistry) { + this.metadata = metadata; + options = new SessionFactoryOptionsImpl( serviceRegistry ); + } + + @Override + public SessionFactoryBuilder with(Interceptor interceptor) { + this.options.interceptor = interceptor; + return this; + } + + @Override + public SessionFactoryBuilder with(CustomEntityDirtinessStrategy dirtinessStrategy) { + this.options.customEntityDirtinessStrategy = dirtinessStrategy; + return this; + } + + @Override + public SessionFactoryBuilder with(CurrentTenantIdentifierResolver currentTenantIdentifierResolver) { + this.options.currentTenantIdentifierResolver = currentTenantIdentifierResolver; + return this; + } + + @Override + public SessionFactoryBuilder add(SessionFactoryObserver... observers) { + this.options.sessionFactoryObserverList.addAll( Arrays.asList( observers ) ); + return this; + } + + @Override + public SessionFactoryBuilder add(EntityNameResolver... entityNameResolvers) { + this.options.entityNameResolvers.addAll( Arrays.asList( entityNameResolvers ) ); + return this; + } + + @Override + public SessionFactoryBuilder with(EntityNotFoundDelegate entityNotFoundDelegate) { + this.options.entityNotFoundDelegate = entityNotFoundDelegate; + return this; + } + + @Override + public SessionFactoryBuilder with(EntityMode entityMode, Class tuplizerClass) { + this.options.settings.getEntityTuplizerFactory().registerDefaultTuplizerClass( entityMode, tuplizerClass ); + return this; + } + + @Override + public SessionFactoryBuilder withValidatorFactory(Object validatorFactory) { + this.options.validatorFactoryReference = validatorFactory; + return this; + } + + @Override + public SessionFactoryBuilder withBeanManager(Object beanManager) { + this.options.beanManagerReference = beanManager; + return this; + } + + @Override + public SessionFactory build() { + return new SessionFactoryImpl( metadata, options ); + } + + private static class SessionFactoryOptionsImpl implements SessionFactory.SessionFactoryOptions { + private final StandardServiceRegistry serviceRegistry; + + private Interceptor interceptor; + private CustomEntityDirtinessStrategy customEntityDirtinessStrategy; + private CurrentTenantIdentifierResolver currentTenantIdentifierResolver; + private List sessionFactoryObserverList = new ArrayList(); + private List entityNameResolvers = new ArrayList(); + private EntityNotFoundDelegate entityNotFoundDelegate; + private Settings settings; + public Object beanManagerReference; + public Object validatorFactoryReference; + + public SessionFactoryOptionsImpl(StandardServiceRegistry serviceRegistry) { + this.serviceRegistry = serviceRegistry; + + final Map configurationSettings = serviceRegistry.getService( ConfigurationService.class ).getSettings(); + + final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class ); + + this.interceptor = strategySelector.resolveDefaultableStrategy( + Interceptor.class, + configurationSettings.get( AvailableSettings.INTERCEPTOR ), + EmptyInterceptor.INSTANCE + ); + + this.entityNotFoundDelegate = StandardEntityNotFoundDelegate.INSTANCE; + + this.customEntityDirtinessStrategy = strategySelector.resolveDefaultableStrategy( + CustomEntityDirtinessStrategy.class, + configurationSettings.get( AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY ), + DefaultCustomEntityDirtinessStrategy.INSTANCE + ); + + this.currentTenantIdentifierResolver = strategySelector.resolveStrategy( + CurrentTenantIdentifierResolver.class, + configurationSettings.get( AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER ) + ); + + this.beanManagerReference = configurationSettings.get( "javax.persistence.bean.manager" ); + this.validatorFactoryReference = configurationSettings.get( "javax.persistence.validation.factory" ); + + Properties properties = new Properties(); + properties.putAll( configurationSettings ); + this.settings = new SettingsFactory().buildSettings( properties, serviceRegistry ); + } + + @Override + public StandardServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + @Override + public Interceptor getInterceptor() { + return interceptor; + } + + @Override + public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { + return customEntityDirtinessStrategy; + } + + @Override + public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { + return currentTenantIdentifierResolver; + } + + @Override + public Settings getSettings() { + return settings; + } + + @Override + public SessionFactoryObserver[] getSessionFactoryObservers() { + return sessionFactoryObserverList.toArray( new SessionFactoryObserver[sessionFactoryObserverList.size()] ); + } + + @Override + public EntityNameResolver[] getEntityNameResolvers() { + return entityNameResolvers.toArray( new EntityNameResolver[entityNameResolvers.size()] ); + } + + @Override + public EntityNotFoundDelegate getEntityNotFoundDelegate() { + return entityNotFoundDelegate; + } + + @Override + public Object getBeanManagerReference() { + return beanManagerReference; + } + + @Override + public Object getValidatorFactoryReference() { + return validatorFactoryReference; + } + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/Binder.java new file mode 100644 index 000000000000..8e58c07aa97c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/Binder.java @@ -0,0 +1,3382 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.FetchMode; +import org.hibernate.MappingException; +import org.hibernate.MultiTenancyStrategy; +import org.hibernate.TruthValue; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.IdentityGenerator; +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.enhanced.TableGenerator; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.internal.binder.HibernateTypeHelper.ReflectedCollectionJavaTypes; +import org.hibernate.metamodel.internal.resolver.AssociationRelationalBindingResolver; +import org.hibernate.metamodel.internal.resolver.MappedByAssociationRelationalBindingResolverImpl; +import org.hibernate.metamodel.internal.resolver.StandardAssociationRelationalBindingResolverImpl; +import org.hibernate.metamodel.reflite.internal.Primitives; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.ConstraintSource; +import org.hibernate.metamodel.source.spi.DerivedValueSource; +import org.hibernate.metamodel.source.spi.DiscriminatorSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.IndexConstraintSource; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.JoinedSubclassEntitySource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.source.spi.MultiTenancySource; +import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.Orderable; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceBasic; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceEmbedded; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceOneToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceBasic; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceEmbedded; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceEntityAttribute; +import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.RelationalValueSourceContainer; +import org.hibernate.metamodel.source.spi.SecondaryTableSource; +import org.hibernate.metamodel.source.spi.SimpleIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.Sortable; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.source.spi.UniqueConstraintSource; +import org.hibernate.metamodel.source.spi.VersionAttributeSource; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicPluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.EntityVersion; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.MetaAttribute; +import org.hibernate.metamodel.spi.binding.OneToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingBasic; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingEmbedded; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingManyToMany; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingOneToMany; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SetBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.BasicType; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.IdentifiableType; +import org.hibernate.metamodel.spi.domain.IndexedPluralAttribute; +import org.hibernate.metamodel.spi.domain.MappedSuperclass; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.tuple.component.ComponentMetamodel; +import org.hibernate.tuple.component.ComponentTuplizer; +import org.hibernate.tuple.entity.EntityTuplizer; +import org.hibernate.type.ForeignKeyDirection; +import org.hibernate.type.Type; + +import org.jboss.jandex.DotName; + +import static org.hibernate.MultiTenancyStrategy.DISCRIMINATOR; +import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME; + +/** + * The common binder shared between annotations and {@code hbm.xml} processing. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + * @author Brett Meyer + * @author Strong Liu + */ +public class Binder { + // Entity hierarchies and source index need be available throughout the binding process + private final Map entityHierarchiesByRootEntityName = + new LinkedHashMap(); + private final SourceIndex sourceIndex = new SourceIndex(); + + private final BinderRootContextImpl rootBindingContext; + private final BinderProcessHelper processHelper; + + private final JavaTypeDescriptorRepository javaTypeDescriptorRepository; + + // todo : hook this map in with the context method to make domain types... + private final Map domainModelTypes + = new HashMap(); + + private final StandardAssociationRelationalBindingResolverImpl standardAssociationRelationalBindingResolver; + private final MappedByAssociationRelationalBindingResolverImpl mappedByAssociationRelationalBindingResolver; + + private final Map entityCacheRegionDefinitionsByEntityName = new HashMap(); + + private final Map> identifierDependencyMap = new HashMap>(); + + public Binder(BindingContext rootBindingContext) { + this.rootBindingContext = new BinderRootContextImpl( rootBindingContext ); + + this.processHelper = new BinderProcessHelper( this.rootBindingContext ); + + this.standardAssociationRelationalBindingResolver = + new StandardAssociationRelationalBindingResolverImpl( this.rootBindingContext ); + this.mappedByAssociationRelationalBindingResolver = + new MappedByAssociationRelationalBindingResolverImpl( this.rootBindingContext ); + + this.javaTypeDescriptorRepository = this.rootBindingContext.getJavaTypeDescriptorRepository(); + + // index cache region definitions for easier lookup. + // for now, just entity regions + if ( rootBindingContext.getBuildingOptions().getCacheRegionDefinitions() != null ) { + for ( CacheRegionDefinition cacheRegionDefinition + : rootBindingContext.getBuildingOptions().getCacheRegionDefinitions() ) { + if ( cacheRegionDefinition.getRegionType() == CacheRegionDefinition.CacheRegionType.ENTITY ) { + entityCacheRegionDefinitionsByEntityName.put( + cacheRegionDefinition.getRole(), + cacheRegionDefinition + ); + } + } + } + } + + /** + * The entry point of {@linkplain Binder} class, adds all the entity hierarchy one by one. + * + * Indexes all {@link EntitySource} objects in an {@link org.hibernate.metamodel.source.spi.EntityHierarchySource} and + * creates all {@link EntityBinding}. + * + * @param entityHierarchies The entity hierarchies resolved from mappings + */ + public void addEntityHierarchies(final Collection entityHierarchies) { + // todo : ultimately (unified source) pass all hierarchies to SourceIndex at once.. + + processHelper.apply( entityHierarchies, new PreliminarySourceHandlingStep() ); + } + + public class PreliminarySourceHandlingStep implements BinderStepHierarchyStrategy { + @Override + public void visit(EntityHierarchySource source, BinderLocalBindingContext context) { + entityHierarchiesByRootEntityName.put( + source.getRoot().getEntityName(), + source + ); + sourceIndex.indexHierarchy( source ); + + final HierarchyDetails hierarchyDetails = createHierarchyDetails( source ); + rootBindingContext.addMapping( source, hierarchyDetails ); + + final EntityBinding rootEntityBinding = hierarchyDetails.getRootEntityBinding(); + final EntitySource rootEntitySource = source.getRoot(); + preliminaryEntityBinding( rootEntityBinding, rootEntitySource, hierarchyDetails ); + + bindVersion( hierarchyDetails, source ); + bindDiscriminator( hierarchyDetails, source ); + bindMultiTenancy( hierarchyDetails, source ); + + if ( hierarchyDetails.getInheritanceType() != InheritanceType.NO_INHERITANCE ) { + // apply to persistent subclasses + visitPreliminaryEntityBindingOnSubclasses( rootEntityBinding, rootEntitySource, hierarchyDetails ); + } + } + + private HierarchyDetails createHierarchyDetails(EntityHierarchySource hierarchySource) { + final HierarchyDetails.Builder builder = new HierarchyDetails.Builder() + .setInheritanceType( hierarchySource.getHierarchyInheritanceType() ) + .setDiscriminated( hierarchySource.getDiscriminatorSource() != null ) + .setVersioned( hierarchySource.getVersionAttributeSource() != null ) + .setEntityMode( hierarchySource.getEntityMode() ) + .setMutable( hierarchySource.isMutable() ) + .setExplicitPolymorphism( hierarchySource.isExplicitPolymorphism() ) + .setOptimisticLockStyle( hierarchySource.getOptimisticLockStyle() ) + .setWhere( hierarchySource.getWhere() ); + + // entity caching + String entityName = hierarchySource.getRoot().getEntityName(); + Caching caching = hierarchySource.getCaching(); + if ( caching == null ) { + caching = new Caching( TruthValue.UNKNOWN ); + } + CacheRegionDefinition cachingOverride = entityCacheRegionDefinitionsByEntityName.get( entityName ); + if ( cachingOverride != null ) { + caching.overlay( cachingOverride ); + } + builder.setCaching( caching ); + + // natural id caching + Caching naturalIdCaching = hierarchySource.getNaturalIdCaching(); + if ( naturalIdCaching == null ) { + naturalIdCaching = new Caching( TruthValue.UNKNOWN ); + } + builder.setNaturalIdCaching( naturalIdCaching ); + + // multi-tenancy discriminator + if ( hierarchySource.getMultiTenancySource() != null ) { + builder.setTenancyDiscriminated( !hierarchySource.getMultiTenancySource().isShared() ); + } + + return builder.createHierarchyDetails(); + } + + private void preliminaryEntityBinding( + EntityBinding binding, + EntitySource source, + HierarchyDetails hierarchyDetails) { + rootBindingContext.addMapping( source, binding ); + + binding.setEntity( (Entity) resolveDomainType( source ) ); + binding.setEntityName( source.getEntityName() ); + binding.setJpaEntityName( source.getJpaEntityName() ); + binding.setDynamicUpdate( source.isDynamicUpdate() ); + binding.setDynamicInsert( source.isDynamicInsert() ); + binding.setBatchSize( source.getBatchSize() ); + binding.setSelectBeforeUpdate( source.isSelectBeforeUpdate() ); + binding.setAbstract( source.isAbstract() ); + binding.setCustomLoaderName( source.getCustomLoaderName() ); + binding.setCustomInsert( source.getCustomSqlInsert() ); + binding.setCustomUpdate( source.getCustomSqlUpdate() ); + binding.setCustomDelete( source.getCustomSqlDelete() ); + binding.setJpaCallbackClasses( source.getJpaCallbackClasses() ); + + // todo: deal with joined and unioned subclass bindings + // todo: bind fetch profiles + // Configure rest of binding + final String customTuplizerClassName = source.getCustomTuplizerClassName(); + if ( customTuplizerClassName != null ) { + binding.setCustomEntityTuplizerClass( + localBindingContext().getClassLoaderAccess().classForName( + customTuplizerClassName + ) + ); + } + final String customPersisterClassName = source.getCustomPersisterClassName(); + if ( customPersisterClassName != null ) { + binding.setCustomEntityPersisterClass( + localBindingContext().getClassLoaderAccess().classForName( + customPersisterClassName + ) + ); + } + binding.setMetaAttributeContext( + createMetaAttributeContext( + source.getToolingHintSources(), + true, + localBindingContext().getGlobalMetaAttributeContext() + ) + ); + + if ( source.getSynchronizedTableNames() != null ) { + binding.addSynchronizedTableNames( source.getSynchronizedTableNames() ); + } + + resolveEntityLaziness( binding, source, hierarchyDetails.getEntityMode() ); + + if ( source.getFilterSources() != null ) { + for ( FilterSource filterSource : source.getFilterSources() ) { + binding.addFilterConfiguration( createFilterConfiguration( filterSource, binding ) ); + } + } + + bindPrimaryTable( binding, source ); + + if ( binding.getHierarchyDetails().getEntityDiscriminator() != null ) { + final String discriminatorValue = source.getDiscriminatorMatchValue(); + if ( discriminatorValue != null ) { + binding.setDiscriminatorMatchValue( discriminatorValue ); + } + else { + // Use the class name as a default if no discriminator value. + binding.setDiscriminatorMatchValue( StringHelper.unqualify( source.getEntityName() ) ); + } + } + + // Register binding with metadata + localBindingContext().getMetadataCollector().addEntity( binding ); + } + + private void visitPreliminaryEntityBindingOnSubclasses( + EntityBinding binding, + IdentifiableTypeSource source, + HierarchyDetails hierarchyDetails) { + for ( IdentifiableTypeSource subType : source.getSubTypes() ) { + if ( EntitySource.class.isInstance( subType ) ) { + final EntityBinding subBinding = binding.makeSubBinding(); + preliminaryEntityBinding( subBinding, (EntitySource) subType, hierarchyDetails ); + visitPreliminaryEntityBindingOnSubclasses( subBinding, subType, hierarchyDetails ); + } + else { + visitPreliminaryEntityBindingOnSubclasses( binding, subType, hierarchyDetails ); + } + } + } + + private void resolveEntityLaziness( + final EntityBinding entityBinding, + final EntitySource entitySource, + final EntityMode entityMode) { + if ( entityMode == EntityMode.POJO ) { + final String proxy = entitySource.getProxy(); + if ( proxy == null ) { + if ( entitySource.isLazy() ) { + entityBinding.setProxyInterfaceType( entityBinding.getEntity().getDescriptor() ); + entityBinding.setLazy( true ); + } + } + else { + entityBinding.setProxyInterfaceType( + localBindingContext().typeDescriptor( proxy ) + ); + entityBinding.setLazy( true ); + } + } + else { + entityBinding.setProxyInterfaceType( null ); + entityBinding.setLazy( entitySource.isLazy() ); + } + } + + private void bindVersion(final HierarchyDetails hierarchyDetails, final EntityHierarchySource source) { + final VersionAttributeSource versionAttributeSource = source.getVersionAttributeSource(); + + if ( versionAttributeSource == null ) { + return; + } + + final EntityVersion version = hierarchyDetails.getEntityVersion(); + final BasicAttributeBinding versionAttributeBinding = (BasicAttributeBinding) bindAttribute( + hierarchyDetails.getRootEntityBinding(), + versionAttributeSource + ); + version.setVersioningAttributeBinding( versionAttributeBinding ); + + // Should be just one value. + if ( versionAttributeBinding.getRelationalValueBindings().size() != 1 ) { + throw source.getRoot().getLocalBindingContext().makeMappingException( + "Encountered multi-column version attribute" + ); + } + + // If it is a column, make sure the column is non-nullable + final RelationalValueBinding valueBinding = versionAttributeBinding.getRelationalValueBindings() + .get( 0 ); + if ( !valueBinding.isDerived() ) { + ( (Column) valueBinding.getValue() ).setNullable( false ); + } + + version.setUnsavedValue( + versionAttributeSource.getUnsavedValue() == null + ? "undefined" + : versionAttributeSource.getUnsavedValue() + ); + } + + private void bindDiscriminator(HierarchyDetails binding, EntityHierarchySource source) { + final DiscriminatorSource discriminatorSource = source.getDiscriminatorSource(); + if ( discriminatorSource == null ) { + return; + } + + binding.getEntityDiscriminator().setInserted( discriminatorSource.isInserted() ); + binding.getEntityDiscriminator().setForced( discriminatorSource.isForced() ); + + final RelationalValueSource valueSource = discriminatorSource.getDiscriminatorRelationalValueSource(); + final TableSpecification table = binding.getRootEntityBinding().getPrimaryTable(); + if ( valueSource != null && valueSource.getContainingTableName() != null ) { + // JPA says that the discriminator needs to come from the primary table... + // if source specifically named a table for the discriminator, make sure it matches + // the primary table + // todo : implement check, or not? + } + + final Value value = buildDiscriminatorRelationValue( valueSource, table ); + binding.getEntityDiscriminator().setRelationalValue( value ); + + typeHelper().bindDiscriminatorType( binding.getEntityDiscriminator(), value ); + } + + private Value buildDiscriminatorRelationValue( + final RelationalValueSource valueSource, + final TableSpecification table) { + if ( valueSource.getNature() == RelationalValueSource.Nature.COLUMN ) { + return tableHelper().locateOrCreateColumn( + table, + (ColumnSource) valueSource, + new ColumnNamingStrategyHelper( + localBindingContext().getMappingDefaults().getDiscriminatorColumnName(), + false + ), + false, + false + ); + } + else { + return table.locateOrCreateDerivedValue( ( (DerivedValueSource) valueSource ).getExpression() ); + } + } + + private void bindMultiTenancy(HierarchyDetails binding, EntityHierarchySource source) { + final MultiTenancySource multiTenancySource = source.getMultiTenancySource(); + if ( multiTenancySource == null ) { + return; + } + + // if (1) the strategy is discriminator based and (2) the entity is not shared, we need to either (a) extract + // the user supplied tenant discriminator value mapping or (b) generate an implicit one + final MultiTenancyStrategy strategy = localBindingContext().getBuildingOptions().getMultiTenancyStrategy(); + if ( strategy != DISCRIMINATOR || multiTenancySource.isShared() ) { + return; + } + + // NOTE : the table for tenant identifier/discriminator is always the primary table + final Value tenantDiscriminatorValue; + final RelationalValueSource valueSource = multiTenancySource.getRelationalValueSource(); + final TableSpecification table = binding.getRootEntityBinding().getPrimaryTable(); + + if ( valueSource == null ) { + // user supplied no explicit information, so use implicit mapping with default name + tenantDiscriminatorValue = table.locateOrCreateColumn( + localBindingContext().getMappingDefaults().getTenantIdColumnName() + ); + } + else { + tenantDiscriminatorValue = buildDiscriminatorRelationValue( valueSource, table ); + } + + binding.getTenantDiscrimination().setDiscriminatorValue( tenantDiscriminatorValue ); + binding.getTenantDiscrimination().setShared( multiTenancySource.isShared() ); + binding.getTenantDiscrimination().setUseParameterBinding( multiTenancySource.bindAsParameter() ); + } + } + + + /** + * Resolves the domain type give a source object representing an Entity or MappedSupperclass + * + * @param source The source object + * + * @return The Entity/MappedSuperclass + */ + @SuppressWarnings("unchecked") + private IdentifiableType resolveDomainType(IdentifiableTypeSource source) { + if ( source == null ) { + return null; + } + + final DotName descriptorTypeName = javaTypeDescriptorRepository.buildName( + typeHelper().determineJavaTypeName( source ) + ); + final JavaTypeDescriptor javaTypeDescriptor = javaTypeDescriptorRepository.getType( descriptorTypeName ); + + if ( EntitySource.class.isInstance( source ) ) { + Entity entityDomainType = (Entity) domainModelTypes.get( javaTypeDescriptor ); + + if ( entityDomainType == null ) { + entityDomainType = new Entity( + javaTypeDescriptor, + resolveDomainType( source.getSuperType() ) + ); + domainModelTypes.put( javaTypeDescriptor, entityDomainType ); + } + + return entityDomainType; + } + else { + MappedSuperclass superDomainType = (MappedSuperclass) domainModelTypes.get( javaTypeDescriptor ); + + if ( superDomainType == null ) { + superDomainType = new MappedSuperclass( + javaTypeDescriptor, + resolveDomainType( source.getSuperType() ) + ); + domainModelTypes.put( javaTypeDescriptor, superDomainType ); + } + + return superDomainType; + } + } + + public void bindEntityHierarchies() { + // Bind everything except for (non-ID) attributes. + // Need to bind ID attributes before resolving associations. + // TODO: when we know the proper order for processing entity hierarchies, + // then applyToAllEntityHierarchies(...) can replace the following method. + bindEntityHierarchiesExcludingNonIdAttributeBindings(); + + // Bind identifier generator for root entitybinding, we have to wait for all entiybindings created, + // since for union-subclass, it may change the root entitybinding in case of root entity is abstract + // so the root table is not physical + applyToAllEntityHierarchies( bindIdentifierGeneratorExecutor() ); + + // Resolve associations: + // - determine if JPA @OneToOne translates to Hibernate's one-to-one or unique many-to-one; + // - determine if JPA @OneToMany translates to Hibernate's one-to-many or unique many-to-many. + applyToAllEntityHierarchies( resolveAssociationSourcesExecutor() ); + + // At this point, SourceIndex has all necessary information. + + // Bind all composite attribute containers. This includes composite sub-attributes. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeNature.COMPOSITE ) ); + + // bind basic singular attributes, including composite sub-attributes that are basic. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeNature.BASIC ) ); + + // many-to-one needs to be bound before one-to-one (um, can't remember why). + + // bind non-mappedby many-to-one and one-to-one attributes, including composite sub-attributes that are many-to-one/one-to-one. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeNature.MANY_TO_ONE ) ); + applyToAllEntityHierarchies( bindSingularAttributesExecutor( false, SingularAttributeNature.ONE_TO_ONE ) ); + + // bind mappedby many-to-one and one-to-one attributes, including composite sub-attributes that are many-to-one/one-to-one. + applyToAllEntityHierarchies( bindSingularAttributesExecutor( true, SingularAttributeNature.MANY_TO_ONE ) ); + applyToAllEntityHierarchies( bindSingularAttributesExecutor( true, SingularAttributeNature.ONE_TO_ONE ) ); + + // bind plural attributes (non-mappedBy first), including composite sub-attributes that are plural + applyToAllEntityHierarchies( bindPluralAttributesExecutor( false ) ); + applyToAllEntityHierarchies( bindPluralAttributesExecutor( true ) ); + + // Bind constraints after all attributes have been bound and the + // columns used by attributes is already determined. + applyToAllEntityHierarchies( bindConstraintsExecutor() ); + + // TODO: check if any many-to-one attribute bindings with logicalOneToOne == false have all columns + // (and no formulas) contained in a defined unique key that only contains these columns. + // if so, mark the many-to-one as a logical one-to-one. + // TODO: when does this have to be done. + } + + private BinderStepHierarchyStrategy bindIdentifierGeneratorExecutor() { + return new BinderStepHierarchyStrategy() { + @Override + public void visit(EntityHierarchySource source, BinderLocalBindingContext context) { + bindIdentifierGenerator( context.locateBinding( source ).getRootEntityBinding() ); + } + }; + } + + private void applyToAllEntityHierarchies(BinderStepHierarchyStrategy strategy) { + processHelper.apply( entityHierarchiesByRootEntityName.values(), strategy ); + } + + private void applyToAllEntityHierarchies(BinderStepEntityStrategy strategy) { + processHelper.apply( entityHierarchiesByRootEntityName.values(), strategy ); + } + + private void applyToAllEntityHierarchies(BinderStepCombinedStrategy strategy) { + processHelper.apply( entityHierarchiesByRootEntityName.values(), strategy ); + } + + private void applyToAllEntityHierarchies( + BinderStepHierarchyStrategy hierarchyStrategy, + BinderStepEntityStrategy entityStrategy) { + processHelper.apply( entityHierarchiesByRootEntityName.values(), hierarchyStrategy, entityStrategy ); + } + + private BinderStepEntityStrategy resolveAssociationSourcesExecutor() { + return new BinderStepEntityStrategy() { + @Override + public boolean applyToRootEntity() { + return true; + } + + @Override + public void visit(EntitySource source, BinderLocalBindingContext context) { + sourceIndex.resolveAssociationSources( source, context ); + } + }; + } + + + + + + + + + public BinderLocalBindingContext localBindingContext() { + return rootBindingContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext(); + } + + public HibernateTypeHelper typeHelper() { + return rootBindingContext.typeHelper(); + } + + public RelationalIdentifierHelper relationalIdentifierHelper() { + return rootBindingContext.relationalIdentifierHelper(); + } + + public TableHelper tableHelper() { + return rootBindingContext.tableHelper(); + } + + public ForeignKeyHelper foreignKeyHelper() { + return rootBindingContext.foreignKeyHelper(); + } + + public RelationalValueBindingHelper relationalValueBindingHelper() { + return rootBindingContext.relationalValueBindingHelper(); + } + + public NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper() { + return rootBindingContext.naturalIdUniqueKeyHelper(); + } + + private void bindEntityHierarchiesExcludingNonIdAttributeBindings() { + final BinderStepCombinedStrategy strategy = new BinderStepCombinedStrategy() { + @Override + public void visit(EntityHierarchySource source, BinderLocalBindingContext context) { + final HierarchyDetails binding = context.locateBinding( source ); + bindIdentifier( binding, source ); + bindSecondaryTables( binding.getRootEntityBinding(), source.getRoot() ); + } + + @Override + public boolean applyToRootEntity() { + return false; + } + + @Override + public void visit(EntitySource source, BinderLocalBindingContext context) { + final EntityBinding binding = context.locateBinding( source ); + bindSubEntityPrimaryKey( binding, source ); + bindSecondaryTables( binding, source ); + markSuperEntityTableAbstractIfNecessary( binding.getSuperEntityBinding() ); + } + + private void bindSecondaryTables(EntityBinding entityBinding, EntitySource entitySource) { + for ( final SecondaryTableSource secondaryTableSource : entitySource.getSecondaryTables() ) { + final TableSpecification table = tableHelper().createTable( + secondaryTableSource.getTableSource(), + new TableNamingStrategyHelper( entityBinding ) + ); + table.addComment( secondaryTableSource.getComment() ); + final List joinRelationalValueBindings = getJoinedPrimaryKeyRelationalValueBindings( + entityBinding, + secondaryTableSource.getPrimaryKeyColumnSources(), + table + ); + + // TODO: make the foreign key column the primary key??? + final List targetColumns = foreignKeyHelper() + .determineForeignKeyTargetColumns( entityBinding, secondaryTableSource ); + final ForeignKey foreignKey = locateOrCreateForeignKey( + secondaryTableSource.getExplicitForeignKeyName(), + table, + joinRelationalValueBindings, + foreignKeyHelper().determineForeignKeyTargetTable( entityBinding, secondaryTableSource ), + targetColumns, + secondaryTableSource.isCascadeDeleteEnabled(), + secondaryTableSource.createForeignKeyConstraint() + ); + SecondaryTable secondaryTable = new SecondaryTable( table, foreignKey ); + if ( secondaryTableSource.getFetchStyle()!=null ) { + secondaryTable.setFetchStyle( secondaryTableSource.getFetchStyle() ); + } + secondaryTable.setInverse( secondaryTableSource.isInverse() ); + secondaryTable.setOptional( secondaryTableSource.isOptional() ); + secondaryTable.setCascadeDeleteEnabled( secondaryTableSource.isCascadeDeleteEnabled() ); + secondaryTable.setCustomDelete( secondaryTableSource.getCustomSqlDelete() ); + secondaryTable.setCustomInsert( secondaryTableSource.getCustomSqlInsert() ); + secondaryTable.setCustomUpdate( secondaryTableSource.getCustomSqlUpdate() ); + entityBinding.addSecondaryTable( secondaryTable ); + rootBindingContext.getMetadataCollector().addSecondaryTable( secondaryTable ); + } + } + + private void bindIdentifier(HierarchyDetails binding, EntityHierarchySource source) { + final IdentifierSource identifierSource = source.getIdentifierSource(); + final EntityIdentifierNature nature = identifierSource.getNature(); + + switch ( nature ) { + case SIMPLE: { + bindSimpleIdentifier( + binding, + (SimpleIdentifierSource) identifierSource + ); + break; + } + case AGGREGATED_COMPOSITE: { + bindAggregatedCompositeIdentifier( + binding, + (AggregatedCompositeIdentifierSource) identifierSource + ); + break; + } + case NON_AGGREGATED_COMPOSITE: { + bindNonAggregatedCompositeIdentifier( + binding, + (NonAggregatedCompositeIdentifierSource) identifierSource + ); + break; + } + default: { + throw localBindingContext().makeMappingException( "Unknown identifier nature : " + nature.name() ); + } + } + } + + private void bindSimpleIdentifier( + final HierarchyDetails binding, + final SimpleIdentifierSource identifierSource) { + // locate the attribute binding + final SingularAttributeBinding idAttributeBinding = (SingularAttributeBinding) bindIdentifierAttribute( + binding.getRootEntityBinding(), + identifierSource.getIdentifierAttributeSource() + ); + + // Configure ID generator + IdentifierGeneratorDefinition generator = identifierSource.getIdentifierGeneratorDescriptor(); + if ( generator == null ) { + final Map params = new HashMap(); + params.put( IdentifierGenerator.ENTITY_NAME, binding.getRootEntityBinding().getEntityName() ); + generator = new IdentifierGeneratorDefinition( "default_assign_identity_generator", "assigned", params ); + } + + // determine the unsaved value mapping + final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); + + binding.getEntityIdentifier().prepareAsSimpleIdentifier( + idAttributeBinding, + generator, + unsavedValue, + identifierSource.getLookupIdClass(), + propertyAccessorName( identifierSource.getIdClassPropertyAccessorName() ) + ); + + } + + private String interpretIdentifierUnsavedValue( + final IdentifierSource identifierSource, + final IdentifierGeneratorDefinition generator) { + if ( identifierSource == null ) { + throw new IllegalArgumentException( "identifierSource must be non-null." ); + } + if ( generator == null || StringHelper.isEmpty( generator.getStrategy() ) ) { + throw new IllegalArgumentException( "generator must be non-null and its strategy must be non-empty." ); + } + String unsavedValue = null; + if ( identifierSource.getUnsavedValue() != null ) { + unsavedValue = identifierSource.getUnsavedValue(); + } + else if ( "assigned".equals( generator.getStrategy() ) ) { + unsavedValue = "undefined"; + } + else { + switch ( identifierSource.getNature() ) { + case SIMPLE: { + // unsavedValue = null; + break; + } + case NON_AGGREGATED_COMPOSITE: { + // The generator strategy should be "assigned" and processed above. + throw new IllegalStateException( + String.format( + "Expected generator strategy for composite ID: 'assigned'; instead it is: %s", + generator.getStrategy() + ) + ); + } + case AGGREGATED_COMPOSITE: { + // TODO: if the component only contains 1 attribute (when flattened) + // and it is not an association then null should be returned; + // otherwise "undefined" should be returned. + throw new NotYetImplementedException( + String.format( + "Unsaved value for (%s) identifier not implemented yet.", + identifierSource.getNature() + ) + ); + } + default: { + throw new AssertionFailure( + String.format( + "Unexpected identifier nature: %s", + identifierSource.getNature() + ) + ); + } + } + } + return unsavedValue; + } + + private void bindAggregatedCompositeIdentifier( + final HierarchyDetails binding, + final AggregatedCompositeIdentifierSource identifierSource) { + // locate the attribute binding + final EmbeddedAttributeBinding idAttributeBinding = (EmbeddedAttributeBinding) bindIdentifierAttribute( + binding.getRootEntityBinding(), + identifierSource.getIdentifierAttributeSource() + ); + + // Configure ID generator + IdentifierGeneratorDefinition generator = identifierSource.getIdentifierGeneratorDescriptor(); + if ( generator == null ) { + final Map params = new HashMap(); + params.put( IdentifierGenerator.ENTITY_NAME, binding.getRootEntityBinding().getEntityName() ); + generator = new IdentifierGeneratorDefinition( "default_assign_identity_generator", "assigned", params ); + } + + // determine the unsaved value mapping + final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); + + binding.getEntityIdentifier().prepareAsAggregatedCompositeIdentifier( + idAttributeBinding, + generator, + unsavedValue, + identifierSource.getLookupIdClass(), + propertyAccessorName( identifierSource.getIdClassPropertyAccessorName() ) + ); + } + + private void bindNonAggregatedCompositeIdentifier( + final HierarchyDetails binding, + final NonAggregatedCompositeIdentifierSource identifierSource) { + // locate the attribute bindings for the real attributes + final List idAttributeBindings = new ArrayList(); + for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) { + final SingularAttributeBinding singularAttributeBinding = bindIdentifierAttribute( + binding.getRootEntityBinding(), + attributeSource + ); + idAttributeBindings.add( singularAttributeBinding ); + } + + final Class idClassType = identifierSource.getLookupIdClass(); + final String idClassPropertyAccessorName = idClassType == null + ? null + : propertyAccessorName( identifierSource.getIdClassPropertyAccessorName() ); + + // Configure ID generator + IdentifierGeneratorDefinition generator = identifierSource.getIdentifierGeneratorDescriptor(); + if ( generator == null ) { + final Map params = new HashMap(); + params.put( IdentifierGenerator.ENTITY_NAME, binding.getRootEntityBinding().getEntityName() ); + generator = new IdentifierGeneratorDefinition( "default_assign_identity_generator", "assigned", params ); + } + // Create the synthetic attribute + final SingularAttribute syntheticAttribute = binding.getRootEntityBinding().getEntity().createSyntheticCompositeAttribute( + SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME, + binding.getRootEntityBinding().getEntity() + ); + + final EmbeddedAttributeBinding syntheticAttributeBinding = binding.getRootEntityBinding() + .makeVirtualCompositeAttributeBinding( + syntheticAttribute, + createMetaAttributeContext( + binding.getRootEntityBinding(), + identifierSource.getToolingHintSources() + ), + idAttributeBindings + ); + + // Create the synthetic attribute binding. + binding.getEntityIdentifier().prepareAsNonAggregatedCompositeIdentifier( + syntheticAttributeBinding, + generator, + interpretIdentifierUnsavedValue( identifierSource, generator ), + idClassType, + idClassPropertyAccessorName + ); + + typeHelper().bindNonAggregatedCompositeIdentifierType( + localBindingContext().getServiceRegistry(), + syntheticAttributeBinding, + syntheticAttribute + ); + } + + private void bindSubEntityPrimaryKey(EntityBinding entityBinding, EntitySource entitySource) { + final InheritanceType inheritanceType = entityBinding.getHierarchyDetails().getInheritanceType(); + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + if ( superEntityBinding == null ) { + throw new AssertionFailure( "super entitybinding is null " ); + } + if ( inheritanceType == InheritanceType.JOINED ) { + JoinedSubclassEntitySource subclassEntitySource = (JoinedSubclassEntitySource) entitySource; + final List columnSources = subclassEntitySource.getPrimaryKeyColumnSources(); + final TableSpecification table = entityBinding.getPrimaryTable(); + final List joinRelationalValueBindings = + getJoinedPrimaryKeyRelationalValueBindings( superEntityBinding, columnSources, table ); + + entityBinding.setKeyRelationalValueBindings( joinRelationalValueBindings ); + List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + superEntityBinding, + subclassEntitySource + ); + + ForeignKey foreignKey = locateOrCreateForeignKey( + subclassEntitySource.getExplicitForeignKeyName(), + table, + joinRelationalValueBindings, + foreignKeyHelper().determineForeignKeyTargetTable( + superEntityBinding, + subclassEntitySource + ), + targetColumns, + subclassEntitySource.isCascadeDeleteEnabled(), + subclassEntitySource.createForeignKeyConstraint() + ); + + if ( subclassEntitySource.isCascadeDeleteEnabled() ) { + entityBinding.setCascadeDeleteEnabled( true ); + } + } + } + + private void markSuperEntityTableAbstractIfNecessary(EntityBinding superEntityBinding) { + if ( superEntityBinding == null ) { + return; + } + if ( superEntityBinding.getHierarchyDetails().getInheritanceType() != InheritanceType.TABLE_PER_CLASS ) { + return; + } + if ( superEntityBinding.isAbstract() != Boolean.TRUE ) { + return; + } + if ( !Table.class.isInstance( superEntityBinding.getPrimaryTable() ) ) { + return; + } + Table.class.cast( superEntityBinding.getPrimaryTable() ).setPhysicalTable( false ); + } + }; + + // TODO: need to determine the proper order for processing EntityHierarchySource objects + // so that dependent EntityHierarchySource is processed after the EntityHierarchySource it + // is dependent on. + // For now, just delay processing the dependent entity hierarchies. + final Set unresolvedEntityHierarchies = new HashSet(); + for ( final EntityHierarchySource entityHierarchySource : entityHierarchiesByRootEntityName.values() ) { + if ( isIdentifierDependentOnOtherEntityHierarchy( entityHierarchySource ) ) { + unresolvedEntityHierarchies.add( entityHierarchySource ); + } + else { + processHelper.apply( entityHierarchySource, strategy ); + } + } + + // The following is to try to resolve any dependent entity hierarchies. + // It runs through all the dependent entity hierarchies and resolves what it can. + // This process repeats until no more can be resolved. + // TODO: this will not be necessary once we know the proper order for + // processing entity hierarchies. + int oldSize = Integer.MAX_VALUE; + while( !unresolvedEntityHierarchies.isEmpty() && unresolvedEntityHierarchies.size() < oldSize ) { + oldSize = unresolvedEntityHierarchies.size(); + for ( Iterator it = unresolvedEntityHierarchies.iterator(); it.hasNext(); ) { + final EntityHierarchySource entityHierarchySource = it.next(); + try { + processHelper.apply( entityHierarchySource, strategy ); + // succeeded, so the entityHierarchySource is no longer unresolved. + it.remove(); + } + catch (Exception ex) { + // to nothing; + } + } + } + // If any entity hierarchies cannot be resolved, then throw exception. + if ( ! unresolvedEntityHierarchies.isEmpty() ) { + StringBuilder buffer = new StringBuilder(); + String sep = ""; + for ( EntityHierarchySource unresolved : unresolvedEntityHierarchies ) { + buffer.append( sep ).append( unresolved.getRoot().getEntityName() ); + sep = ", "; + } + throw new IllegalStateException( + "Could not resolve all EntityHierarchies; remaining = {" + buffer.toString() + "}" + ); + } + } + + // TODO: this will not be necessary once we know the proper order for + // processing entity hierarchies. + private boolean isIdentifierDependentOnOtherEntityHierarchy(EntityHierarchySource entityHierarchySource) { + final EntitySource rootEntitySource = entityHierarchySource.getRoot(); + final IdentifierSource identifierSource = entityHierarchySource.getIdentifierSource(); + if ( identifierSource.getNature() != EntityIdentifierNature.SIMPLE ) { + final List subAttributeSources; + if ( identifierSource.getNature() == EntityIdentifierNature.AGGREGATED_COMPOSITE ) { + subAttributeSources = ( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource().getEmbeddableSource().attributeSources(); + } + else { + subAttributeSources = ( (NonAggregatedCompositeIdentifierSource) identifierSource ).getAttributeSourcesMakingUpIdentifier(); + } + return containsSingularAssociation( subAttributeSources ); + } + else { + final SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource; + return simpleIdentifierSource.getIdentifierAttributeSource().getSingularAttributeNature() != SingularAttributeNature.BASIC; + } + } + + // TODO: this will not be necessary once we know the proper order for + // processing entity hierarchies. + private boolean containsSingularAssociation(List subAttributeSources) { + for ( AttributeSource attributeSource : subAttributeSources ) { + SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource; + // If the attribute source is for a -to-one association, the nature may not be resolved yet. + if ( ToOneAttributeSource.class.isInstance( singularAttributeSource ) ) { + return true; + } + else if ( ( (SingularAttributeSource) attributeSource ).getSingularAttributeNature() == SingularAttributeNature.COMPOSITE ) { + EmbeddedAttributeSource embeddedAttributeSource = (EmbeddedAttributeSource) attributeSource; + return containsSingularAssociation( embeddedAttributeSource.getEmbeddableSource().attributeSources() ); + } + } + return false; + } + + private AttributeBindingContainer locateAttributeBindingContainer(final EntityBinding entityBinding, final String containerPath) { + if ( StringHelper.isEmpty( containerPath ) ) { + return entityBinding; + } + + final AttributeBinding attributeBinding = entityBinding.locateAttributeBindingByPath( containerPath, false ); + if ( AttributeBindingContainer.class.isInstance( attributeBinding ) ) { + return (AttributeBindingContainer) attributeBinding; + } + else if ( EmbeddedAttributeBinding.class.isInstance( attributeBinding ) ) { + return ( (EmbeddedAttributeBinding) attributeBinding ).getEmbeddableBinding(); + } + + throw localBindingContext().makeMappingException( + "Could not determine how to treat resolved attribute binding [" + attributeBinding + + "] as AttributeBindingContainer" + ); + } + + private BinderStepEntityStrategy bindSingularAttributesExecutor( + final boolean isMappedBy, + final SingularAttributeNature singularAttributeNature) { + return new BinderStepEntityStrategy() { + @Override + public boolean applyToRootEntity() { + return true; + } + + @Override + public void visit(EntitySource source, BinderLocalBindingContext context) { + final EntityBinding binding = context.locateBinding( source ); + bindSingularAttributes( binding, isMappedBy, singularAttributeNature ); + + } + }; + } + + private Map embeddableToContributingAttributeMap + = new HashMap(); + + + // TODO: create separate methods that are more clear for the cases. + private void bindSingularAttributes( + final EntityBinding entityBinding, + final boolean isMappedBy, + final SingularAttributeNature singularAttributeNature) { + // Get the map of all attributes for the entity binding of the specified nature. + Map map = sourceIndex.getSingularAttributeSources( + entityBinding.getEntityName(), + isMappedBy, + singularAttributeNature + ); + for ( SingularAttributeSource attributeSource : map.values() ) { + final String containerPath = attributeSource.getAttributePath().getParent() == null + ? "" + : attributeSource.getAttributePath().getParent().getFullPath(); + + final AttributeBindingContainer attributeBindingContainer = locateAttributeBindingContainer( entityBinding, containerPath ); + if ( isMappedBy ) { + if ( !ToOneAttributeSource.class.isInstance( attributeSource ) ) { + throw new AssertionFailure( + String.format( + Locale.ENGLISH, + "mappedBy is true, but attributeSource is not an association: %s", + attributeSource.getAttributeRole().getFullPath() + ) + ); + } + bindMappedBySecondaryTableIfNecessary( entityBinding, (ToOneAttributeSource) attributeSource ); + } + + if ( singularAttributeNature == SingularAttributeNature.COMPOSITE ) { + // This only creates the composite attribute container. + EmbeddedAttributeBinding attributeBinding = createAggregatedCompositeAttribute( + attributeBindingContainer, + (EmbeddedAttributeSource) attributeSource, + null + ); + + embeddableToContributingAttributeMap.put( attributeBinding.getEmbeddableBinding(), attributeBinding ); + + Aggregate aggregate = (Aggregate) attributeBinding.getAttribute().getSingularAttributeType(); + + typeHelper().bindAggregatedCompositeAttributeType( + localBindingContext().getServiceRegistry(), + false, + aggregate, + aggregate.getDescriptor(), + attributeBinding + ); + } + else if ( attributeBindingContainer instanceof EmbeddableBinding ) { + // This attribute source is within a composite; skip binding if it is the parent. + final EmbeddableBinding embeddableBinding = (EmbeddableBinding) attributeBindingContainer; + final SingularAttribute parentReference = embeddableBinding.getParentReference(); + + if ( parentReference == null || !parentReference.getName().equals( attributeSource.getName() ) ) { + bindAttribute( attributeBindingContainer, attributeSource ); + + final EmbeddedAttributeBinding embeddedAttributeBinding + = embeddableToContributingAttributeMap.get( embeddableBinding ); + if ( embeddedAttributeBinding == null ) { + throw localBindingContext().makeMappingException( + "Could not resolve embeddable binding back to the attribute that contributed it : " + + attributeSource.getAttributeRole().getFullPath() + ); + } + + final EmbeddedAttributeSource embeddedAttributeSource + = (EmbeddedAttributeSource) sourceIndex.attributeSource( embeddedAttributeBinding.getAttributeRole() ); + if ( embeddedAttributeSource == null ) { + throw localBindingContext().makeMappingException( + "Could not resolve embeddable binding back to the attribute source that contributed it : " + + attributeSource.getAttributeRole().getFullPath() + ); + } + + completeCompositeAttributeBindingIfPossible( + embeddedAttributeBinding, + embeddedAttributeSource + ); + } + } + else { + // The container is the EntityBinding itself. + bindAttribute( attributeBindingContainer, attributeSource ); + } + } + } + + // All sub-attributes must be bound before it's type and ComponentMetamodel can be determined. + private void completeCompositeAttributeBindingIfPossible( + EmbeddedAttributeBinding embeddedAttributeBinding, + EmbeddedAttributeSource compositeAttributeSource) { + // Find out the number of sub-attributes, excluding the parent attribute. + final int nAttributeSourcesExcludingParent = embeddedAttributeBinding.getEmbeddableBinding().getParentReference() != null + ? compositeAttributeSource.getEmbeddableSource().attributeSources().size() - 1 + : compositeAttributeSource.getEmbeddableSource().attributeSources().size(); + if ( embeddedAttributeBinding.getEmbeddableBinding().attributeBindingSpan() == nAttributeSourcesExcludingParent ) { + // All sub-attribute bindings are present; now check if all sub-attributes have + // their type resolved. + boolean allResolved = true; + for ( AttributeBinding attributeBinding : embeddedAttributeBinding.getEmbeddableBinding().attributeBindings() ) { + if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() == null ) { + // Something is not resolved. + allResolved = false; + break; + } + } + if ( allResolved ) { + final Aggregate aggregate = (Aggregate) embeddedAttributeBinding.getAttribute().getSingularAttributeType(); + + // All are resolved, so we can bind the type. + typeHelper().bindAggregatedCompositeAttributeType( + localBindingContext().getServiceRegistry(), + false, + aggregate, + aggregate.getDescriptor(), + embeddedAttributeBinding + ); + // Now check the container. + if ( embeddedAttributeBinding.getContainer() instanceof EmbeddableBinding ) { + // The container is also a EmbeddableBinding. + // We need this process for the container. + final EmbeddedAttributeBinding parentEmbeddedAttributeBinding = embeddableToContributingAttributeMap.get( + embeddedAttributeBinding.getContainer() + ); + final EmbeddedAttributeSource parentCompositeAttributeSource + = (EmbeddedAttributeSource) sourceIndex.attributeSource( parentEmbeddedAttributeBinding.getAttributeRole() ); + + completeCompositeAttributeBindingIfPossible( + parentEmbeddedAttributeBinding, + parentCompositeAttributeSource + ); + } + } + } + } + + private BinderStepEntityStrategy bindPluralAttributesExecutor(final boolean isInverse) { + return new BinderStepEntityStrategy() { + @Override + public boolean applyToRootEntity() { + return true; + } + + @Override + public void visit(EntitySource source, BinderLocalBindingContext context) { + // TODO: may want bind plural attributes of a particular element nature. + final EntityBinding entityBinding = context.locateBinding( source ); + // Get the map for inverse or non-inverse (as specified) plural attributes + Map map = sourceIndex.getPluralAttributeSources( + entityBinding.getEntityName(), + isInverse + ); + for ( PluralAttributeSource attributeSource : map.values() ) { + // Bind the attribute into the appropriate container. + final String containerPath = attributeSource.getAttributePath().getParent() == null + ? "" + : attributeSource.getAttributePath().getParent().getFullPath(); + final AttributeBindingContainer attributeBindingContainer = + locateAttributeBindingContainer( entityBinding, containerPath ); + + bindAttribute( attributeBindingContainer, attributeSource ); + + if ( attributeBindingContainer instanceof EmbeddableBinding ) { + // We just bound a sub-attribute into a EmbeddedAttributeBinding. + final EmbeddableBinding embeddableBinding = (EmbeddableBinding) attributeBindingContainer; + + final EmbeddedAttributeBinding embeddedAttributeBinding = embeddableToContributingAttributeMap.get( + embeddableBinding + ); + + final EmbeddedAttributeSource compositeAttributeSource = (EmbeddedAttributeSource) sourceIndex.attributeSource( + embeddedAttributeBinding.getAttributeRole() + ); + + // Resolve the type if types are resolved for all sub-attributes now. + completeCompositeAttributeBindingIfPossible( embeddedAttributeBinding, compositeAttributeSource ); + } + } + } + }; + } + + + private BinderStepEntityStrategy bindConstraintsExecutor() { + return new BinderStepEntityStrategy() { + @Override + public boolean applyToRootEntity() { + return true; + } + + @Override + public void visit(EntitySource source, BinderLocalBindingContext context) { + final EntityBinding entityBinding = context.locateBinding( source ); + for ( final ConstraintSource constraintSource : source.getConstraints() ) { + final TableSpecification table = findConstraintTable( entityBinding, constraintSource.getTableName() ); + final List columns = new ArrayList(); + for ( final String columnName : constraintSource.columnNames() ) { + final Column column = tableHelper().locateColumn( table, columnName, + new ColumnNamingStrategyHelper( null, false ) ); + if (column == null) { + throw new MappingException( "While creating a constraint, could not find column " + + columnName + " on table "+ table.getLogicalName().getText() ); + } + columns.add( column ); + } + + if ( UniqueConstraintSource.class.isInstance( constraintSource ) ) { + tableHelper().createUniqueKey( table, columns, constraintSource.name() ); + } + else if ( IndexConstraintSource.class.isInstance( constraintSource ) ) { + final IndexConstraintSource indexConstraintSource = (IndexConstraintSource) constraintSource; + tableHelper().createIndex( table, columns, indexConstraintSource.name(), + indexConstraintSource.isUnique() ); + } + } + } + }; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Entity binding relates methods + + private EntityBinding locateEntityBinding( + final JavaTypeDescriptor referencedEntityTypeDescriptor, + final String explicitEntityName) { + final String referencedEntityName; + if ( explicitEntityName != null ) { + referencedEntityName = explicitEntityName; + } + else if ( referencedEntityTypeDescriptor != null ) { + referencedEntityName = referencedEntityTypeDescriptor.getName().toString(); + } + else { + throw new IllegalArgumentException( "explicitEntityName and entityJavaClassReference cannot both be null." ); + } + return locateEntityBinding( referencedEntityName ); + } + + private EntityBinding locateEntityBinding(final String entityName) { + // Check if binding has already been created + EntityBinding entityBinding = rootBindingContext.getMetadataCollector().getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw localBindingContext().makeMappingException( + String.format( "No entity binding with name: %s", entityName ) + ); + } + return entityBinding; + } + + + + private FilterConfiguration createFilterConfiguration(FilterSource filterSource, EntityBinding entityBinding){ + String condition = filterSource.getCondition(); + if(StringHelper.isEmpty( condition )){ + FilterDefinition filterDefinition = rootBindingContext.getMetadataCollector().getFilterDefinitions().get( filterSource.getName() ); + if(filterDefinition == null){ + throw localBindingContext().makeMappingException( + String.format( + "Filter[%s] doesn't have a condition", + filterSource.getName() + ) + ); + } + condition = filterDefinition.getDefaultFilterCondition(); + } + return new FilterConfiguration( + filterSource.getName(), + condition, + filterSource.shouldAutoInjectAliases(), + filterSource.getAliasToTableMap(), + filterSource.getAliasToEntityMap(), + entityBinding + ); + } + + private void bindPrimaryTable( + final EntityBinding entityBinding, + final EntitySource entitySource) { + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + final InheritanceType inheritanceType = entityBinding.getHierarchyDetails().getInheritanceType(); + final TableSpecification table; + final String tableName; + if ( superEntityBinding != null && inheritanceType == InheritanceType.SINGLE_TABLE ) { + // single table and sub entity + table = superEntityBinding.getPrimaryTable(); + tableName = superEntityBinding.getPrimaryTableName(); + } + else { + // single table and root entity + // joined + // table per class and non-abstract entity + Table includedTable = null; + if ( superEntityBinding != null + && inheritanceType == InheritanceType.TABLE_PER_CLASS + && Table.class.isInstance( superEntityBinding.getPrimaryTable() ) ) { + includedTable = Table.class.cast( superEntityBinding.getPrimaryTable() ); + } + table = tableHelper().createTable( + entitySource.getPrimaryTable(), new TableNamingStrategyHelper( entityBinding ), includedTable + ); + tableName = table.getLogicalName().getText(); + } + + entityBinding.setPrimaryTable( table ); + entityBinding.setPrimaryTableName( tableName ); + } + + private void bindMappedBySecondaryTableIfNecessary(EntityBinding entityBinding, ToOneAttributeSource attributeSource) { + if ( ! attributeSource.isMappedBy() ) { + throw new IllegalArgumentException( "attributeSource does not have mappedBy defined." ); + } + final MappedByAssociationSource mappedByAssociationSource = (MappedByAssociationSource) attributeSource; + + final ToOneAttributeSource ownerAttributeSource = (ToOneAttributeSource) sourceIndex.attributeSource( + mappedByAssociationSource.getReferencedEntityName(), + mappedByAssociationSource.getMappedBy() + ); + if ( ownerAttributeSource.isMappedBy() ) { + throw new AssertionFailure( "owner attribute source has mappedBy != null" ); + } + + final EntityBinding ownerEntityBinding = locateEntityBinding( attributeSource.getReferencedEntityName() ); + + if ( ownerAttributeSource.getSingularAttributeNature() == SingularAttributeNature.ONE_TO_ONE || + ownerAttributeSource.getContainingTableName() == null || + ownerAttributeSource.getContainingTableName().equals( ownerEntityBinding.getPrimaryTableName() ) ) { + // primary table is used, so no need to bind an inverse secondary table. + return; + } + + final AttributeBinding ownerAttributeBinding = + ownerEntityBinding.locateAttributeBindingByPath( mappedByAssociationSource.getMappedBy(), true ); + if ( !SingularAssociationAttributeBinding.class.isInstance( ownerAttributeBinding ) ) { + throw new AssertionFailure( "Owner is not a one-to-one or many-to-one association." ); + } + final SingularAssociationAttributeBinding ownerAssociationAttributeBinding = + (SingularAssociationAttributeBinding) ownerAttributeBinding; + + // If the owner side of the association uses a secondary table, then an inverse secondary table needs + // to be bound for the entity binding containing the mappedBy attribute.. + final TableSpecification ownerTable = ownerAssociationAttributeBinding.getTable(); + if ( !ownerEntityBinding.getPrimaryTable().equals( ownerTable ) ) { + final SecondaryTable ownerSecondaryTable = + ownerEntityBinding.getSecondaryTables().get( + ownerTable.getLogicalName() + ); + if ( ownerSecondaryTable == null ) { + throw new AssertionFailure( "Owner association does not use primary table, but no secondary table was found." ); + } + } + + if ( entityBinding.getPrimaryTable().equals( ownerTable ) || + entityBinding.getSecondaryTables().containsKey( ownerTable.getLogicalName() ) ) { + // table already exists; nothing to do. + return; + } + + // locate the foreign key + final List targetColumns = new ArrayList( ownerAssociationAttributeBinding.getRelationalValueBindings().size() ); + for ( Value targetValue : ownerAssociationAttributeBinding.getReferencedAttributeBinding().getValues() ) { + targetColumns.add( (Column) targetValue ); + } + final ForeignKey foreignKey = foreignKeyHelper().locateOrCreateForeignKey( + null, + ownerTable, + extractColumnsFromRelationalValueBindings( ownerAssociationAttributeBinding.getRelationalValueBindings() ), + entityBinding.getPrimaryTable(), + targetColumns, + attributeSource.isCascadeDeleteEnabled(), + true + ); + if ( foreignKey == null ) { + throw new AssertionFailure( "Foreign key not found; should have been defined by owner side of association." ); + } + final SecondaryTable ownerSecondaryTable = ownerEntityBinding.getSecondaryTables().get( ownerTable.getLogicalName() ); + SecondaryTable secondaryTable = new SecondaryTable( ownerTable, foreignKey ); + secondaryTable.setInverse( true ); + secondaryTable.setOptional( ownerSecondaryTable.isOptional() ); + // TODO: how should this be set??? + secondaryTable.setCascadeDeleteEnabled( false ); + secondaryTable.setCustomDelete( ownerSecondaryTable.getCustomDelete() ); + secondaryTable.setCustomInsert( ownerSecondaryTable.getCustomInsert() ); + secondaryTable.setCustomUpdate( ownerSecondaryTable.getCustomUpdate() ); + entityBinding.addSecondaryTable( secondaryTable ); + rootBindingContext.getMetadataCollector().addSecondaryTable( secondaryTable ); + } + + + + private List getJoinedPrimaryKeyRelationalValueBindings( + EntityBinding entityBinding, + List joinedPrimaryKeyColumnSources, + TableSpecification table) { + final List primaryKeyColumns = entityBinding.getPrimaryTable().getPrimaryKey().getColumns(); + + final List joinRelationalValueBindings; + // TODO: deal with property-refs??? + if ( joinedPrimaryKeyColumnSources.isEmpty() ) { + joinRelationalValueBindings = new ArrayList( primaryKeyColumns.size() ); + for ( Column joinedColumn : primaryKeyColumns ) { + Column joinColumn = table.locateOrCreateColumn( + localBindingContext().getBuildingOptions().getNamingStrategy().joinKeyColumnName( + joinedColumn.getColumnName().getText(), + entityBinding.getPrimaryTable().getLogicalName().getText() + ) + ); + joinColumn.setNullable( false ); + table.getPrimaryKey().addColumn( joinColumn ); + joinRelationalValueBindings.add( new RelationalValueBinding( entityBinding.getPrimaryTable(), joinColumn, true, false ) ); + } + } + else { + joinRelationalValueBindings = CollectionHelper.arrayList( joinedPrimaryKeyColumnSources.size() ); + if ( primaryKeyColumns.size() != joinedPrimaryKeyColumnSources.size() ) { + throw localBindingContext().makeMappingException( + String.format( + "The number of primary key column sources provided for a secondary table is not equal to the number of columns in the primary key for [%s].", + entityBinding.getEntityName() + ) + ); + } + for ( int i = 0; i < primaryKeyColumns.size(); i++ ) { + // todo : apply naming strategy to infer missing column name + final ColumnSource joinColumnSource = joinedPrimaryKeyColumnSources.get( i ); + Column column = table.locateColumn( joinColumnSource.getName() ); + if ( column == null ) { + column = tableHelper().locateOrCreateColumn( + table, + joinColumnSource, + new ColumnNamingStrategyHelper( + null, + false + ), + true, + false + ); + table.getPrimaryKey().addColumn( column ); + } + joinRelationalValueBindings.add( new RelationalValueBinding( table, column, true, false ) ); + } + } + typeHelper().bindJdbcDataType( + entityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(), + joinRelationalValueBindings + ); + return joinRelationalValueBindings; + } + + public ForeignKey locateOrCreateForeignKey( + final String foreignKeyName, + final TableSpecification sourceTable, + final List sourceRelationalValueBindings, + final TableSpecification targetTable, + final List targetColumns, + boolean isCascadeDeleteEnabled, + boolean createConstraint) { + return foreignKeyHelper().locateOrCreateForeignKey( + foreignKeyName, + sourceTable, + extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ), + targetTable, + targetColumns, + isCascadeDeleteEnabled, + createConstraint + ); + } + + // TODO: try to get rid of this... + private static List extractColumnsFromRelationalValueBindings( + final List valueBindings) { + List columns = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : valueBindings ) { + final Value value = relationalValueBinding.getValue(); + // todo : currently formulas are not supported here... :( + if ( !Column.class.isInstance( value ) ) { + throw new NotYetImplementedException( + "Derived values are not supported when creating a foreign key that targets columns." + ); + } + columns.add( (Column) value ); + } + return columns; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ identifier binding relates methods + + + + private void bindIdentifierGenerator(final EntityBinding rootEntityBinding) { + final Properties properties = new Properties(); + properties.putAll( + rootBindingContext.getBuildingOptions() + .getServiceRegistry() + .getService( ConfigurationService.class ) + .getSettings() + ); + if ( !properties.contains( AvailableSettings.PREFER_POOLED_VALUES_LO ) ) { + properties.put( AvailableSettings.PREFER_POOLED_VALUES_LO, "false" ); + } + if ( !properties.contains( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER ) ) { + properties.put( + PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, + rootBindingContext.getMetadataCollector().getObjectNameNormalizer() + ); + } + final EntityIdentifier entityIdentifier = rootEntityBinding.getHierarchyDetails().getEntityIdentifier(); + entityIdentifier.createIdentifierGenerator( + rootBindingContext.getMetadataCollector().getIdentifierGeneratorFactory(), + properties + ); + if ( IdentityGenerator.class.isInstance( entityIdentifier.getIdentifierGenerator() ) ) { + if ( rootEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() != 1 ) { + throw localBindingContext().makeMappingException( + String.format( + "ID for %s is mapped as an identity with %d columns. IDs mapped as an identity can only have 1 column.", + rootEntityBinding.getEntityName(), + rootEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() + ) + ); + } + rootEntityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).setIdentity( true ); + } + if ( PersistentIdentifierGenerator.class.isInstance( entityIdentifier.getIdentifierGenerator() ) ) { + ( (PersistentIdentifierGenerator) entityIdentifier.getIdentifierGenerator() ).registerExportables( + rootBindingContext.getMetadataCollector().getDatabase() + ); + } + } + + private SingularAttributeBinding bindIdentifierAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return bindSingularAttribute( attributeBindingContainer, attributeSource, true ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Attributes binding relates methods + private void bindAttributes( + final AttributeBindingContainer attributeBindingContainer, + final AttributeSourceContainer attributeSourceContainer) { + for ( final AttributeSource attributeSource : attributeSourceContainer.attributeSources() ) { + bindAttribute( attributeBindingContainer, attributeSource ); + } + } + + private void bindAttributes( + final EmbeddableBinding embeddableBinding, + final AttributeSourceContainer attributeSourceContainer) { + if ( embeddableBinding.getParentReference() == null ) { + bindAttributes( + (AttributeBindingContainer) embeddableBinding, + attributeSourceContainer + ); + } + else { + for ( final AttributeSource subAttributeSource : attributeSourceContainer.attributeSources() ) { + if ( !subAttributeSource.getName().equals( embeddableBinding.getParentReference().getName() ) ) { + bindAttribute( + embeddableBinding, + subAttributeSource + ); + } + } + } + + } + + private AttributeBinding bindAttribute( + final AttributeBindingContainer attributeBindingContainer, + final AttributeSource attributeSource) { + // Return existing binding if available + final String attributeName = attributeSource.getName(); + final AttributeBinding attributeBinding = attributeBindingContainer.locateAttributeBinding( attributeName ); + if ( attributeBinding != null ) { + return attributeBinding; + } + if ( attributeSource.isSingular() ) { + return bindSingularAttribute( + attributeBindingContainer, + SingularAttributeSource.class.cast( attributeSource ), + false + ); + } + else { + return bindPluralAttribute( + attributeBindingContainer, + PluralAttributeSource.class.cast( attributeSource ) + ); + } + } + + private BasicAttributeBinding bindBasicAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource, + SingularAttribute attribute) { + if ( attribute == null ) { + attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); + } + final List relationalValueBindings = relationalValueBindingHelper().createRelationalValueBindings( + attributeBindingContainer, + attributeSource, + attribute, + locateDefaultTableSpecificationForAttribute( attributeBindingContainer, attributeSource ), + false + ); + final BasicAttributeBinding attributeBinding = attributeBindingContainer.makeBasicAttributeBinding( + attribute, + relationalValueBindings, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + attributeSource.getNaturalIdMutability(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath(), + attributeSource.getGeneration() + ); + typeHelper().bindSingularAttributeType( + attributeSource, + attributeBinding + ); + return attributeBinding; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ singular attributes binding + private SingularAttributeBinding bindSingularAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource, + final boolean isIdentifierAttribute) { + final SingularAttributeNature singularAttributeNature = attributeSource.getSingularAttributeNature(); + final SingularAttribute attribute = + attributeBindingContainer.getAttributeContainer().locateSingularAttribute( attributeSource.getName() ); + switch ( singularAttributeNature ) { + case BASIC: + return bindBasicAttribute( attributeBindingContainer, attributeSource, attribute ); + case ONE_TO_ONE: + return bindOneToOneAttribute( + attributeBindingContainer, + ToOneAttributeSource.class.cast( attributeSource ), + attribute + ); + case MANY_TO_ONE: + return bindManyToOneAttribute( + attributeBindingContainer, + ToOneAttributeSource.class.cast( attributeSource ), + attribute + ); + case COMPOSITE: + return bindAggregatedCompositeAttribute( + attributeBindingContainer, + EmbeddedAttributeSource.class.cast( attributeSource ), + attribute, + isIdentifierAttribute + ); + default: + throw new NotYetImplementedException( singularAttributeNature.toString() ); + } + } + + private EmbeddedAttributeBinding bindAggregatedCompositeAttribute( + final AttributeBindingContainer attributeBindingContainer, + final EmbeddedAttributeSource attributeSource, + SingularAttribute attribute, + boolean isAttributeIdentifier) { + EmbeddedAttributeBinding attributeBinding = createAggregatedCompositeAttribute( + attributeBindingContainer, attributeSource, attribute + ); + bindAttributes( attributeBinding.getEmbeddableBinding(), attributeSource.getEmbeddableSource() ); + typeHelper().bindAggregatedCompositeAttributeType( + localBindingContext().getServiceRegistry(), + isAttributeIdentifier, + (Aggregate) attributeBinding.getAttribute().getSingularAttributeType(), + null, // TODO: don't have the default value at this point; shouldn't be needed... + attributeBinding + ); + return attributeBinding; + } + + private EmbeddedAttributeBinding createAggregatedCompositeAttribute( + final AttributeBindingContainer attributeBindingContainer, + final EmbeddedAttributeSource attributeSource, + SingularAttribute attribute) { + final Aggregate composite; + if ( attribute == null ) { + // see if the AttributeContainer already has an attribute for this name... + attribute = attributeBindingContainer.getAttributeContainer().locateCompositeAttribute( + attributeSource.getName() + ); + if ( attribute != null ) { + // validate its ok to use... + if ( !Aggregate.class.isInstance( attribute.getSingularAttributeType() ) ) { + throw localBindingContext().makeMappingException( + "Found existing attribute on container for '" + attributeSource.getName() + + "', but was expecting an Aggregate" + ); + } + composite = (Aggregate) attribute.getSingularAttributeType(); + } + else { + final JavaTypeDescriptor compositeTypeDescriptor; + if ( attributeSource.getEmbeddableSource().getTypeDescriptor() != null ) { + compositeTypeDescriptor = attributeSource.getEmbeddableSource().getTypeDescriptor(); + } + else { + final EntityMode entityMode = + attributeBindingContainer.seekEntityBinding().getHierarchyDetails().getEntityMode(); + compositeTypeDescriptor = typeHelper().determineJavaType( + attributeSource, + attributeBindingContainer.getAttributeContainer(), + entityMode + ); + } + composite = new Aggregate( compositeTypeDescriptor, null ); + attribute = attributeBindingContainer.getAttributeContainer().createCompositeAttribute( + attributeSource.getName(), + composite + ); + } + } + else { + composite = (Aggregate) attribute.getSingularAttributeType(); + } + + final SingularAttribute referencingAttribute = StringHelper.isEmpty( attributeSource.getEmbeddableSource().getParentReferenceAttributeName() ) + ? null + : composite.createSingularAttribute( attributeSource.getEmbeddableSource().getParentReferenceAttributeName() ); + final NaturalIdMutability naturalIdMutability = attributeSource.getNaturalIdMutability(); + + Class tuplizerClass = null; + if ( attributeSource.getEmbeddableSource().getExplicitTuplizerClassName() != null ) { + tuplizerClass = localBindingContext().getBuildingOptions().getServiceRegistry() + .getService( ClassLoaderService.class ) + .classForName( attributeSource.getEmbeddableSource().getExplicitTuplizerClassName() ); + } + final EmbeddedAttributeBinding attributeBinding = attributeBindingContainer.makeAggregatedCompositeAttributeBinding( + attribute, + referencingAttribute, + tuplizerClass, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + naturalIdMutability, + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath() + ); + + return attributeBinding; + } + + private ManyToOneAttributeBinding bindManyToOneAttribute( + final AttributeBindingContainer attributeBindingContainer, + final ToOneAttributeSource attributeSource, + SingularAttribute attribute) { + if ( attribute == null ) { + attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); + } + + final JavaTypeDescriptor referencedEntityTypeDescriptor = typeHelper().determineJavaType( + attributeSource, + attributeBindingContainer.getAttributeContainer() + ); + final EntityBinding referencedEntityBinding = locateEntityBinding( + referencedEntityTypeDescriptor, + attributeSource.getReferencedEntityName() + ); + + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + + //now find the referenced attribute binding, either the referenced entity's id attribute or the referenced attribute + //todo referenced entityBinding null check? + final SingularAttributeBinding referencedAttributeBinding = resolver.resolveManyToOneReferencedAttributeBinding( + attributeBindingContainer, + attributeSource, + referencedEntityBinding + ); + + // todo : currently a chicken-egg problem here between creating the attribute binding and binding its FK values... + // now we have everything to create the attribute binding + final ManyToOneAttributeBinding attributeBinding = attributeBindingContainer.makeManyToOneAttributeBinding( + attribute, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + attributeSource.isIgnoreNotFound(), + attributeSource.getNaturalIdMutability(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath(), + referencedEntityBinding, + referencedAttributeBinding + ); + + /** + * this is not correct, here, if no @JoinColumn defined, we simply create the FK column only with column calucated + * but what we should do is get all the column info from the referenced column(s), including nullable, size etc. + */ + final List relationalValueBindings = resolver.resolveManyToOneRelationalValueBindings( + attributeSource, + attributeBindingContainer, + referencedAttributeBinding, + referencedEntityBinding + ); + final ForeignKey foreignKey = + relationalValueBindings.isEmpty() || relationalValueBindingHelper().hasDerivedValue( relationalValueBindings ) ? + null : + resolver.resolveManyToOneForeignKey( + attributeSource, + attributeBindingContainer, + relationalValueBindings, + referencedEntityBinding + ); + attributeBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); + + // Type resolution... + if ( !attribute.isTypeResolved() ) { + attribute.resolveType( referencedEntityBinding.getEntity() ); + } + + if ( referencedAttributeBinding != referencedEntityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() ) { + referencedAttributeBinding.setAlternateUniqueKey( true ); + } + + final SingularAttributeBinding idAttributeBinding = + referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + final String uniqueKeyAttributeName = idAttributeBinding == referencedAttributeBinding + ? null + : referencedAttributeBinding.getAttributePath().getFullPath(); + + final Type resolvedType = rootBindingContext.getMetadataCollector().getTypeResolver().getTypeFactory().manyToOne( + referencedEntityBinding.getEntityName(), + uniqueKeyAttributeName == null, + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeSource.isIgnoreNotFound(), + attributeSource.isUnique() + ); + typeHelper().bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + attributeSource.getTypeInformation(), + referencedEntityTypeDescriptor, + resolvedType + ); + + typeHelper().bindJdbcDataType( + attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + attributeBinding.getRelationalValueBindings() + ); + + bindToOneDetails( attributeSource, attributeBinding ); + + return attributeBinding; + } + + private OneToOneAttributeBinding bindOneToOneAttribute( + final AttributeBindingContainer attributeBindingContainer, + final ToOneAttributeSource attributeSource, + SingularAttribute attribute) { + if ( attribute == null ) { + attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); + } + final JavaTypeDescriptor referencedEntityJavaClassReference = typeHelper().determineJavaType( + attributeSource, + attributeBindingContainer.getAttributeContainer() + ); + final EntityBinding referencedEntityBinding = locateEntityBinding( + referencedEntityJavaClassReference, + attributeSource.getReferencedEntityName() + ); + + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + + //now find the referenced attribute binding, either the referenced entity's id attribute or the referenced attribute + //todo referenced entityBinding null check? + final SingularAttributeBinding referencedAttributeBinding = resolver.resolveOneToOneReferencedAttributeBinding( + attributeSource, + referencedEntityBinding + ); + // todo : currently a chicken-egg problem here between creating the attribute binding and binding its FK values... + // now we have everything to create the attribute binding + final OneToOneAttributeBinding attributeBinding = attributeBindingContainer.makeOneToOneAttributeBinding( + attribute, + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + attributeSource.getNaturalIdMutability(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath(), + referencedEntityBinding, + referencedAttributeBinding, + attributeSource.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT + ); + + /** + * this is not correct, here, if no @JoinColumn defined, we simply create the FK column only with column calucated + * but what we should do is get all the column info from the referenced column(s), including nullable, size etc. + */ + final List relationalValueBindings = resolver.resolveOneToOneRelationalValueBindings( + attributeSource, + attributeBindingContainer, + referencedAttributeBinding + ); + final ForeignKey foreignKey; + if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT ) { + foreignKey = resolver.resolveOneToOneForeignKey( + attributeSource, + attributeBinding.getContainer().getPrimaryTable(), + attributeBinding.getContainer().getPrimaryTable().getPrimaryKey().getColumns(), + referencedEntityBinding + ); + } + else { + foreignKey = null; + } + attributeBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); + + // Type resolution... + if ( !attribute.isTypeResolved() ) { + attribute.resolveType( referencedEntityBinding.getEntity() ); + } + + final String uniqueKeyAttributeName; + final AttributeBinding referencedEntityIdAttributeBinding = + referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + if ( referencedEntityIdAttributeBinding == referencedAttributeBinding || + referencedAttributeBinding.getRelationalValueBindings().isEmpty()) { + uniqueKeyAttributeName = null; + } + else { + uniqueKeyAttributeName = referencedAttributeBinding.getAttributePath().getFullPath(); + } + final Type resolvedType; + if ( attributeSource.isMappedBy() || attributeSource.relationalValueSources().isEmpty() ) { + resolvedType = rootBindingContext.getMetadataCollector().getTypeResolver().getTypeFactory().oneToOne( + referencedEntityBinding.getEntityName(), + attributeSource.getForeignKeyDirection(), + uniqueKeyAttributeName == null, + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeBindingContainer.seekEntityBinding().getEntityName(), + attribute.getName() + ); + } + else { + resolvedType = rootBindingContext.getMetadataCollector().getTypeResolver().getTypeFactory().specialOneToOne( + referencedEntityBinding.getEntityName(), + attributeSource.getForeignKeyDirection(), + uniqueKeyAttributeName == null, + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeBindingContainer.seekEntityBinding().getEntityName(), + attribute.getName() + ); + } + + typeHelper().bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + attributeSource.getTypeInformation(), + referencedEntityJavaClassReference, + resolvedType + ); + if ( !attributeBinding.getRelationalValueBindings().isEmpty() ) { + typeHelper().bindJdbcDataType( + attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + attributeBinding.getRelationalValueBindings() + ); + } + bindToOneDetails( attributeSource, attributeBinding ); + + return attributeBinding; + } + + private void bindToOneDetails( + final ToOneAttributeSource attributeSource, + final SingularAssociationAttributeBinding attributeBinding) { + final SingularAttributeBinding idAttributeBinding = + attributeBinding.getReferencedEntityBinding().getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + if ( attributeBinding.getReferencedAttributeBinding() != idAttributeBinding ) { + attributeBinding.getReferencedAttributeBinding().setAlternateUniqueKey( true ); + } + attributeBinding.setCascadeStyle( determineCascadeStyle( attributeSource.getCascadeStyles() ) ); + attributeBinding.setFetchTiming( attributeSource.getFetchTiming() ); + attributeBinding.setFetchStyle( attributeSource.getFetchStyle() ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ plural attributes binding + private AbstractPluralAttributeBinding bindPluralAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource) { + final PluralAttributeNature nature = attributeSource.getNature(); + final PluralAttribute attribute = + attributeBindingContainer.getAttributeContainer().locatePluralAttribute( attributeSource.getName() ); + final AbstractPluralAttributeBinding attributeBinding; + switch ( nature ) { + case BAG: + attributeBinding = bindBagAttribute( attributeBindingContainer, attributeSource, attribute ); + break; + case SET: + attributeBinding = bindSetAttribute( attributeBindingContainer, attributeSource, attribute ); + break; + case LIST: + attributeBinding = bindListAttribute( + attributeBindingContainer, + (IndexedPluralAttributeSource) attributeSource, + attribute + ); + break; + case MAP: + attributeBinding = bindMapAttribute( + attributeBindingContainer, + attributeSource, + attribute + ); + break; + case ARRAY: + attributeBinding = bindArrayAttribute( + attributeBindingContainer, + (IndexedPluralAttributeSource) attributeSource, + attribute + ); + break; + default: + throw new NotYetImplementedException( nature.toString() ); + } + + // Must do first -- sorting/ordering can determine the resolved type + // (ex: Set vs. SortedSet). + bindSortingAndOrdering( attributeBinding, attributeSource ); + + if ( attributeSource.getFilterSources() != null ) { + for ( final FilterSource filterSource : attributeSource.getFilterSources() ) { + attributeBinding.addFilterConfiguration( createFilterConfiguration( filterSource, null ) ); + } + } + + // Note: Collection types do not have a relational model + attributeBinding.setFetchTiming( attributeSource.getFetchTiming() ); + attributeBinding.setFetchStyle( attributeSource.getFetchStyle() ); + if ( attributeSource.getFetchStyle() == FetchStyle.SUBSELECT ) { + attributeBindingContainer.seekEntityBinding().setSubselectLoadableCollections( true ); + } + + attributeBinding.getCaching().overlay( attributeSource.getCaching() ); + + if ( StringHelper.isNotEmpty( attributeSource.getCustomPersisterClassName() ) ) { + attributeBinding.setExplicitPersisterClass( + localBindingContext().getClassLoaderAccess().classForName( + attributeSource.getCustomPersisterClassName() + ) + ); + } + attributeBinding.setCustomLoaderName( attributeSource.getCustomLoaderName() ); + attributeBinding.setCustomSqlInsert( attributeSource.getCustomSqlInsert() ); + attributeBinding.setCustomSqlUpdate( attributeSource.getCustomSqlUpdate() ); + attributeBinding.setCustomSqlDelete( attributeSource.getCustomSqlDelete() ); + attributeBinding.setCustomSqlDeleteAll( attributeSource.getCustomSqlDeleteAll() ); + attributeBinding.setWhere( attributeSource.getWhere() ); + attributeBinding.setMutable( attributeSource.isMutable() ); + attributeBinding.setBatchSize( attributeSource.getBatchSize() ); + ClassLoaderService cls = localBindingContext().getServiceRegistry().getService( ClassLoaderService.class ); + ReflectedCollectionJavaTypes reflectedCollectionJavaTypes = HibernateTypeHelper.getReflectedCollectionJavaTypes( + cls, + attributeBinding + ); + switch ( attributeSource.getElementSource().getNature() ) { + case BASIC: + bindBasicPluralAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case ONE_TO_MANY: + bindOneToManyAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case MANY_TO_MANY: + bindManyToManyAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case AGGREGATE: + bindPluralAggregateAttribute( attributeSource, attributeBinding, reflectedCollectionJavaTypes ); + break; + case MANY_TO_ANY: + //todo?? + default: + throw localBindingContext().makeMappingException( + String.format( + "Unknown type of collection element: %s", + attributeSource.getElementSource().getNature() + ) + ); + } + // Cannot resolve plural attribute type until after the element binding is bound. + final Type resolvedType = typeHelper().resolvePluralType( cls, attributeBinding, attributeSource, nature ); + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + JavaTypeDescriptor defaultCollectionTypeDescriptor = typeHelper().reflectedCollectionClassReference( + reflectedCollectionJavaTypes + ); + if ( defaultCollectionTypeDescriptor == null ) { + defaultCollectionTypeDescriptor = localBindingContext().typeDescriptor( + attributeSource.getNature().reportedJavaType().getName() + ); + } + typeHelper().bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + attributeSource.getTypeInformation(), + defaultCollectionTypeDescriptor, + resolvedType + ); + if ( attributeBinding.hasIndex() ) { + bindPluralAttributeIndex( + (IndexedPluralAttributeSource) attributeSource, + (IndexedPluralAttributeBinding) attributeBinding, + reflectedCollectionJavaTypes + ); + } + bindCollectionTablePrimaryKey( attributeBinding, attributeSource ); + rootBindingContext.getMetadataCollector().addCollection( attributeBinding ); + return attributeBinding; + } + + private AbstractPluralAttributeBinding bindBagAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createBag( attributeSource.getName() ); + } + return attributeBindingContainer.makeBagAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath() + ); + } + + private AbstractPluralAttributeBinding bindListAttribute( + final AttributeBindingContainer attributeBindingContainer, + final IndexedPluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createList( attributeSource.getName() ); + } + return attributeBindingContainer.makeListAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath(), + getSequentialPluralAttributeIndexBase( attributeSource ) + ); + } + + private AbstractPluralAttributeBinding bindArrayAttribute( + final AttributeBindingContainer attributeBindingContainer, + final IndexedPluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createArray( attributeSource.getName() ); + } + return attributeBindingContainer.makeArrayAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath(), + getSequentialPluralAttributeIndexBase( attributeSource ) + ); + } + + private int getSequentialPluralAttributeIndexBase(IndexedPluralAttributeSource pluralAttributeSource) { + final PluralAttributeIndexSource indexedPluralAttributeSource = pluralAttributeSource.getIndexSource(); + if ( ! PluralAttributeSequentialIndexSource.class.isInstance( indexedPluralAttributeSource ) ) { + throw new IllegalArgumentException( + String.format( + "Expected an argument of type: %s; instead, got %s", + PluralAttributeSequentialIndexSource.class.getName(), + indexedPluralAttributeSource.getClass().getName() + ) + ); + } + return ( (PluralAttributeSequentialIndexSource) indexedPluralAttributeSource ).base(); + } + + private AbstractPluralAttributeBinding bindMapAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createMap( attributeSource.getName() ); + } + return attributeBindingContainer.makeMapAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + pluralAttributeIndexNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath() + ); + } + + private AbstractPluralAttributeBinding bindSetAttribute( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource, + PluralAttribute attribute) { + if ( attribute == null ) { + attribute = attributeBindingContainer.getAttributeContainer().createSet( attributeSource.getName() ); + } + return attributeBindingContainer.makeSetAttributeBinding( + attribute, + pluralAttributeElementNature( attributeSource ), + determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ), + propertyAccessorName( attributeSource ), + attributeSource.isIncludedInOptimisticLocking(), + createMetaAttributeContext( attributeBindingContainer, attributeSource ), + attributeSource.getAttributeRole(), + attributeSource.getAttributePath() + ); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ collection attributes binding + + private void bindBasicCollectionElement( + final PluralAttributeElementBindingBasic elementBinding, + final PluralAttributeElementSourceBasic elementSource, + final JavaTypeDescriptor defaultElementJavaClassReference) { + bindBasicPluralElementRelationalValues( elementSource, elementBinding ); + typeHelper().bindBasicCollectionElementType( elementBinding, elementSource, defaultElementJavaClassReference ); + elementBinding.getPluralAttributeBinding().getAttribute().setElementType( + localBindingContext().makeDomainType( + elementBinding.getHibernateTypeDescriptor().getJavaTypeDescriptor().getName() + ) + ); + } + + private void bindNonAssociationCollectionKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource) { + if ( attributeSource.getElementSource().getNature() != PluralAttributeElementNature.BASIC && + attributeSource.getElementSource().getNature() != PluralAttributeElementNature.AGGREGATE ) { + throw new AssertionFailure( + String.format( + "Expected basic or aggregate attribute binding; instead got {%s}", + attributeSource.getElementSource().getNature() + ) + ); + } + attributeBinding.getPluralAttributeKeyBinding().setInverse( false ); + TableSpecification collectionTable = tableHelper().createTable( + attributeSource.getCollectionTableSpecificationSource(), + new CollectionTableNamingStrategyHelper( attributeBinding ) + ); + if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableComment() ) ) { + collectionTable.addComment( attributeSource.getCollectionTableComment() ); + } + if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableCheck() ) ) { + collectionTable.addCheckConstraint( attributeSource.getCollectionTableCheck() ); + } + bindCollectionTableJoinRelationalValueBindings( + attributeBinding, + attributeSource, + collectionTable + ); + } + + private Aggregate findOrBuildAggregate(JavaTypeDescriptor embeddableDescriptor) { + org.hibernate.metamodel.spi.domain.Type domainType = domainModelTypes.get( embeddableDescriptor ); + if ( domainType == null ) { + domainType = new Aggregate( embeddableDescriptor, null ); + domainModelTypes.put( embeddableDescriptor, domainType ); + } + + if ( !Aggregate.class.isInstance( domainType ) ) { + throw new IllegalStateException( + String.format( + Locale.ENGLISH, + "Found previously built domain type for Aggregate JavaTypeDescriptor [%s] which was not Aggregate : %s", + embeddableDescriptor.getName(), + domainType.getName() + ) + ); + } + + return (Aggregate) domainType; + } + + private void bindCompositeCollectionElement( + final PluralAttributeElementBindingEmbedded elementBinding, + final PluralAttributeElementSourceEmbedded elementSource, + final JavaTypeDescriptor reflectedElementTypeDescriptor) { + final PluralAttributeBinding pluralAttributeBinding = elementBinding.getPluralAttributeBinding(); + // Create the aggregate type + final JavaTypeDescriptor elementTypeDescriptor; + if ( elementSource.getEmbeddableSource().getTypeDescriptor() != null ) { + elementTypeDescriptor = elementSource.getEmbeddableSource().getTypeDescriptor(); + } + else { + elementTypeDescriptor = reflectedElementTypeDescriptor; + } + + final Aggregate aggregate = findOrBuildAggregate( elementTypeDescriptor ); + + final String parentReferenceAttributeName = StringHelper.nullIfEmpty( + elementSource.getEmbeddableSource().getParentReferenceAttributeName() + ); + final SingularAttribute parentAttribute = parentReferenceAttributeName == null + ? null + : aggregate.createSingularAttribute( parentReferenceAttributeName ); + + Class tuplizerClass = null; + final String tuplizerClassName = elementSource.getEmbeddableSource().getExplicitTuplizerClassName(); + if ( StringHelper.isNotEmpty( tuplizerClassName ) ) { + tuplizerClass = localBindingContext().getBuildingOptions() + .getServiceRegistry() + .getService( ClassLoaderService.class ) + .classForName( tuplizerClassName ); + } + + final EmbeddableBinding embeddableBinding = elementBinding.createBindingContainer( + aggregate, + createMetaAttributeContext( + pluralAttributeBinding.getContainer(), + elementSource.getToolingHintSources() + ), + parentAttribute, + tuplizerClass + ); + + bindAttributes( embeddableBinding, elementSource.getEmbeddableSource() ); + + pluralAttributeBinding.getAttribute().setElementType( aggregate ); + Type resolvedType = rootBindingContext.getMetadataCollector().getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( rootBindingContext.getServiceRegistry(), embeddableBinding, false, false ) + ); + // TODO: binding the HibernateTypeDescriptor should be simplified since we know the class name already + typeHelper().bindHibernateTypeDescriptor( + elementBinding.getHibernateTypeDescriptor(), + aggregate.getDescriptor().getName().toString(), + null, + reflectedElementTypeDescriptor == null ? null : reflectedElementTypeDescriptor, + resolvedType + ); + /** + * TODO + * don't know why, but see org.hibernate.mapping.Property#getCompositeCascadeStyle + * + * and not sure if this is the right place to apply this logic, apparently source level is not okay, so here it is, for now. + */ + for ( AttributeBinding ab : embeddableBinding.attributeBindings() ) { + if ( ab.isCascadeable() ) { + final Cascadeable cascadeable; + if ( ab.getAttribute().isSingular() ) { + cascadeable = Cascadeable.class.cast( ab ); + } + else { + cascadeable = Cascadeable.class.cast( ( (PluralAttributeBinding) ab ).getPluralAttributeElementBinding() ); + } + CascadeStyle cascadeStyle = cascadeable.getCascadeStyle(); + if ( cascadeStyle != CascadeStyles.NONE ) { + elementBinding.setCascadeStyle( CascadeStyles.ALL ); + } + } + } + if ( elementBinding.getCascadeStyle() == null || elementBinding.getCascadeStyle() == CascadeStyles.NONE ) { + elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) ); + } + } + + private void bindListIndex( + IndexedPluralAttributeBinding attributeBinding, + PluralAttributeSequentialIndexSource indexSource, + JavaTypeDescriptor reflectedIndexTypeDescriptor) { + final BasicPluralAttributeIndexBinding indexBinding = + (BasicPluralAttributeIndexBinding) attributeBinding.getPluralAttributeIndexBinding(); + // TODO: need to resolve default column names. + indexBinding.setRelationalValueBindings( + relationalValueBindingHelper().createRelationalValueBindings( + attributeBinding.getContainer(), + indexSource, + attributeBinding.getPluralAttributeKeyBinding().getCollectionTable(), + indexSource.getDefaultNamingStrategies(), + true + ) + ); + + typeHelper().bindHibernateTypeDescriptor( + indexBinding.getHibernateTypeDescriptor(), + indexSource.getTypeInformation(), + Primitives.INTEGER.getPrimitiveType() + ); + typeHelper().bindJdbcDataType( + indexBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + indexBinding.getRelationalValueBindings() + ); + + IndexedPluralAttribute indexedPluralAttribute = + (IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute(); + + // todo : we need to centralize this stuff somewhere... + final HibernateTypeDescriptor hibernateTypeDescriptor = indexBinding.getHibernateTypeDescriptor(); + final BasicType basicType; + if ( hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) { + basicType = (BasicType) localBindingContext().makeDomainType( + hibernateTypeDescriptor.getJavaTypeDescriptor().getName() + ); + } + else if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { + basicType = (BasicType) localBindingContext().makeDomainType( + hibernateTypeDescriptor.getResolvedTypeMapping().getName() + ); + } + else if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) { + basicType = (BasicType) localBindingContext().makeDomainType( + hibernateTypeDescriptor.getExplicitTypeName() + ); + } + else { + basicType = new BasicType( hibernateTypeDescriptor.getJavaTypeDescriptor() ); + } + + indexedPluralAttribute.setIndexType( basicType ); + } + + private void bindEntityAttributePluralAttributeIndex( + final IndexedPluralAttributeBinding attributeBinding, + final PluralAttributeMapKeySourceEntityAttribute indexSource, + final JavaTypeDescriptor defaultIndexTypeDescriptor) { + throw new NotYetImplementedException( "Plural attribute index that is an attribute of the referenced entity is not supported yet." ); + } + + private void bindBasicCollectionIndex( + final IndexedPluralAttributeBinding attributeBinding, + final PluralAttributeMapKeySourceBasic indexSource, + final JavaTypeDescriptor defaultIndexTypeDescriptor) { + final BasicPluralAttributeIndexBinding indexBinding = + (BasicPluralAttributeIndexBinding) attributeBinding.getPluralAttributeIndexBinding(); + // TODO: need to resolve default column names. + indexBinding.setRelationalValueBindings( + relationalValueBindingHelper().createRelationalValueBindings( + attributeBinding.getContainer(), + indexSource, + attributeBinding.getPluralAttributeKeyBinding().getCollectionTable(), + indexSource.getDefaultNamingStrategies(), + attributeBinding.getPluralAttributeElementBinding() + .getNature() != PluralAttributeElementNature.ONE_TO_MANY + ) + ); + // TODO: create a foreign key if non-inverse and the index is an association + + typeHelper().bindHibernateTypeDescriptor( + indexBinding.getHibernateTypeDescriptor(), + indexSource.getTypeInformation(), + defaultIndexTypeDescriptor + ); + typeHelper().bindJdbcDataType( + indexBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + indexBinding.getRelationalValueBindings() + ); + IndexedPluralAttribute indexedPluralAttribute = + (IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute(); + + // todo : we need to centralize this stuff somewhere... + final HibernateTypeDescriptor hibernateTypeDescriptor = indexBinding.getHibernateTypeDescriptor(); + final BasicType basicType; + if ( hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) { + basicType = (BasicType) localBindingContext().makeDomainType( + hibernateTypeDescriptor.getJavaTypeDescriptor().getName() + ); + } + else if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { + basicType = (BasicType) localBindingContext().makeDomainType( + hibernateTypeDescriptor.getResolvedTypeMapping().getName() + ); + } + else if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) { + basicType = (BasicType) localBindingContext().makeDomainType( + hibernateTypeDescriptor.getExplicitTypeName() + ); + } + else { + basicType = new BasicType( hibernateTypeDescriptor.getJavaTypeDescriptor() ); + } + + indexedPluralAttribute.setIndexType( basicType ); + } + + private void bindCompositeCollectionIndex( + final CompositePluralAttributeIndexBinding indexBinding, + final IndexedPluralAttributeSource indexedPluralAttributeSource, + final JavaTypeDescriptor reflectedIndexTypeDescriptor) { + final PluralAttributeMapKeySourceEmbedded indexSource = + (PluralAttributeMapKeySourceEmbedded) indexedPluralAttributeSource.getIndexSource(); + final JavaTypeDescriptor indexTypeDescriptor; + if ( indexSource.getEmbeddableSource().getTypeDescriptor() != null ) { + indexTypeDescriptor = indexSource.getEmbeddableSource().getTypeDescriptor(); + } + else { + indexTypeDescriptor = reflectedIndexTypeDescriptor; + } + + final Aggregate aggregate = findOrBuildAggregate( indexTypeDescriptor ); + + final EmbeddableBinding embeddableBinding = indexBinding.createCompositeAttributeBindingContainer( + aggregate, + null, + null, + null + ); + + bindAttributes( embeddableBinding, indexSource.getEmbeddableSource() ); + + Type resolvedType = rootBindingContext.getMetadataCollector().getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( + rootBindingContext.getServiceRegistry(), + embeddableBinding, + false, + false + ) + ); + // TODO: binding the HibernateTypeDescriptor should be simplified since we know the class name already + typeHelper().bindHibernateTypeDescriptor( + indexBinding.getHibernateTypeDescriptor(), + aggregate.getDescriptor().getName().toString(), + null, + indexTypeDescriptor == null ? null : indexTypeDescriptor, + resolvedType + ); + IndexedPluralAttribute indexedPluralAttribute = + (IndexedPluralAttribute) indexBinding.getIndexedPluralAttributeBinding().getAttribute(); + indexedPluralAttribute.setIndexType( aggregate ); + } + + private void bindOneToManyCollectionElement( + final PluralAttributeElementBindingOneToMany elementBinding, + final PluralAttributeElementSourceOneToMany elementSource, + final EntityBinding referencedEntityBinding, + final JavaTypeDescriptor defaultElementTypeDescriptor) { + elementBinding.setElementEntityIdentifier( + referencedEntityBinding.getKeyRelationalValueBindings() + ); + + Type resolvedElementType = rootBindingContext.getMetadataCollector().getTypeResolver().getTypeFactory().manyToOne( + referencedEntityBinding.getEntityName(), + true, + null, + false, + false, + elementSource.isIgnoreNotFound(), + false + ); + final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor(); + final JavaTypeDescriptor elementTypeDescriptor; + if ( defaultElementTypeDescriptor != null ) { + elementTypeDescriptor = defaultElementTypeDescriptor; + } + else { + elementTypeDescriptor = referencedEntityBinding.getEntity().getDescriptor(); + } + typeHelper().bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + referencedEntityBinding.getEntityName(), + null, + elementTypeDescriptor, + resolvedElementType + ); + // no need to bind JDBC data types because element is referenced EntityBinding's ID + elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) ); + elementBinding.getPluralAttributeBinding().getAttribute().setElementType( referencedEntityBinding.getEntity() ); + } + + private void bindManyToManyCollectionElement( + final PluralAttributeElementBindingManyToMany elementBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final EntityBinding referencedEntityBinding, + final JavaTypeDescriptor defaultElementTypeDescriptor) { + final TableSpecification collectionTable = + elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(); + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( + elementSource.getAttributeSource() + ); + final List relationalValueBindings = + resolver.resolveManyToManyElementRelationalValueBindings( + elementBinding.getPluralAttributeBinding().getContainer().seekEntityBinding(), + elementSource, + collectionTable, + referencedEntityBinding + ); + final ForeignKey foreignKey; + if ( !elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().isInverse() && + !relationalValueBindingHelper().hasDerivedValue( relationalValueBindings ) ) { + foreignKey = resolver.resolveManyToManyElementForeignKey( + elementBinding.getPluralAttributeBinding().getContainer().seekEntityBinding(), + elementSource, + collectionTable, + relationalValueBindings, + referencedEntityBinding + ); + } + else { + foreignKey = null; + } + if ( elementSource.isUnique() ) { + final List columns = new ArrayList(); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( ! relationalValueBinding.isDerived() ) { + columns.add( (Column) relationalValueBinding.getValue() ); + } + } + tableHelper().createUniqueKey( collectionTable, columns, null ); + } + elementBinding.setJoinRelationalValueBindings( relationalValueBindings, foreignKey ); + typeHelper().bindManyToManyAttributeType( + elementBinding, + elementSource, + referencedEntityBinding, + defaultElementTypeDescriptor + ); + elementBinding.getPluralAttributeBinding().getAttribute().setElementType( referencedEntityBinding.getEntity() ); + elementBinding.setCascadeStyle( determineCascadeStyle( elementSource.getCascadeStyles() ) ); + elementBinding.setManyToManyWhere( elementSource.getWhere() ); + elementBinding.setManyToManyOrderBy( elementSource.getOrder() ); + elementBinding.setFetchMode( elementSource.getFetchTiming() == FetchTiming.IMMEDIATE ? FetchMode.JOIN : FetchMode.SELECT ); + //TODO: initialize filters from elementSource + } + + private void bindOneToManyCollectionKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource, + final EntityBinding referencedEntityBinding) { + if ( attributeSource.getElementSource().getNature() != PluralAttributeElementNature.ONE_TO_MANY ) { + throw new AssertionFailure( + String.format( + "Expected one-to-many attribute binding; instead got {%s}", + attributeSource.getElementSource().getNature() + ) + ); + } + // By definition, a one-to-many can only be on a foreign key, so the + // collection table is the referenced entity binding's primary table. + final TableSpecification collectionTable = referencedEntityBinding.getPrimaryTable(); + final boolean isInverse = attributeSource.isInverse(); + final PluralAttributeKeyBinding keyBinding = attributeBinding.getPluralAttributeKeyBinding(); + keyBinding.setInverse( isInverse ); + bindCollectionTableJoinRelationalValueBindings( attributeBinding, attributeSource, collectionTable ); + } + + private void bindManyToManyCollectionKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource, + final EntityBinding referencedEntityBinding) { + if ( attributeSource.getElementSource().getNature() != PluralAttributeElementNature.MANY_TO_MANY ) { + throw new AssertionFailure( + String.format( + "Expected many-to-many attribute binding; instead got {%s}", + attributeSource.getElementSource().getNature() + ) + ); + } + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + final TableSpecification collectionTable = resolver.resolveManyToManyCollectionTable( + attributeSource, + attributeSource.getAttributePath().getFullPath(), + attributeBinding.getContainer().seekEntityBinding(), + referencedEntityBinding + ); + final PluralAttributeKeyBinding keyBinding = attributeBinding.getPluralAttributeKeyBinding(); + keyBinding.setInverse( attributeSource.isInverse() ); + bindCollectionTableJoinRelationalValueBindings( attributeBinding, attributeSource, collectionTable ); + } + + private void bindPluralAttributeIndex( + final IndexedPluralAttributeSource attributeSource, + final IndexedPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + final JavaTypeDescriptor reflectedIndexTypeDescriptor = typeHelper().reflectedCollectionIndexClassReference( + reflectedCollectionJavaTypes + ); + final PluralAttributeIndexSource indexSource = attributeSource.getIndexSource(); + if ( PluralAttributeMapKeySourceEntityAttribute.class.isInstance( indexSource ) ) { + bindEntityAttributePluralAttributeIndex( + attributeBinding, + (PluralAttributeMapKeySourceEntityAttribute) indexSource, + reflectedIndexTypeDescriptor + ); + } + else { + switch ( attributeSource.getIndexSource().getNature() ) { + case BASIC: { + bindBasicCollectionIndex( + attributeBinding, + (PluralAttributeMapKeySourceBasic) attributeSource.getIndexSource(), + reflectedIndexTypeDescriptor + ); + break; + } + case AGGREGATE: { + bindCompositeCollectionIndex( + (CompositePluralAttributeIndexBinding) attributeBinding.getPluralAttributeIndexBinding(), + attributeSource, + reflectedIndexTypeDescriptor + ); + break; + } + case SEQUENTIAL: { + // easy peasy, we have an array/list index + bindListIndex( + attributeBinding, + (PluralAttributeSequentialIndexSource) attributeSource.getIndexSource(), + reflectedIndexTypeDescriptor + ); + break; + } + default: { + throw new NotYetImplementedException( + String.format( + "%s collection indexes are not supported yet.", + attributeSource.getIndexSource().getNature() + ) + ); + } + } + if ( attributeBinding.getPluralAttributeElementBinding() + .getNature() == PluralAttributeElementNature.ONE_TO_MANY ) { + for ( RelationalValueBinding relationalValueBinding : attributeBinding.getPluralAttributeIndexBinding().getRelationalValueBindings() ) { + if ( Column.class.isInstance( relationalValueBinding.getValue() ) ) { + // TODO: fix this when column nullability is refactored + Column column = (Column) relationalValueBinding.getValue(); + column.setNullable( true ); + } + } + } + } + } + + private void bindPluralAggregateAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + bindNonAssociationCollectionKey( attributeBinding, attributeSource ); + bindCompositeCollectionElement( + (PluralAttributeElementBindingEmbedded) attributeBinding.getPluralAttributeElementBinding(), + (PluralAttributeElementSourceEmbedded) attributeSource.getElementSource(), + typeHelper().reflectedCollectionElementJavaType( reflectedCollectionJavaTypes ) + ); + } + + private void bindManyToManyAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + final PluralAttributeElementSourceManyToMany elementSource = + (PluralAttributeElementSourceManyToMany) attributeSource.getElementSource(); + final JavaTypeDescriptor reflectedElementTypeDescriptor = typeHelper().reflectedCollectionElementJavaType( + reflectedCollectionJavaTypes + ); + if ( elementSource.getReferencedEntityName() == null && reflectedElementTypeDescriptor == null ) { + throw localBindingContext().makeMappingException( + String.format( + "The mapping for the entity associated with one-to-many attribute (%s) is undefined.", + attributeSource.getAttributeRole().getFullPath() + ) + ); + } + EntityBinding referencedEntityBinding = locateEntityBinding( + reflectedElementTypeDescriptor, + elementSource.getReferencedEntityName() + ); + PluralAttributeElementBindingManyToMany manyToManyPluralAttributeElementBinding = (PluralAttributeElementBindingManyToMany) attributeBinding + .getPluralAttributeElementBinding(); + + if ( elementSource.getFilterSources() != null ) { + for ( FilterSource filterSource : elementSource.getFilterSources() ) { + manyToManyPluralAttributeElementBinding.addFilterConfiguration( + createFilterConfiguration( + filterSource, + null + ) + ); + } + } + bindManyToManyCollectionKey( attributeBinding, attributeSource, referencedEntityBinding ); + bindManyToManyCollectionElement( + manyToManyPluralAttributeElementBinding, + (PluralAttributeElementSourceManyToMany) attributeSource.getElementSource(), + referencedEntityBinding, + reflectedElementTypeDescriptor + ); + } + + private void bindOneToManyAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + final PluralAttributeElementSourceOneToMany elementSource = + (PluralAttributeElementSourceOneToMany) attributeSource.getElementSource(); + final JavaTypeDescriptor defaultElementTypeDescriptor = typeHelper().reflectedCollectionElementJavaType( + reflectedCollectionJavaTypes + ); + if ( elementSource.getReferencedEntityName() == null && defaultElementTypeDescriptor == null ) { + throw localBindingContext().makeMappingException( + String.format( + "The mapping for the entity associated with one-to-many attribute (%s) is undefined.", + attributeSource.getAttributeRole().getFullPath() + ) + ); + } + EntityBinding referencedEntityBinding = locateEntityBinding( + defaultElementTypeDescriptor, + elementSource.getReferencedEntityName() + ); + bindOneToManyCollectionKey( attributeBinding, attributeSource, referencedEntityBinding ); + bindOneToManyCollectionElement( + (PluralAttributeElementBindingOneToMany) attributeBinding.getPluralAttributeElementBinding(), + (PluralAttributeElementSourceOneToMany) attributeSource.getElementSource(), + referencedEntityBinding, + defaultElementTypeDescriptor + ); + } + + private void bindBasicPluralAttribute( + final PluralAttributeSource attributeSource, + final AbstractPluralAttributeBinding attributeBinding, + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + bindNonAssociationCollectionKey( attributeBinding, attributeSource ); + bindBasicCollectionElement( + (PluralAttributeElementBindingBasic) attributeBinding.getPluralAttributeElementBinding(), + (PluralAttributeElementSourceBasic) attributeSource.getElementSource(), + typeHelper().reflectedCollectionElementJavaType( reflectedCollectionJavaTypes ) + ); + } + + + private void bindSortingAndOrdering( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource) { + if ( Sortable.class.isInstance( attributeSource ) ) { + final Sortable sortable = (Sortable) attributeSource; + attributeBinding.setSorted( sortable.isSorted() ); + if ( sortable.isSorted() + && !sortable.getComparatorName().equalsIgnoreCase( "natural" ) ) { + Class> comparatorClass = localBindingContext(). + getClassLoaderAccess() + .classForName( sortable.getComparatorName() ); + try { + attributeBinding.setComparator( comparatorClass.newInstance() ); + } + catch ( Exception error ) { + throw localBindingContext().makeMappingException( + String.format( + "Unable to create comparator [%s] for attribute [%s]", + sortable.getComparatorName(), + attributeSource.getName() + ), + error + ); + } + } + } + if ( Orderable.class.isInstance( attributeSource ) ) { + final Orderable orderable = (Orderable) attributeSource; + if ( orderable.isOrdered() ) { + attributeBinding.setOrderBy( orderable.getOrder() ); + + } + } + } + + private SingularAttributeBinding determinePluralAttributeKeyReferencedBinding( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource) { + return getAssociationRelationalBindingResolver( attributeSource ).resolvePluralAttributeKeyReferencedBinding( + attributeBindingContainer, + attributeSource + ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ relational binding relates methods + private void bindBasicPluralElementRelationalValues( + final RelationalValueSourceContainer relationalValueSourceContainer, + final PluralAttributeElementBindingBasic elementBinding) { + elementBinding.setRelationalValueBindings( + relationalValueBindingHelper().createRelationalValueBindings( + elementBinding.getPluralAttributeBinding().getContainer(), + relationalValueSourceContainer, + elementBinding.getPluralAttributeBinding().getAttribute(), + elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(), + false + ) + ); + } + + private void bindSetCollectionTablePrimaryKey(final SetBinding attributeBinding) { + // only bind the primary key if there is a non-nullable element value. + if ( !attributeBinding.getPluralAttributeElementBinding().getRelationalValueContainer().hasNonNullableRelationalValueBinding() ) { + return; + } + + + final PluralAttributeElementBinding elementBinding = attributeBinding.getPluralAttributeElementBinding(); + final PrimaryKey primaryKey = attributeBinding.getPluralAttributeKeyBinding() + .getCollectionTable() + .getPrimaryKey(); + final List keyValueBindings = + attributeBinding.getPluralAttributeKeyBinding().getRelationalValueBindings(); + for ( final RelationalValueBinding keyRelationalValueBinding : keyValueBindings ) { + primaryKey.addColumn( (Column) keyRelationalValueBinding.getValue() ); + } + for ( final RelationalValueBinding elementValueBinding + : elementBinding.getRelationalValueContainer().relationalValueBindings() ) { + if ( !elementValueBinding.isDerived() && !elementValueBinding.isNullable() ) { + primaryKey.addColumn( (Column) elementValueBinding.getValue() ); + } + } + } + + private void bindCollectionTableJoinRelationalValueBindings( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource, + final TableSpecification collectionTable) { + + final EntityBinding referencedEntityBinding = attributeBinding.getContainer().seekEntityBinding(); + final PluralAttributeKeyBinding keyBinding = attributeBinding.getPluralAttributeKeyBinding(); + final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( attributeSource ); + final List sourceRelationalBindings = + resolver.resolvePluralAttributeKeyRelationalValueBindings( + attributeSource, + attributeBinding.getContainer().seekEntityBinding(), + collectionTable, + referencedEntityBinding + ); + + final ForeignKey foreignKey = resolver.resolvePluralAttributeKeyForeignKey( + attributeSource, + attributeBinding.getContainer().seekEntityBinding(), + collectionTable, + sourceRelationalBindings, + referencedEntityBinding + ); + keyBinding.setJoinRelationalValueBindings( sourceRelationalBindings, foreignKey ); + + final HibernateTypeDescriptor pluralAttributeKeyTypeDescriptor = keyBinding.getHibernateTypeDescriptor(); + + pluralAttributeKeyTypeDescriptor.copyFrom( + keyBinding.getReferencedAttributeBinding() + .getHibernateTypeDescriptor() + ); + final Type resolvedKeyType = pluralAttributeKeyTypeDescriptor.getResolvedTypeMapping(); + typeHelper().bindJdbcDataType( resolvedKeyType, keyBinding.getRelationalValueBindings() ); + } + + /** + * TODO : It is really confusing that we have so many different natures + */ + private void bindCollectionTablePrimaryKey( + final AbstractPluralAttributeBinding attributeBinding, + final PluralAttributeSource attributeSource) { + final PluralAttributeNature pluralAttributeSourceNature = attributeSource.getNature(); + final PluralAttributeElementNature pluralElementSourceNature = attributeSource.getElementSource().getNature(); + + //TODO what is this case? it would be really good to add a comment + if ( pluralElementSourceNature == PluralAttributeElementNature.ONE_TO_MANY + || pluralAttributeSourceNature == PluralAttributeNature.BAG ) { + return; + } + if ( !attributeBinding.getPluralAttributeKeyBinding().isInverse() ) { + switch ( pluralAttributeSourceNature ) { + case SET: + bindSetCollectionTablePrimaryKey( (SetBinding) attributeBinding ); + break; + case LIST: + case MAP: + case ARRAY: + bindIndexedCollectionTablePrimaryKey( (IndexedPluralAttributeBinding) attributeBinding ); + break; + default: + throw new NotYetImplementedException( + String.format( "%s of elements is not supported yet.", pluralAttributeSourceNature ) + ); + } + } + } + + private TableSpecification findConstraintTable(EntityBinding entityBinding, String tableName) { + try { + return entityBinding.locateTable( tableName ); + } + catch ( AssertionFailure e ) { + Identifier identifier = Identifier.toIdentifier( tableName ); + + // TODO: Make TableGenerator & MultipleHiLoPerTableGenerator extend an abstract? + // @TableGenerator + IdentifierGenerator idGenerator = entityBinding.getHierarchyDetails().getEntityIdentifier().getIdentifierGenerator(); + if (idGenerator instanceof TableGenerator) { + Table generatorTable = ((TableGenerator) idGenerator).getTable(); + if (generatorTable != null && generatorTable.getLogicalName().equals( identifier ) ) { + return generatorTable; + } + } + else if (idGenerator instanceof MultipleHiLoPerTableGenerator) { + Table generatorTable = ((MultipleHiLoPerTableGenerator) idGenerator).getTable(); + if (generatorTable != null && generatorTable.getLogicalName().equals( identifier ) ) { + return generatorTable; + } + } + + // @JoinTable and @CollectionTable + for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) { + if ( attributeBinding instanceof PluralAttributeBinding ) { + PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + final TableSpecification pluralTable = + pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable(); + if ( pluralTable != null && pluralTable.getLogicalName().equals( identifier ) ) { + return pluralTable; + } + } + } + } + + throw new AssertionFailure( + String.format( + "Unable to find locate table %s", + tableName + ) + ); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ simple instance helper methods + + private AssociationRelationalBindingResolver getAssociationRelationalBindingResolver(AttributeSource attributeSource) { + if ( ToOneAttributeSource.class.isInstance( attributeSource ) && + ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) { + return mappedByAssociationRelationalBindingResolver; + } + else if ( PluralAttributeSource.class.isInstance( attributeSource ) && + PluralAttributeSource.class.cast( attributeSource ).getMappedBy() != null ) { + return mappedByAssociationRelationalBindingResolver; + } + else { + return standardAssociationRelationalBindingResolver; + + } + } + + + private String propertyAccessorName(final AttributeSource attributeSource) { + return propertyAccessorName( attributeSource.getPropertyAccessorName() ); + } + + private String propertyAccessorName(final String propertyAccessorName) { + return propertyAccessorName == null + ? localBindingContext().getMappingDefaults().getPropertyAccessorName() + : propertyAccessorName; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static methods + private static TableSpecification locateDefaultTableSpecificationForAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return attributeSource.getContainingTableName() == null ? + attributeBindingContainer.getPrimaryTable() : + attributeBindingContainer.seekEntityBinding().locateTable( attributeSource.getContainingTableName() ); + } + + private static PluralAttributeElementNature pluralAttributeElementNature( + final PluralAttributeSource attributeSource) { + return attributeSource.getElementSource().getNature(); + } + + private static PluralAttributeIndexNature pluralAttributeIndexNature( + final PluralAttributeSource attributeSource) { + if ( !IndexedPluralAttributeSource.class.isInstance( attributeSource ) ) { + return null; + } + return PluralAttributeIndexNature.valueOf( + ( (IndexedPluralAttributeSource) attributeSource ).getIndexSource().getNature().name() + ); + } + + private void bindIndexedCollectionTablePrimaryKey( + final IndexedPluralAttributeBinding attributeBinding) { + final TableSpecification collectionTable = attributeBinding.getPluralAttributeKeyBinding().getCollectionTable(); + final PrimaryKey primaryKey = collectionTable.getPrimaryKey(); + + final List keyRelationalValueBindings = + attributeBinding.getPluralAttributeKeyBinding().getRelationalValueBindings(); + + final PluralAttributeIndexBinding indexBinding = attributeBinding.getPluralAttributeIndexBinding(); + + // Don't add any columns to the primary key unless there is a non-nullable index or element column. + if ( relationalValueBindingHelper().hasDerivedValue( indexBinding.getRelationalValueBindings() ) ) { + // the index has as formula; + // only create the primary key if there are non-nullable element columns + final PluralAttributeElementBinding pluralAttributeElementBinding = attributeBinding.getPluralAttributeElementBinding(); + if ( pluralAttributeElementBinding.getRelationalValueContainer().hasNonNullableRelationalValueBinding() ) { + for ( final RelationalValueBinding keyRelationalValueBinding : keyRelationalValueBindings ) { + primaryKey.addColumn( (Column) keyRelationalValueBinding.getValue() ); + } + for ( RelationalValueBinding relationalValueBinding + : pluralAttributeElementBinding.getRelationalValueContainer().relationalValueBindings() ) { + if ( !relationalValueBinding.isDerived() && + !relationalValueBinding.isNullable() && + relationalValueBinding.getTable().equals( collectionTable ) ){ + primaryKey.addColumn( (Column)relationalValueBinding.getValue() ); + } + } + } + } + else { + for ( final RelationalValueBinding keyRelationalValueBinding : keyRelationalValueBindings ) { + primaryKey.addColumn( (Column) keyRelationalValueBinding.getValue() ); + } + for ( RelationalValueBinding relationalValueBinding : indexBinding.getRelationalValueBindings() ) { + if ( relationalValueBinding.getTable().equals( collectionTable ) && + !relationalValueBinding.isNullable() ) { + primaryKey.addColumn( (Column) relationalValueBinding.getValue() ); + } + } + } + } + + // TODO: should this be moved to CascadeStyles as a static method? + // TODO: sources already factor in default cascade; should that be done here instead? + private static CascadeStyle determineCascadeStyle( + final Iterable cascadeStyles) { + CascadeStyle cascadeStyleResult; + List cascadeStyleList = new ArrayList(); + for ( CascadeStyle style : cascadeStyles ) { + if ( style != CascadeStyles.NONE ) { + cascadeStyleList.add( style ); + } + } + if ( cascadeStyleList.isEmpty() ) { + cascadeStyleResult = CascadeStyles.NONE; + } + else if ( cascadeStyleList.size() == 1 ) { + cascadeStyleResult = cascadeStyleList.get( 0 ); + } + else { + cascadeStyleResult = new CascadeStyles.MultipleCascadeStyle( + cascadeStyleList.toArray( new CascadeStyle[cascadeStyleList.size()] ) + ); + } + return cascadeStyleResult; + } + + private static MetaAttributeContext createMetaAttributeContext( + final AttributeBindingContainer attributeBindingContainer, + final AttributeSource attributeSource) { + return createMetaAttributeContext( attributeBindingContainer, attributeSource.getToolingHintSources() ); + } + + private static MetaAttributeContext createMetaAttributeContext( + final AttributeBindingContainer attributeBindingContainer, + final Iterable metaAttributeSources) { + return createMetaAttributeContext( + metaAttributeSources, + false, + attributeBindingContainer.getMetaAttributeContext() + ); + } + + private static MetaAttributeContext createMetaAttributeContext( + final Iterable metaAttributeSources, + final boolean onlyInheritable, + final MetaAttributeContext parentContext) { + final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); + for ( final ToolingHintSource toolingHintSource : metaAttributeSources ) { + if ( onlyInheritable && !toolingHintSource.isInheritable() ) { + continue; + } + final String name = toolingHintSource.getName(); + MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); + if ( metaAttribute == null || metaAttribute == parentContext.getMetaAttribute( name ) ) { + metaAttribute = new MetaAttribute( name ); + subContext.add( metaAttribute ); + } + metaAttribute.addValue( toolingHintSource.getValue() ); + } + return subContext; + } + + private static SingularAttribute createSingularAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return attributeSource.isVirtualAttribute() ? + attributeBindingContainer.getAttributeContainer().createSyntheticSingularAttribute( + attributeSource.getName() + ) : + attributeBindingContainer.getAttributeContainer().createSingularAttribute( attributeSource.getName() ); + } + + public static interface DefaultNamingStrategy { + String defaultName(NamingStrategy namingStrategy); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContext.java new file mode 100644 index 000000000000..e58b10150c60 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContext.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; + +/** + * The processes performed by Binder are done as a series of steps, where each + * step performs a iteration on an entity hierarchy and visits the hierarchy and + * its entities. + *

    + * This contract representations access to "context information" relating to the + * visitation and is presented to the visitation strategies. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public interface BinderLocalBindingContext extends BinderRootContext, LocalBindingContext { + /** + * Locate the binding representation of the hierarchy for the given source + * representation. + * + * @param source The source representation + * + * @return The binding representation + */ + public HierarchyDetails locateBinding(EntityHierarchySource source); + + /** + * Locate the binding representation of the entity for the given source + * representation. + * + * @param source The source representation + * + * @return The binding representation + */ + public EntityBinding locateBinding(EntitySource source); + + HibernateTypeHelper typeHelper(); + RelationalIdentifierHelper relationalIdentifierHelper(); + TableHelper tableHelper(); + ForeignKeyHelper foreignKeyHelper(); + RelationalValueBindingHelper relationalValueBindingHelper(); + NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContextSelector.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContextSelector.java new file mode 100644 index 000000000000..8aa7cb4993d0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContextSelector.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +/** + * @author Steve Ebersole + */ +public interface BinderLocalBindingContextSelector { + BinderLocalBindingContext getCurrentBinderLocalBindingContext(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContextSelectorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContextSelectorImpl.java new file mode 100644 index 000000000000..9b129a5366dd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderLocalBindingContextSelectorImpl.java @@ -0,0 +1,175 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.MappingDefaults; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.BaseDelegatingBindingContext; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; +import org.hibernate.xml.spi.Origin; + +/** + * @author Gail Badner + * @author Steve Ebersole + */ +public class BinderLocalBindingContextSelectorImpl implements BinderLocalBindingContextSelector { + private final BinderRootContext rootContext; + private BinderLocalBindingContextImpl current; + + public BinderLocalBindingContextSelectorImpl(BinderRootContext rootContext) { + this.rootContext = rootContext; + } + + @Override + public BinderLocalBindingContext getCurrentBinderLocalBindingContext() { + if ( current == null ) { + throw new AssertionFailure( "No BinderLocalBindingContextImpl currently set" ); + } + return current; + } + + public BinderLocalBindingContext setCurrent(EntitySource entitySource) { + current = new BinderLocalBindingContextImpl( rootContext, entitySource ); + return current; + } + + public void unsetCurrent() { + current = null; + } + + private static class BinderLocalBindingContextImpl + extends BaseDelegatingBindingContext + implements BinderLocalBindingContext { + + private final EntitySource source; + + private BinderLocalBindingContextImpl(BinderRootContext parent, EntitySource source) { + super( parent ); + this.source = source; + } + + @Override + protected BinderRootContext parent() { + return (BinderRootContext) super.parent(); + } + + @Override + public HierarchyDetails locateBinding(EntityHierarchySource source) { + return parent().locateBinding( source ); + } + + @Override + public EntityBinding locateBinding(EntitySource source) { + return parent().locateBinding( source ); + } + + @Override + public BinderLocalBindingContextSelector getLocalBindingContextSelector() { + return parent().getLocalBindingContextSelector(); + } + + @Override + public HibernateTypeHelper typeHelper() { + return parent().typeHelper(); + } + + @Override + public RelationalIdentifierHelper relationalIdentifierHelper() { + return parent().relationalIdentifierHelper(); + } + + @Override + public TableHelper tableHelper() { + return parent().tableHelper(); + } + + @Override + public ForeignKeyHelper foreignKeyHelper() { + return parent().foreignKeyHelper(); + } + + @Override + public RelationalValueBindingHelper relationalValueBindingHelper() { + return parent().relationalValueBindingHelper(); + } + + @Override + public NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper() { + return parent().naturalIdUniqueKeyHelper(); + } + + @Override + public boolean quoteIdentifiersInContext() { + // NOTE : for now source.quoteIdentifiersLocalToEntity() only ever returns + // TRUE/UNKNOWN. The logic here accounts for possible future + // allowance of selectively disabling global-identifier-quoting. + switch ( source.quoteIdentifiersLocalToEntity() ) { + case TRUE: { + return true; + } + case FALSE: { + return false; + } + default: { + return super.quoteIdentifiersInContext(); + } + } + } + + @Override + public String qualifyClassName(String name) { + return source.getLocalBindingContext().qualifyClassName( name ); + } + + @Override + public JavaTypeDescriptor typeDescriptor(String name) { + return source.getLocalBindingContext().typeDescriptor( name ); + } + + @Override + public MappingDefaults getMappingDefaults() { + return source.getLocalBindingContext().getMappingDefaults(); + } + + @Override + public Origin getOrigin() { + return source.getLocalBindingContext().getOrigin(); + } + + @Override + public MappingException makeMappingException(String message) { + return source.getLocalBindingContext().makeMappingException( message ); + } + + @Override + public MappingException makeMappingException(String message, Exception cause) { + return source.getLocalBindingContext().makeMappingException( message, cause ); + } + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderProcessHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderProcessHelper.java new file mode 100644 index 000000000000..b3b9a1b0fe89 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderProcessHelper.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.Collection; + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +/** + * The processes performed by Binder are done as a series of steps, where each + * step performs a iteration on an entity hierarchy and visits the hierarchy and + * its entities. + *

    + * This class is the visitation process. In many ways its a simple iterator over the + * EntitySource structure skipping MapperSuperclassSource types. + * + * @author Steve Ebersole + */ +public class BinderProcessHelper { + private final BinderRootContext context; + + public static final BinderStepHierarchyStrategy NOOP_HIERARCHY_STRATEGY = new BinderStepHierarchyStrategy() { + @Override + public void visit(EntityHierarchySource source, BinderLocalBindingContext context) { + + } + }; + + public static final BinderStepEntityStrategy NOOP_ENTITY_STRATEGY = new BinderStepEntityStrategy() { + @Override + public boolean applyToRootEntity() { + return false; + } + + @Override + public void visit(EntitySource source, BinderLocalBindingContext context) { + + } + }; + + public BinderProcessHelper(BinderRootContext context) { + this.context = context; + } + + public void apply( + Collection hierarchySources, + BinderStepHierarchyStrategy hierarchyStrategy) { + for ( EntityHierarchySource hierarchySource : hierarchySources ) { + apply( hierarchySource, hierarchyStrategy ); + } + } + + public void apply(EntityHierarchySource hierarchySource, BinderStepHierarchyStrategy hierarchyStrategy) { + apply( hierarchySource, hierarchyStrategy, NOOP_ENTITY_STRATEGY ); + } + + public void apply( + Collection hierarchySources, + BinderStepCombinedStrategy strategy) { + for ( EntityHierarchySource hierarchySource : hierarchySources ) { + apply( hierarchySource, strategy ); + } + } + + public void apply(EntityHierarchySource hierarchySource, BinderStepCombinedStrategy strategy) { + apply( hierarchySource, strategy, strategy ); + } + + public void apply( + Collection hierarchySources, + BinderStepEntityStrategy entityStrategy) { + for ( EntityHierarchySource hierarchySource: hierarchySources ) { + apply( hierarchySource, entityStrategy ); + } + } + + public void apply(EntityHierarchySource hierarchySource, BinderStepEntityStrategy strategy) { + apply( hierarchySource, NOOP_HIERARCHY_STRATEGY, strategy ); + } + + public void apply( + Collection hierarchySources, + BinderStepHierarchyStrategy hierarchyStrategy, + BinderStepEntityStrategy entityStrategy) { + for ( EntityHierarchySource hierarchySource: hierarchySources ) { + apply( hierarchySource, hierarchyStrategy, entityStrategy ); + } + } + + public void apply( + EntityHierarchySource hierarchySource, + BinderStepHierarchyStrategy hierarchyStrategy, + BinderStepEntityStrategy entityStrategy) { + final BinderLocalBindingContextSelectorImpl selector + = (BinderLocalBindingContextSelectorImpl) context.getLocalBindingContextSelector(); + + BinderLocalBindingContext localContext = selector.setCurrent( hierarchySource.getRoot() ); + hierarchyStrategy.visit( hierarchySource, localContext ); + + final EntitySource rootEntitySource = hierarchySource.getRoot(); + if ( entityStrategy.applyToRootEntity() ) { + entityStrategy.visit( rootEntitySource, localContext ); + } + + if ( hierarchySource.getHierarchyInheritanceType() != InheritanceType.NO_INHERITANCE ) { + visitSubclasses( rootEntitySource, entityStrategy, localContext ); + } + } + + private void visitSubclasses( + IdentifiableTypeSource source, + BinderStepEntityStrategy entityStrategy, + BinderLocalBindingContext localContext) { + for ( IdentifiableTypeSource subType : source.getSubTypes() ) { + if ( EntitySource.class.isInstance( subType ) ) { + entityStrategy.visit( (EntitySource) subType, localContext ); + } + visitSubclasses( subType, entityStrategy, localContext ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderRootContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderRootContext.java new file mode 100644 index 000000000000..338fe0947f93 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderRootContext.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; + +/** + * @author Steve Ebersole + */ +public interface BinderRootContext extends BindingContext { + /** + * Locate the binding representation of the hierarchy for the given source + * representation. + * + * @param source The source representation + * + * @return The binding representation + */ + public HierarchyDetails locateBinding(EntityHierarchySource source); + + /** + * Locate the binding representation of the entity for the given source + * representation. + * + * @param source The source representation + * + * @return The binding representation + */ + public EntityBinding locateBinding(EntitySource source); + + public BinderLocalBindingContextSelector getLocalBindingContextSelector(); + + HibernateTypeHelper typeHelper(); + RelationalIdentifierHelper relationalIdentifierHelper(); + TableHelper tableHelper(); + ForeignKeyHelper foreignKeyHelper(); + RelationalValueBindingHelper relationalValueBindingHelper(); + NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderRootContextImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderRootContextImpl.java new file mode 100644 index 000000000000..800e37122f85 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderRootContextImpl.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.spi.BaseDelegatingBindingContext; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; + +/** + * @author Steve Ebersole + */ +public class BinderRootContextImpl extends BaseDelegatingBindingContext implements BinderRootContext { + private Map hierarchySourceToBindingMap + = new HashMap(); + private Map entitySourceToBindingMap + = new HashMap(); + + private final HibernateTypeHelper typeHelper; // todo: refactor helper and remove redundant methods in this class + private final RelationalIdentifierHelper relationalIdentifierHelper; + private final TableHelper tableHelper; + private final ForeignKeyHelper foreignKeyHelper; + private final RelationalValueBindingHelper relationalValueBindingHelper; + private final NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper; + + private final BinderLocalBindingContextSelector localBindingContextSelector; + + public BinderRootContextImpl(BindingContext parent) { + super( parent ); + + this.typeHelper = new HibernateTypeHelper( this ); + this.relationalIdentifierHelper = new RelationalIdentifierHelper( this ); + this.tableHelper = new TableHelper( this ); + this.foreignKeyHelper = new ForeignKeyHelper( this ); + this.relationalValueBindingHelper = new RelationalValueBindingHelper( this ); + this.naturalIdUniqueKeyHelper = new NaturalIdUniqueKeyHelper( this ); + this.localBindingContextSelector = new BinderLocalBindingContextSelectorImpl( this ); + } + + public void addMapping(EntityHierarchySource source, HierarchyDetails binding) { + hierarchySourceToBindingMap.put( source, binding ); + } + + public void addMapping(EntitySource source, EntityBinding binding) { + entitySourceToBindingMap.put( source, binding ); + } + + @Override + public HierarchyDetails locateBinding(EntityHierarchySource source) { + // todo : add missing checks + return hierarchySourceToBindingMap.get( source ); + } + + @Override + public EntityBinding locateBinding(EntitySource source) { + // todo : add missing checks + return entitySourceToBindingMap.get( source ); + } + + @Override + public BinderLocalBindingContextSelector getLocalBindingContextSelector() { + return localBindingContextSelector; + } + + @Override + public HibernateTypeHelper typeHelper() { + return typeHelper; + } + + @Override + public RelationalIdentifierHelper relationalIdentifierHelper() { + return relationalIdentifierHelper; + } + + @Override + public TableHelper tableHelper() { + return tableHelper; + } + + @Override + public ForeignKeyHelper foreignKeyHelper() { + return foreignKeyHelper; + } + + @Override + public RelationalValueBindingHelper relationalValueBindingHelper() { + return relationalValueBindingHelper; + } + + @Override + public NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper() { + return naturalIdUniqueKeyHelper; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepCombinedStrategy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepCombinedStrategy.java new file mode 100644 index 000000000000..b6440c265d5a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepCombinedStrategy.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +/** + * @author Steve Ebersole + */ +public interface BinderStepCombinedStrategy extends BinderStepHierarchyStrategy, BinderStepEntityStrategy { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepEntityStrategy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepEntityStrategy.java new file mode 100644 index 000000000000..bb5fad5b66d9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepEntityStrategy.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.metamodel.source.spi.EntitySource; + +/** + * The work performed by Binder is done as a series of steps, where each + * step performs a iteration on an entity hierarchy and visits the hierarchy and + * its entities. + *

    + * This contract defines the visitation of entity objects. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public interface BinderStepEntityStrategy { + public boolean applyToRootEntity(); + + public void visit(EntitySource source, BinderLocalBindingContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepHierarchyStrategy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepHierarchyStrategy.java new file mode 100644 index 000000000000..7fd0f1c1fd5d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/BinderStepHierarchyStrategy.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; + +/** + * The processes performed by Binder are done as a series of steps, where each + * step performs a iteration on an entity hierarchy and visits the hierarchy and + * its entities. + *

    + * This contract defines the visitation of the hierarchy object + * + * @author Steve Ebersole + * @author Gail Badner + */ +public interface BinderStepHierarchyStrategy { + public void visit(EntityHierarchySource source, BinderLocalBindingContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/CollectionTableNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/CollectionTableNamingStrategyHelper.java new file mode 100644 index 000000000000..40e99f0481ee --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/CollectionTableNamingStrategyHelper.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.relational.Table; + +/** + * @author Strong Liu + */ +public class CollectionTableNamingStrategyHelper extends TableNamingStrategyHelper { + private final String propertyName; + + public CollectionTableNamingStrategyHelper(final AbstractPluralAttributeBinding pluralAttributeBinding) { + super( pluralAttributeBinding.getContainer().seekEntityBinding() ); + this.propertyName = pluralAttributeBinding.getAttribute().getName(); + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return strategy.collectionTableName( + entityBinding.getEntityName(), + strategy.classToTableName( entityBinding.getEntityName() ), + null, + null, + propertyName + + ); + } + + @Override + public String getLogicalName(NamingStrategy strategy) { + return strategy.logicalCollectionTableName( + logicalName, + strategy.classToTableName( entityBinding.getEntityName() ), + null, + propertyName + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ColumnNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ColumnNamingStrategyHelper.java new file mode 100644 index 000000000000..042ff037066a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ColumnNamingStrategyHelper.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; + +/** + * @author Strong Liu + */ +public class ColumnNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + private final String defaultName; + private final boolean isDefaultAttributeName; + + public ColumnNamingStrategyHelper( + final String defaultName, + final boolean isDefaultAttributeName) { + this.defaultName = defaultName; + this.isDefaultAttributeName = isDefaultAttributeName; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + if ( isDefaultAttributeName ) { + return strategy.propertyToColumnName( defaultName ); + } + else { + return strategy.columnName( defaultName ); + } + } + + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return strategy.columnName( name ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ConstraintNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ConstraintNamingStrategyHelper.java new file mode 100644 index 000000000000..c46e1479669c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ConstraintNamingStrategyHelper.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Brett Meyer + */ +public abstract class ConstraintNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + + protected final TableSpecification table; + + protected final List columns; + + public ConstraintNamingStrategyHelper(TableSpecification table, List columns) { + this.table = table; + this.columns = columns; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return doDetermineImplicitName( strategy, table.getLogicalName().getText(), getColumnNames( columns ) ); + } + + protected abstract String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames); + + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return name; + } + + public static class UniqueKeyNamingStrategyHelper extends ConstraintNamingStrategyHelper { + public UniqueKeyNamingStrategyHelper(TableSpecification table, List columns) { + super( table, columns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + return strategy.uniqueKeyName( tableName, columnNames ); + } + } + + public static class ForeignKeyNamingStrategyHelper extends ConstraintNamingStrategyHelper { + // named using a combo of source/target table/columns + private final String targetTableName; + private final List targetColumnNames; + + public ForeignKeyNamingStrategyHelper(TableSpecification sourceTable, List sourceColumns, + TableSpecification targetTable, List targetColumns) { + super( sourceTable, sourceColumns ); + targetTableName = targetTable.getLogicalName().getText(); + targetColumnNames = getColumnNames( targetColumns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + // combine source and target (if available) to ensure uniqueness + return strategy.foreignKeyName( tableName, columnNames, targetTableName, targetColumnNames ); + } + } + + public static class IndexNamingStrategyHelper extends ConstraintNamingStrategyHelper { + public IndexNamingStrategyHelper(TableSpecification table, List columns) { + super( table, columns ); + } + + @Override + protected String doDetermineImplicitName(NamingStrategy strategy, String tableName, List columnNames) { + return strategy.indexName( tableName, columnNames ); + } + } + + private static List getColumnNames(List columns) { + final List columnNames = new ArrayList(); + for ( final Column column : columns ) { + columnNames.add( column.getColumnName().getText() ); + } + return columnNames; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/DefaultColumnNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/DefaultColumnNamingStrategyHelper.java new file mode 100644 index 000000000000..4e7b14eb7c49 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/DefaultColumnNamingStrategyHelper.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; + +/** + * @author Gail Badner + */ +public class DefaultColumnNamingStrategyHelper implements ObjectNameNormalizer.NamingStrategyHelper { + private final Binder.DefaultNamingStrategy defaultNameStrategy; + + public DefaultColumnNamingStrategyHelper(Binder.DefaultNamingStrategy defaultNameStrategy) { + this.defaultNameStrategy = defaultNameStrategy; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return defaultNameStrategy.defaultName( strategy ); + } + + @Override + public String handleExplicitName(NamingStrategy strategy, String name) { + return strategy.columnName( name ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ForeignKeyDelegate.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ForeignKeyDelegate.java new file mode 100644 index 000000000000..7188b873f5a6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ForeignKeyDelegate.java @@ -0,0 +1,98 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.Map; + +import javax.persistence.ConstraintMode; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Brett Meyer + */ +public class ForeignKeyDelegate { + + private String explicitForeignKeyName = null; + + private String inverseForeignKeyName = null; + + private boolean createForeignKeyConstraint = true; + + // TODO: do we need inverseCreateForeignKeyConstraint? + + public ForeignKeyDelegate() { + } + + public ForeignKeyDelegate(Map annotations, ClassLoaderService cls) { + final AnnotationInstance joinColumnAnnotation = annotations.get( JPADotNames.JOIN_COLUMN ); + final AnnotationInstance joinTable = annotations.get( JPADotNames.JOIN_TABLE ); + final AnnotationInstance collectionTable = annotations.get( JPADotNames.COLLECTION_TABLE ); + + if ( joinColumnAnnotation != null ) { + resolveExplicitName( joinColumnAnnotation, cls ); + resolveCreateForeignKeyConstraint( joinColumnAnnotation, cls ); + } + if ( joinTable != null ) { + resolveExplicitName( joinTable, cls ); + resolveInverseName( joinTable, cls ); + resolveCreateForeignKeyConstraint( joinTable, cls ); + } + if ( collectionTable != null ) { + resolveExplicitName( collectionTable, cls ); + resolveCreateForeignKeyConstraint( collectionTable, cls ); + } + } + + private void resolveExplicitName(AnnotationInstance owningAnnotation, ClassLoaderService cls) { + AnnotationInstance jpaFkAnnotation = JandexHelper.getValue( owningAnnotation, "foreignKey", AnnotationInstance.class, cls ); + explicitForeignKeyName = jpaFkAnnotation != null ? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null; + } + + private void resolveInverseName(AnnotationInstance owningAnnotation, ClassLoaderService cls) { + AnnotationInstance jpaFkAnnotation = JandexHelper.getValue( owningAnnotation, "inverseForeignKey", AnnotationInstance.class, cls ); + inverseForeignKeyName = jpaFkAnnotation != null ? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null; + } + + private void resolveCreateForeignKeyConstraint(AnnotationInstance owningAnnotation, ClassLoaderService cls) { + AnnotationInstance jpaFkAnnotation = JandexHelper.getValue( owningAnnotation, "foreignKey", AnnotationInstance.class, cls ); + if ( jpaFkAnnotation != null ) { + ConstraintMode mode = JandexHelper.getEnumValue( jpaFkAnnotation, "value", ConstraintMode.class, cls ); + createForeignKeyConstraint = !mode.equals( ConstraintMode.NO_CONSTRAINT ); + } + } + + public String getExplicitForeignKeyName() { + return explicitForeignKeyName; + } + + public String getInverseForeignKeyName() { + return inverseForeignKeyName; + } + + public boolean createForeignKeyConstraint() { + return createForeignKeyConstraint; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ForeignKeyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ForeignKeyHelper.java new file mode 100644 index 000000000000..f8e693096818 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ForeignKeyHelper.java @@ -0,0 +1,344 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.ForeignKeyNamingStrategyHelper; +import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Gail Badner + * @author Brett Meyer + */ +public class ForeignKeyHelper { + private final BinderRootContext helperContext; + + public ForeignKeyHelper(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + public List determineForeignKeyTargetColumns( + final EntityBinding entityBinding, + final ForeignKeyContributingSource foreignKeyContributingSource) { + + // TODO: This method, JoinColumnResolutionContext, + // and JoinColumnResolutionDelegate need re-worked. There is currently + // no way to bind to a collection's inverse foreign key. + + final ForeignKeyContributingSource.JoinColumnResolutionDelegate fkColumnResolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + + if ( fkColumnResolutionDelegate == null ) { + return entityBinding.getPrimaryTable().getPrimaryKey().getColumns(); + } + else { + final List columns = new ArrayList(); + final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = new JoinColumnResolutionContextImpl( entityBinding ); + for ( Value relationalValue : fkColumnResolutionDelegate.getJoinColumns( resolutionContext ) ) { + if ( !Column.class.isInstance( relationalValue ) ) { + throw bindingContext().makeMappingException( + "Foreign keys can currently only name columns, not formulas" + ); + } + columns.add( (Column) relationalValue ); + } + return columns; + } + } + + public TableSpecification determineForeignKeyTargetTable( + final EntityBinding entityBinding, + final ForeignKeyContributingSource foreignKeyContributingSource) { + + final ForeignKeyContributingSource.JoinColumnResolutionDelegate fkColumnResolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + if ( fkColumnResolutionDelegate == null ) { + return entityBinding.getPrimaryTable(); + } + else { + final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = new JoinColumnResolutionContextImpl( entityBinding ); + return fkColumnResolutionDelegate.getReferencedTable( resolutionContext ); + } + } + + public SingularAttributeBinding determineReferencedAttributeBinding( + final ForeignKeyContributingSource foreignKeyContributingSource, + final EntityBinding referencedEntityBinding) { + final ForeignKeyContributingSource.JoinColumnResolutionDelegate resolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = resolutionDelegate == null ? null : new JoinColumnResolutionContextImpl( + referencedEntityBinding + ); + if ( resolutionDelegate == null ) { + return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + } + + final String explicitName = resolutionDelegate.getReferencedAttributeName(); + final AttributeBinding referencedAttributeBinding; + if ( explicitName != null ) { + referencedAttributeBinding = referencedEntityBinding.locateAttributeBindingByPath( explicitName, true ); + } + else { + referencedAttributeBinding = referencedEntityBinding.locateAttributeBinding( + resolutionDelegate.getReferencedTable( resolutionContext ), + resolutionDelegate.getJoinColumns( resolutionContext ), + true + ); + } + + if ( referencedAttributeBinding == null ) { + if ( explicitName != null ) { + throw bindingContext().makeMappingException( + String.format( + "No attribute binding found with name: %s.%s", + referencedEntityBinding.getEntityName(), + explicitName + ) + ); + } + else { + throw new NotYetImplementedException( + "No support yet for referenced join columns unless they correspond with columns bound for an attribute binding." + ); + } + } + + if ( !referencedAttributeBinding.getAttribute().isSingular() ) { + throw bindingContext().makeMappingException( + String.format( + "Foreign key references a non-singular attribute [%s]", + referencedAttributeBinding.getAttribute().getName() + ) + ); + } + return (SingularAttributeBinding) referencedAttributeBinding; + } + + public ForeignKey locateOrCreateForeignKey( + String explicitForeignKeyName, + final TableSpecification sourceTable, + final List sourceColumns, + final TableSpecification targetTable, + final List targetColumns, + boolean isCascadeDeleteEnabled, + boolean createConstraint) { + final String foreignKeyName = helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( + explicitForeignKeyName, new ForeignKeyNamingStrategyHelper( + sourceTable, sourceColumns, targetTable, targetColumns ) ); + + ForeignKey foreignKey = locateAndBindForeignKeyByName( foreignKeyName, sourceTable, sourceColumns, targetTable, targetColumns ); + if ( foreignKey == null ) { + // no foreign key found; create one + foreignKey = sourceTable.createForeignKey( targetTable, foreignKeyName, createConstraint ); + bindForeignKeyColumns( foreignKey, sourceTable, sourceColumns, targetTable, targetColumns ); + } + if ( isCascadeDeleteEnabled ) { + foreignKey.setDeleteRule( ForeignKey.ReferentialAction.CASCADE ); + } + return foreignKey; + } + + private void bindForeignKeyColumns( + final ForeignKey foreignKey, + final TableSpecification sourceTable, + final List sourceColumns, + final TableSpecification targetTable, + final List targetColumns) { + if ( sourceColumns.size() != targetColumns.size() ) { + throw bindingContext().makeMappingException( + String.format( + "Non-matching number columns in foreign key source columns [%s : %s] and target columns [%s : %s]", + sourceTable.getLogicalName().getText(), + sourceColumns.size(), + targetTable.getLogicalName().getText(), + targetColumns.size() + ) + ); + } + for ( int i = 0; i < sourceColumns.size(); i++ ) { + foreignKey.addColumnMapping( sourceColumns.get( i ), targetColumns.get( i ) ); + } + } + + private ForeignKey locateAndBindForeignKeyByName( + final String foreignKeyName, + final TableSpecification sourceTable, + final List sourceColumns, + final TableSpecification targetTable, + final List targetColumns) { + if ( foreignKeyName == null ) { + throw new AssertionFailure( "foreignKeyName must be non-null." ); + } + ForeignKey foreignKey = sourceTable.locateForeignKey( foreignKeyName ); + if ( foreignKey != null ) { + if ( !targetTable.equals( foreignKey.getTargetTable() ) ) { + throw bindingContext().makeMappingException( + String.format( + "Unexpected target table defined for foreign key \"%s\"; expected \"%s\"; found \"%s\"", + foreignKeyName, + targetTable.getLogicalName(), + foreignKey.getTargetTable().getLogicalName() + ) + ); + } + // check if source and target columns have been bound already + if ( foreignKey.getColumnSpan() == 0 ) { + // foreign key was found, but no columns bound to it yet + bindForeignKeyColumns( foreignKey, sourceTable, sourceColumns, targetTable, targetColumns ); + } + else { + // The located foreign key already has columns bound; + // Make sure they are the same columns. + if ( !foreignKey.getSourceColumns().equals( sourceColumns ) || + !foreignKey.getTargetColumns().equals( targetColumns ) ) { + throw bindingContext().makeMappingException( + String.format( + "Attempt to bind exisitng foreign key \"%s\" with different columns.", + foreignKeyName + ) + ); + } + } + } + return foreignKey; + } + + private BinderLocalBindingContext bindingContext() { + return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext(); + } + + private class JoinColumnResolutionContextImpl implements ForeignKeyContributingSource.JoinColumnResolutionContext { + private final EntityBinding referencedEntityBinding; + + + public JoinColumnResolutionContextImpl(EntityBinding referencedEntityBinding) { + this.referencedEntityBinding = referencedEntityBinding; + } + + @Override + public Column resolveColumn( + String logicalColumnName, + String logicalTableName, + String logicalSchemaName, + String logicalCatalogName) { + if ( bindingContext().quoteIdentifiersInContext() && !org.hibernate + .internal + .util + .StringHelper + .isQuoted( logicalColumnName ) ) { + logicalColumnName = org.hibernate.internal.util.StringHelper.quote( logicalColumnName ); + } + return resolveTable( logicalTableName, logicalSchemaName, logicalCatalogName ).locateOrCreateColumn( + logicalColumnName + ); + } + + @Override + public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName) { + Identifier tableIdentifier = helperContext.relationalIdentifierHelper().createIdentifier( logicalTableName ); + if ( tableIdentifier == null ) { + tableIdentifier = referencedEntityBinding.getPrimaryTable().getLogicalName(); + } + + + Identifier catalogName = org.hibernate.internal.util.StringHelper.isNotEmpty( logicalCatalogName ) ? + Identifier.toIdentifier( logicalCatalogName ) + : referencedEntityBinding.getPrimaryTable().getSchema().getName().getCatalog(); + Identifier schemaName = org.hibernate.internal.util.StringHelper.isNotEmpty( logicalCatalogName ) ? + Identifier.toIdentifier( logicalSchemaName ) + : referencedEntityBinding.getPrimaryTable().getSchema().getName().getSchema(); + Schema schema = bindingContext().getMetadataCollector().getDatabase().getSchema( catalogName, schemaName ); + return schema.locateTable( tableIdentifier ); + } + + @Override + public List resolveRelationalValuesForAttribute(String attributeName) { + if ( attributeName == null ) { + List values = new ArrayList(); + for ( Column column : referencedEntityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { + values.add( column ); + } + return values; + } + List valueBindings = + resolveReferencedAttributeBinding( attributeName ).getRelationalValueBindings(); + List values = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding valueBinding : valueBindings ) { + values.add( valueBinding.getValue() ); + } + return values; + } + + @Override + public TableSpecification resolveTableForAttribute(String attributeName) { + if ( attributeName == null ) { + return referencedEntityBinding.getPrimaryTable(); + } + else { + return resolveReferencedAttributeBinding( attributeName ).getRelationalValueBindings().get( 0 ).getTable(); + } + } + + private SingularAttributeBinding resolveReferencedAttributeBinding(String attributeName) { + if ( attributeName == null ) { + return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + } + final AttributeBinding referencedAttributeBinding = + referencedEntityBinding.locateAttributeBindingByPath( attributeName, true ); + if ( referencedAttributeBinding == null ) { + throw bindingContext().makeMappingException( + String.format( + "Could not resolve named referenced property [%s] against entity [%s]", + attributeName, + referencedEntityBinding.getEntityName() + ) + ); + } + if ( !referencedAttributeBinding.getAttribute().isSingular() ) { + throw bindingContext().makeMappingException( + String.format( + "Referenced property [%s] against entity [%s] is a plural attribute; it must be a singular attribute.", + attributeName, + referencedEntityBinding.getEntityName() + ) + ); + } + return (SingularAttributeBinding) referencedAttributeBinding; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/HashedNameUtil.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/HashedNameUtil.java new file mode 100644 index 000000000000..3acfbf1c6644 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/HashedNameUtil.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.binder; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.HibernateException; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Brett Meyer + */ +public class HashedNameUtil { + + /** + * If a constraint is not explicitly named, this is called to generate + * a unique hash using the table and column names. + * Static so the name can be generated prior to creating the Constraint. + * They're cached, keyed by name, in multiple locations. + * + * @param prefix + * @param tableName + * @param columnNames + * @return String The generated name + */ + public static String generateName(String prefix, String tableName, String... columnNames ) { + // Use a concatenation that guarantees uniqueness, even if identical names + // exist between all table and column identifiers. + + StringBuilder sb = new StringBuilder( "table`" + tableName + "`" ); + + // Ensure a consistent ordering of columns, regardless of the order + // they were bound. + // Clone the list, as sometimes a set of order-dependent Column + // bindings are given. + String[] alphabeticalColumns = columnNames.clone(); + Arrays.sort( alphabeticalColumns ); + for ( String columnName : alphabeticalColumns ) { + sb.append( "column`" + columnName + "`" ); + } + return prefix + hashedName( sb.toString() ); + } + + /** + * Helper method for {@link #generateName} + * + * @param prefix + * @param tableName + * @param columnNames + * + * @return String The generated name + */ + public static String generateName(String prefix, String tableName, List columnNames) { + String[] columnNamesArray = new String[columnNames.size()]; + for ( int i = 0; i < columnNames.size(); i++ ) { + columnNamesArray[i] = columnNames.get( i ); + } + return generateName( prefix, tableName, columnNamesArray ); + } + + /** + * Hash a constraint name using MD5. Convert the MD5 digest to base 35 + * (full alphanumeric), guaranteeing + * that the length of the name will always be smaller than the 30 + * character identifier restriction enforced by a few dialects. + * + * @param s The name to be hashed. + * @return String The hased name. + */ + public static String hashedName(String s) { + try { + MessageDigest md = MessageDigest.getInstance( "MD5" ); + md.reset(); + md.update( s.getBytes() ); + byte[] digest = md.digest(); + BigInteger bigInt = new BigInteger( 1, digest ); + // By converting to base 35 (full alphanumeric), we guarantee + // that the length of the name will always be smaller than the 30 + // character identifier restriction enforced by a few dialects. + return bigInt.toString( 35 ); + } + catch ( NoSuchAlgorithmException e ) { + throw new HibernateException( "Unable to generate a hashed name!", e ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/HibernateTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/HibernateTypeHelper.java new file mode 100644 index 000000000000..4afae81cc643 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/HibernateTypeHelper.java @@ -0,0 +1,1048 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.beans.BeanInfo; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.util.beans.BeanInfoHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.reflite.spi.PrimitiveTypeDescriptor; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceBasic; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingBasic; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingManyToMany; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.AbstractValue; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tuple.component.ComponentMetamodel; +import org.hibernate.type.CompositeType; +import org.hibernate.type.EntityType; +import org.hibernate.type.Type; +import org.hibernate.type.TypeFactory; + +import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; + +/** + * Delegate for handling:

      + *
    1. + * binding of Hibernate type information ({@link org.hibernate.metamodel.source.spi.HibernateTypeSource} -> + * {@link HibernateTypeDescriptor} + *
    2. + *
    3. + * attempt to resolve the actual {@link Type} instance + *
    4. + *
    5. + * push java type and JDBC type information reported by the {@link Type} instance to relational/ + * domain models. + *
    6. + *
    + *

    + * Methods intended as entry points are:

      + *
    • {@link #bindSingularAttributeType}
    • + *
    + *

    + * Currently the following methods are also required to be non-private because of handling discriminators which + * are currently not modeled using attributes:

      + *
    • {@link #bindJdbcDataType(org.hibernate.type.Type, org.hibernate.metamodel.spi.relational.Value)}
    • + *
    + * + * @author Steve Ebersole + * @author Gail Badner + * @author Brett Meyer + */ +class HibernateTypeHelper { + private static final Logger log = Logger.getLogger( HibernateTypeHelper.class ); + + /** + * package-protected + *

    + * Model a plural attribute's type info, including : + *

      + *
    • collection type, like {@code list}, {@code set} etc
    • + *
    • elements' type, which belongs in this collection
    • + *
    • collection index type
    • + *
    + */ + public static class ReflectedCollectionJavaTypes { + /** + * Singleton access + */ + public static final ReflectedCollectionJavaTypes NONE = new ReflectedCollectionJavaTypes(); + + private final String collectionTypeName; + private final String collectionElementTypeName; + private final String collectionIndexTypeName; + + public ReflectedCollectionJavaTypes() { + this( null, null, null ); + } + + private ReflectedCollectionJavaTypes( + Class collectionType, + Class collectionElementType, + Class collectionIndexType) { + this.collectionTypeName = collectionType != null ? collectionType.getName() : null; + this.collectionElementTypeName = collectionElementType != null ? collectionElementType.getName() : null; + this.collectionIndexTypeName = collectionIndexType != null ? collectionIndexType.getName() : null; + } + + String getCollectionElementTypeName() { + return collectionElementTypeName; + } + + String getCollectionIndexTypeName() { + return collectionIndexTypeName; + } + + String getCollectionTypeName() { + return collectionTypeName; + } + } + + JavaTypeDescriptor reflectedCollectionElementJavaType( + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + if ( reflectedCollectionJavaTypes != null && + reflectedCollectionJavaTypes.getCollectionElementTypeName() != null ) { + return bindingContext().typeDescriptor( + reflectedCollectionJavaTypes.getCollectionElementTypeName() + ); + } + else { + return null; + } + } + + JavaTypeDescriptor reflectedCollectionIndexClassReference( + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + if ( reflectedCollectionJavaTypes != null && reflectedCollectionJavaTypes.getCollectionIndexTypeName() != null ) { + return bindingContext().typeDescriptor( reflectedCollectionJavaTypes.getCollectionIndexTypeName() ); + } + else { + return null; + } + } + + JavaTypeDescriptor reflectedCollectionClassReference( + final ReflectedCollectionJavaTypes reflectedCollectionJavaTypes) { + if( reflectedCollectionJavaTypes != null && reflectedCollectionJavaTypes.getCollectionTypeName() != null ) { + return bindingContext().typeDescriptor( reflectedCollectionJavaTypes.getCollectionTypeName() ); + } + else { + return null; + } + } + + static ReflectedCollectionJavaTypes getReflectedCollectionJavaTypes( + ClassLoaderService classLoaderService, + final PluralAttributeBinding attributeBinding) { + return determineReflectedCollectionJavaTypes( classLoaderService, attributeBinding.getAttribute() ); + } + + //-------------------------------------------------------------------------------- + + /** + * Bind type info into {@link HibernateTypeDescriptor}. The strategy below applied: + *

    + *

      + *
    • if {@param resolvedType} is not null, then we can get resolvedTypeMapping, javaTypeName, toOne from it.
    • + *
    • Or, we have to use provided {@param explicitTypeName} / {@param defaultJavaTypeName} to resolve hibernate type
    • + *
    + * + * @param hibernateTypeDescriptor + * The target {@link HibernateTypeDescriptor} to be bind. Can not be null. + * + * @param explicitTypeName + * + * Explicit type name defined in the mapping or resolved from referenced attribute. + * null is accepted. + * + * @param explicitTypeParameters + * + * Explicit type parameters defined in the mapping or resolved from refrenced attribute type. + * null is accepted. + * + * @param defaultTypeDescriptor + * + * Attribute java type. null is accepted. + * + * @param resolvedType + * + * Provided hibernate type. null is accepted. + */ + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final String explicitTypeName, + final Map explicitTypeParameters, + final JavaTypeDescriptor defaultTypeDescriptor, + final Type resolvedType) { + Type type; + if ( resolvedType != null ) { + type = resolvedType; + } + else { + //1. pre processing, resolve either explicitType or javaType + preProcessHibernateTypeDescriptor( + hibernateTypeDescriptor, + explicitTypeName, + explicitTypeParameters, + defaultTypeDescriptor + ); + //2. resolve hibernate type + type = getHeuristicType( + determineTypeName( hibernateTypeDescriptor ), + getTypeParameters( hibernateTypeDescriptor ) + ); + } + if ( type == null ) { + //todo how to deal with this? + } + + //3. now set hibernateTypeDescriptor ResolvedTypeMapping and defaultJavaType (if not yet) + hibernateTypeDescriptor.setResolvedTypeMapping( type ); + + if ( hibernateTypeDescriptor.getJavaTypeDescriptor() == null ) { + if ( defaultTypeDescriptor != null ) { + hibernateTypeDescriptor.setJavaTypeDescriptor( defaultTypeDescriptor ); + } + else if ( type != null && ! type.isAssociationType() ) { + hibernateTypeDescriptor.setJavaTypeDescriptor( + bindingContext().typeDescriptor( + type.getReturnedClass() + .getName() + ) + ); + } + } + } + + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final String explicitTypeName, + final Map explictTypeParameters, + final JavaTypeDescriptor defaultTypeDescriptor) { + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + explicitTypeName, + explictTypeParameters, + defaultTypeDescriptor, + null + ); + } + + + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final HibernateTypeSource explicitTypeSource, + final JavaTypeDescriptor defaultTypeDescriptor){ + bindHibernateTypeDescriptor( hibernateTypeDescriptor, explicitTypeSource, defaultTypeDescriptor, null); + } + + void bindHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final HibernateTypeSource explicitTypeSource, + final JavaTypeDescriptor defaultTypeDescriptor, + final Type resolvedType) { + final String explicitTypeName = explicitTypeSource != null ? explicitTypeSource.getName() : null; + final Map parameters = explicitTypeSource != null ? explicitTypeSource.getParameters() : null; + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + explicitTypeName, + parameters, + defaultTypeDescriptor, + resolvedType + ); + } + //-------------------------------------------------------------------------------- + + private final BinderRootContext helperContext; + + //package scope methods + HibernateTypeHelper(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + /** + * Bind relational types using hibernate type just resolved. + * + * @param resolvedHibernateType The hibernate type resolved from metadata. + * @param value The relational value to be binded. + */ + void bindJdbcDataType( + final Type resolvedHibernateType, + final Value value) { + if ( value != null && value.getJdbcDataType() == null && resolvedHibernateType != null ) { + final Type resolvedRelationalType = + resolvedHibernateType.isEntityType() + ? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadataCollector() ) + : resolvedHibernateType; + if ( AbstractValue.class.isInstance( value ) ) { + ( (AbstractValue) value ).setJdbcDataType( + new JdbcDataType( + resolvedRelationalType.sqlTypes( metadataCollector() )[0], + resolvedRelationalType.getName(), + resolvedRelationalType.getReturnedClass() + ) + ); + } + } + } + + void bindJdbcDataType( + final Type resolvedHibernateType, + final List relationalValueBindings) { + if ( resolvedHibernateType == null ) { + throw new IllegalArgumentException( "resolvedHibernateType must be non-null." ); + } + if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) { + throw new IllegalArgumentException( "relationalValueBindings must be non-null." ); + } + if ( relationalValueBindings.size() == 1 ) { + bindJdbcDataType( resolvedHibernateType, relationalValueBindings.get( 0 ).getValue() ); + } + else { + final Type resolvedRelationalType = + resolvedHibernateType.isEntityType() + ? EntityType.class.cast( resolvedHibernateType ).getIdentifierOrUniqueKeyType( metadataCollector() ) + : resolvedHibernateType; + if ( !CompositeType.class.isInstance( resolvedRelationalType ) ) { + throw bindingContext() + .makeMappingException( "Column number mismatch" ); // todo refine the exception message + } + Type[] subTypes = CompositeType.class.cast( resolvedRelationalType ).getSubtypes(); + for ( int i = 0; i < subTypes.length; i++ ) { + bindJdbcDataType( subTypes[i], relationalValueBindings.get( i ).getValue() ); + } + } + } + + void bindAggregatedCompositeAttributeType( + final ServiceRegistry serviceRegistry, + final boolean isAttributeIdentifier, + final Aggregate composite, + final JavaTypeDescriptor defaultTypeDescriptor, + final EmbeddedAttributeBinding attributeBinding) { + Type resolvedType = typeFactory().component( + new ComponentMetamodel( + serviceRegistry, + attributeBinding.getEmbeddableBinding(), + isAttributeIdentifier, + false + ) + ); + bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + composite.getDescriptor().getName().toString(), + null, + defaultTypeDescriptor, + resolvedType + ); + } + + void bindBasicCollectionElementType( + final PluralAttributeElementBindingBasic elementBinding, + final PluralAttributeElementSourceBasic elementSource, + final JavaTypeDescriptor defaultElementTypeDescriptor) { + bindHibernateTypeDescriptor( + elementBinding.getHibernateTypeDescriptor(), + elementSource.getExplicitHibernateTypeSource(), + defaultElementTypeDescriptor + ); + bindJdbcDataType( + elementBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(), + elementBinding.getRelationalValueBindings() + ); + } + void bindNonAggregatedCompositeIdentifierType( + final ServiceRegistry serviceRegistry, + final EmbeddedAttributeBinding syntheticAttributeBinding, + final SingularAttribute syntheticAttribute) { + final Type resolvedType = typeFactory().embeddedComponent( + new ComponentMetamodel( serviceRegistry, syntheticAttributeBinding.getEmbeddableBinding(), true, false ) + ); + final HibernateTypeDescriptor typeDescriptor = syntheticAttributeBinding.getHibernateTypeDescriptor(); + final String className = syntheticAttribute.getSingularAttributeType().getDescriptor() == null ? + null : + syntheticAttribute.getSingularAttributeType().getDescriptor().getName().toString(); + bindHibernateTypeDescriptor( + typeDescriptor, + className, + null, + null, + resolvedType + ); + } + void bindManyToManyAttributeType( + final PluralAttributeElementBindingManyToMany elementBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final EntityBinding referencedEntityBinding, + final JavaTypeDescriptor defaultElementTypeDescriptor) { + final Type resolvedElementType = typeFactory().manyToOne( + referencedEntityBinding.getEntityName(), + elementSource.getReferencedEntityAttributeName(), + false, + false, + elementSource.isIgnoreNotFound(), + false + ); + final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor(); + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + referencedEntityBinding.getEntityName(), + null, + defaultElementTypeDescriptor, + resolvedElementType + ); + bindJdbcDataType( + resolvedElementType, + elementBinding.getRelationalValueContainer().relationalValueBindings() + ); + } + + void bindDiscriminatorType(EntityDiscriminator discriminator, Value value) { + bindHibernateTypeDescriptor( + discriminator.getExplicitHibernateTypeDescriptor(), + null, + null, + bindingContext().typeDescriptor( String.class.getName() ) + ); + bindJdbcDataType( discriminator.getExplicitHibernateTypeDescriptor().getResolvedTypeMapping(), value ); + } + + void bindSingularAttributeType( + final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding + .getHibernateTypeDescriptor(); + final JavaTypeDescriptor attributeTypeDescriptor = determineJavaType( + attributeSource, + attributeBinding.getAttribute().getAttributeContainer() + ); + //try to resolve this attribute's java type first + final JavaTypeDescriptor defaultTypeDescriptor; + if ( attributeTypeDescriptor != null ) { + attributeBinding.getAttribute().resolveType( + makeDomainType( attributeTypeDescriptor.getName().toString() ) + ); + defaultTypeDescriptor = attributeTypeDescriptor; + } + else { + defaultTypeDescriptor = null; + } + //do our best to full fill hibernateTypeDescriptor + bindHibernateTypeDescriptor( + hibernateTypeDescriptor, + attributeSource.getTypeInformation(), + defaultTypeDescriptor + ); + + processSingularAttributeTypeInformation( + attributeSource, + attributeBinding + ); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hibernate type resolver + Type resolvePluralType( + ClassLoaderService classLoaderService, + final PluralAttributeBinding pluralAttributeBinding, + final PluralAttributeSource pluralAttributeSource, + final PluralAttributeNature nature) { + if ( pluralAttributeBinding.getHibernateTypeDescriptor().getExplicitTypeName() != null ) { + return resolveCustomCollectionType( pluralAttributeBinding ); + } + else { + final String role = pluralAttributeBinding.getAttribute().getRole(); + final String propertyRef = getReferencedPropertyNameIfNotId( pluralAttributeBinding ); + switch ( nature ) { + case BAG: { + return typeFactory().bag( role, propertyRef ); + } + case LIST: { + return typeFactory().list( role, propertyRef ); + } + case ARRAY: { + // TODO: Move into a util? + final JavaTypeDescriptor descriptor = pluralAttributeSource.getElementTypeDescriptor(); + final Class clazz; + if (PrimitiveTypeDescriptor.class.isInstance( descriptor )) { + clazz = ( (PrimitiveTypeDescriptor) descriptor ).getClassType(); + } + else { + clazz = classLoaderService.classForName( descriptor.getName().toString() ); + } + return typeFactory().array( + role, + propertyRef, + clazz + ); + } + case MAP: { + if ( pluralAttributeBinding.isSorted() ) { + return typeFactory().sortedMap( + role, + propertyRef, + pluralAttributeBinding.getComparator() + ); + } + // TODO: else if ( pluralAttributeBinding.hasOrder() ) { orderedMap... } + else { + return typeFactory().map( role, propertyRef ); + } + } + case SET: { + if ( pluralAttributeBinding.isSorted() ) { + return typeFactory().sortedSet( + role, + propertyRef, + pluralAttributeBinding.getComparator() + ); + } + else if ( pluralAttributeBinding.getOrderBy() != null ) { + return typeFactory().orderedSet( role, propertyRef ); + } + else if ( pluralAttributeBinding.getPluralAttributeElementBinding().getNature() == PluralAttributeElementNature.MANY_TO_MANY && + ( (PluralAttributeElementBindingManyToMany) pluralAttributeBinding.getPluralAttributeElementBinding() ).getManyToManyOrderBy() != null ) { + return typeFactory().orderedSet( role, propertyRef ); + } + else { + return typeFactory().set( role, propertyRef ); + } + } + default: { + throw new NotYetImplementedException( nature + " is to be implemented" ); + } + } + } + } + + private TypeFactory typeFactory(){ + return metadataCollector().getTypeResolver().getTypeFactory(); + } + + private Type determineHibernateTypeFromAttributeJavaType( + final SingularAttribute singularAttribute) { + if ( singularAttribute.getSingularAttributeType() != null ) { + return getHeuristicType( + singularAttribute.getSingularAttributeType().getDescriptor().getName().toString(), + null + ); + } + return null; + } + private Type resolveCustomCollectionType( + final PluralAttributeBinding pluralAttributeBinding) { + final HibernateTypeDescriptor hibernateTypeDescriptor = pluralAttributeBinding.getHibernateTypeDescriptor(); + Properties typeParameters = getTypeParameters( hibernateTypeDescriptor ); + return typeFactory().customCollection( + hibernateTypeDescriptor.getExplicitTypeName(), + typeParameters, + pluralAttributeBinding.getAttribute().getName(), + getReferencedPropertyNameIfNotId( pluralAttributeBinding ) + ); + } + /** + * Resolve hibernate type with info from {@link HibernateTypeDescriptor} using {@link org.hibernate.type.TypeResolver}. + *

    + * return null if can't resolve. + */ + private Type getHeuristicType( + final String typeName, + final Properties typeParameters) { + if ( typeName != null ) { + try { + return metadataCollector().getTypeResolver().heuristicType( typeName, typeParameters ); + } + catch ( Exception ignore ) { + } + } + + return null; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private scope methods + + /** + * Given an attribute, process all of its type information. This includes resolving the actual + * {@link Type} instance and pushing JDBC/java information from that type down. + * + * @param attributeSource The attribute source. + * @param attributeBinding The attribute. + */ + private void processSingularAttributeTypeInformation( + final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding) { + Type resolvedType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + + if ( resolvedType == null ) { + // we can determine the Hibernate Type if either: + // 1) the user explicitly named a Type in a HibernateTypeDescriptor + // 2) we know the java type of the attribute + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + resolvedType = getHeuristicType( + determineTypeName( hibernateTypeDescriptor ), + getTypeParameters( hibernateTypeDescriptor ) + ); + if ( resolvedType == null ) { + resolvedType = determineHibernateTypeFromAttributeJavaType( attributeBinding.getAttribute() ); + } + } + + if ( resolvedType != null ) { + pushHibernateTypeInformationDown( attributeSource, attributeBinding, resolvedType ); + } + + //todo throw exception?? + } + + private void preProcessHibernateTypeDescriptor( + final HibernateTypeDescriptor hibernateTypeDescriptor, + final String explicitTypeName, + final Map explictTypeParameters, + final JavaTypeDescriptor defaultTypeDescriptor) { + if ( explicitTypeName == null ) { + if ( defaultTypeDescriptor != null ) { + if ( hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) { + throw bindingContext().makeMappingException( + String.format( + "Attempt to re-initialize (non-explicit) Java type name; current=%s new=%s", + hibernateTypeDescriptor.getJavaTypeDescriptor(), + defaultTypeDescriptor + ) + ); + } + hibernateTypeDescriptor.setJavaTypeDescriptor( defaultTypeDescriptor ); + } + } + else { + // Check if user-specified name is of a User-Defined Type (UDT) + final TypeDefinition typeDef = metadataCollector().getTypeDefinition( explicitTypeName ); + if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) { + throw bindingContext().makeMappingException( + String.format( + "Attempt to re-initialize explicitly-mapped Java type name; current=%s new=%s", + hibernateTypeDescriptor.getExplicitTypeName(), + explicitTypeName + ) + ); + } + if ( typeDef == null ) { + hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName ); + } + else { + hibernateTypeDescriptor.setExplicitTypeName( typeDef.getTypeImplementorClass().getName() ); + // Don't use set() -- typeDef#parameters is unmodifiable + hibernateTypeDescriptor.getTypeParameters().putAll( typeDef.getParameters() ); + } + if ( explictTypeParameters != null ) { + hibernateTypeDescriptor.getTypeParameters().putAll( explictTypeParameters ); + } + } + } + + private void pushHibernateTypeInformationDown( + final SingularAttributeSource attributeSource, + final SingularAttributeBinding attributeBinding, + final Type resolvedHibernateType) { + if ( resolvedHibernateType == null ) { + throw bindingContext().makeMappingException( "Resolved hibernate type can't be null" ); + } + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) { + hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType ); + } + if ( hibernateTypeDescriptor.getJavaTypeDescriptor() == null ) { + // try to get Java type name from attribute because it may not be available from + // resolvedHibernateType until after persisters are available. + if ( attributeBinding.getAttribute().isTypeResolved() ) { + hibernateTypeDescriptor.setJavaTypeDescriptor( + attributeBinding.getAttribute().getSingularAttributeType().getDescriptor() + ); + } + else { + hibernateTypeDescriptor.setJavaTypeDescriptor( + bindingContext().typeDescriptor( + resolvedHibernateType.getReturnedClass().getName() + ) + ); + } + } + + // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) { + pushHibernateTypeInformationDown( + (BasicAttributeBinding) attributeBinding, + resolvedHibernateType + ); + } + else if ( EmbeddedAttributeBinding.class.isInstance( attributeBinding ) ) { + pushHibernateTypeInformationDown( + (EmbeddedAttributeSource) attributeSource, + (EmbeddedAttributeBinding) attributeBinding, + resolvedHibernateType + ); + } + } + + /** + * Resolve domain type for this attribute and also bind jdbc type. + * + * hibernateTypeDescriptor from this binding must already be set with same resolvedHibernateType. + */ + private void pushHibernateTypeInformationDown( + final BasicAttributeBinding attributeBinding, + final Type resolvedHibernateType) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + final SingularAttribute singularAttribute = attributeBinding.getAttribute(); + if ( !singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) { + singularAttribute.resolveType( makeDomainType( hibernateTypeDescriptor.getJavaTypeDescriptor().getName() ) ); + } + bindJdbcDataType( resolvedHibernateType, attributeBinding.getRelationalValueBindings() ); + } + + @SuppressWarnings({ "UnusedParameters" }) + private void pushHibernateTypeInformationDown( + final EmbeddedAttributeSource attributeSource, + final EmbeddedAttributeBinding attributeBinding, + final Type resolvedHibernateType) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + final SingularAttribute singularAttribute = attributeBinding.getAttribute(); + if ( !singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) { + singularAttribute.resolveType( makeDomainType( hibernateTypeDescriptor.getJavaTypeDescriptor().getName() ) ); + } + + Iterator subAttributeSourceIterator = attributeSource.getEmbeddableSource().attributeSources().iterator(); + for ( AttributeBinding subAttributeBinding : attributeBinding.getEmbeddableBinding().attributeBindings() ) { + AttributeSource subAttributeSource = subAttributeSourceIterator.next(); + if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { + processSingularAttributeTypeInformation( + (SingularAttributeSource) subAttributeSource, + SingularAttributeBinding.class.cast( subAttributeBinding ) + ); + } + else { + throw new AssertionFailure( + "Unknown type of AttributeBinding: " + attributeBinding.getClass() + .getName() + ); + } + } + } + + private BinderLocalBindingContext bindingContext() { + return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext(); + } + + private InFlightMetadataCollector metadataCollector() { + return bindingContext().getMetadataCollector(); + } + + private org.hibernate.metamodel.spi.domain.Type makeDomainType(String name) { + return bindingContext().makeDomainType( name ); + } + + private org.hibernate.metamodel.spi.domain.Type makeDomainType(DotName name) { + return bindingContext().makeDomainType( name ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private static methods + private static String determineTypeName(final HibernateTypeDescriptor hibernateTypeDescriptor) { + if ( hibernateTypeDescriptor.getExplicitTypeName() != null ) { + return hibernateTypeDescriptor.getExplicitTypeName(); + } + if ( hibernateTypeDescriptor.getJavaTypeDescriptor() != null ) { + return hibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString(); + } + return null; + } + + public String determineJavaTypeName(final IdentifiableTypeSource identifiableTypeSource) { + if ( identifiableTypeSource.getTypeName() == null ) { + if ( identifiableTypeSource.getHierarchy().getEntityMode() == EntityMode.MAP ) { + return Map.class.getName(); + + } + else { + return null; + } + } + else { + return identifiableTypeSource.getTypeName(); + } + } + + public JavaTypeDescriptor determineJavaType( + final EmbeddedAttributeSource attributeSource, + final AttributeContainer attributeContainer, + final EntityMode entityMode) { + if ( attributeSource.getEmbeddableSource().getTypeDescriptor() != null ) { + return attributeSource.getEmbeddableSource().getTypeDescriptor(); + } + else if ( entityMode == EntityMode.MAP ) { + return bindingContext().typeDescriptor( Map.class.getName() ); + } + else { + return determineJavaType( attributeSource, attributeContainer ); + } + } + + public JavaTypeDescriptor determineJavaType( + final AttributeSource attributeSource, + final AttributeContainer attributeContainer) { + if ( attributeSource.getTypeInformation() != null && attributeSource.getTypeInformation().getJavaType() != null ) { + return attributeSource.getTypeInformation().getJavaType(); + } + else if ( attributeContainer.getDescriptor() == null ) { + return null; + } + else { + return determineAttributeType( attributeContainer.getDescriptor(), attributeSource.getName() ); + } + } + + public static JavaTypeDescriptor determineAttributeType( + JavaTypeDescriptor containerTypeDescriptor, + String attributeName) { + // todo : this needs to change once we figure out what to do with declared/non-declared attributes + // and generics... + + // check fields... + for ( FieldDescriptor field : containerTypeDescriptor.getDeclaredFields() ) { + if ( field.getName().equals( attributeName ) ) { + return field.getType().getErasedType(); + } + } + + // check methods... + final String attributeNameCapitalized = capitalize( attributeName ); + final String setterName = "set" + attributeNameCapitalized; + final String getterName = "get" + attributeNameCapitalized; + final String isGetterName = "is" + attributeNameCapitalized; + for ( MethodDescriptor method : containerTypeDescriptor.getDeclaredMethods() ) { + // look for a setter... + if ( method.getName().equals( setterName ) ) { + if ( method.getArgumentTypes().size() == 1 ) { + // technically the setters could be overloaded. but we'll assume this was it... + return method.getArgumentTypes().iterator().next(); + } + } + + // look for a getter + if ( method.getName().equals( getterName ) || method.getName().equals( isGetterName ) ) { + return method.getReturnType().getErasedType(); + } + + } + + if ( ClassDescriptor.class.isInstance( containerTypeDescriptor ) ) { + final ClassDescriptor superType = ( (ClassDescriptor) containerTypeDescriptor ).getSuperType(); + if ( superType != null ) { + return determineAttributeType( superType, attributeName ); + } + } + + return null; + } + + private static String capitalize(String attributeName) { + return Character.toUpperCase( attributeName.charAt( 0 ) ) + attributeName.substring( 1 ); + } + + + /** + * TODO : this should really use the field/methods descriptors to determine this information + *

    + * In the meantime we force load the Collection using ClassLoaderService and use Class to + * decide + */ + private static ReflectedCollectionJavaTypes determineReflectedCollectionJavaTypes( + ClassLoaderService classLoaderService, + PluralAttribute attribute) { + if ( attribute.getAttributeContainer().getDescriptor() == null ) { + return null; // EARLY RETURN + } + + + final String ownerClassName = attribute.getAttributeContainer().getDescriptor().getName().toString(); + try { + final Class ownerClass = classLoaderService.classForName( ownerClassName ); + PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate( + ownerClass, + attribute.getName() + ); + BeanInfoHelper.visitBeanInfo( ownerClass, delegate ); + return delegate.collectionJavaTypes; + } + catch ( Exception ignore ) { + log.debugf( + "Unable to locate attribute [%s] on class [%s]", + attribute.getName(), + ownerClassName + ); + } + return null; + } + + /** + * + * @return type parameters defined in the hibernate type descriptor or {@code empty property}. + */ + private static Properties getTypeParameters( + final HibernateTypeDescriptor hibernateTypeDescriptor) { + if ( CollectionHelper.isEmpty( hibernateTypeDescriptor.getTypeParameters() ) ) { + return null; + } + else { + Properties typeParameters = new Properties(); + typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() ); + return typeParameters; + } + } + + /** + * Find the referenced attribute name, if it is not id attribute. + * @param pluralAttributeBinding Plural attribute binding that has this reference info + * @return Plural attribute referenced attribute name, or null if it is id. + */ + private static String getReferencedPropertyNameIfNotId( + final PluralAttributeBinding pluralAttributeBinding) { + EntityIdentifier entityIdentifier = + pluralAttributeBinding.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + final String idAttributeName = + entityIdentifier.getAttributeBinding().getAttribute().getName(); + return pluralAttributeBinding.getReferencedPropertyName().equals( idAttributeName ) ? + null : + pluralAttributeBinding.getReferencedPropertyName(); + } + + /** + * @see HibernateTypeHelper#determineReflectedCollectionJavaTypes + */ + private static class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { + private final Class ownerClass; + private final String attributeName; + + private ReflectedCollectionJavaTypes collectionJavaTypes; + + private PluralAttributeJavaTypeDeterminerDelegate(Class ownerClass, String attributeName) { + this.ownerClass = ownerClass; + this.attributeName = attributeName; + } + + @Override + public void processBeanInfo(BeanInfo beanInfo) throws Exception { + Class collectionType = null; + Class elementJavaType = null; + Class indexJavaType = null; + + java.lang.reflect.Type collectionAttributeType = null; + if ( beanInfo.getPropertyDescriptors() == null || beanInfo.getPropertyDescriptors().length == 0 ) { + // we need to look for the field and look at it... + Field field = ownerClass.getDeclaredField( attributeName ); + field.setAccessible( true ); + collectionAttributeType = field.getGenericType(); + } + else { + for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) { + if ( propertyDescriptor.getName().equals( attributeName ) ) { + if ( propertyDescriptor.getReadMethod() != null ) { + collectionType = propertyDescriptor.getReadMethod().getReturnType(); + collectionAttributeType = propertyDescriptor.getReadMethod().getGenericReturnType(); + } + else if ( propertyDescriptor.getWriteMethod() != null ) { + collectionType = propertyDescriptor.getWriteMethod().getParameterTypes()[0]; + collectionAttributeType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0]; + } + } + } + } + + if ( collectionAttributeType != null ) { + if ( ParameterizedType.class.isInstance( collectionAttributeType ) ) { + final java.lang.reflect.Type[] types = ( (ParameterizedType) collectionAttributeType ).getActualTypeArguments(); + if ( types == null ) { + } + else if ( types.length == 1 ) { + elementJavaType = (Class) types[0]; + } + else if ( types.length == 2 ) { + // Map + indexJavaType = (Class) types[0]; + elementJavaType = (Class) types[1]; + } + } + else if ( collectionType != null && collectionType.isArray() ) { + elementJavaType = collectionType.getComponentType(); + } + else { + } + } + collectionJavaTypes = new ReflectedCollectionJavaTypes( collectionType, elementJavaType, indexJavaType ); + } + + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ManyToManyCollectionTableNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ManyToManyCollectionTableNamingStrategyHelper.java new file mode 100644 index 000000000000..f507379d4d45 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/ManyToManyCollectionTableNamingStrategyHelper.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Table; + +/** + * @author Strong Liu + */ +public class ManyToManyCollectionTableNamingStrategyHelper extends TableNamingStrategyHelper { + private final EntityBinding ownerEntityBinding; + private final EntityBinding inverseEntityBinding; + private final String ownerTableLogicalName; + private final String inverseTableLogicalName; + private final String propertyName; + + public ManyToManyCollectionTableNamingStrategyHelper( + final String attributePath, + final boolean isInverse, + final EntityBinding entityBinding, + final EntityBinding associatedEntityBinding) { + super( entityBinding ); + if ( isInverse ) { + ownerEntityBinding = associatedEntityBinding; + inverseEntityBinding = entityBinding; + } + else { + ownerEntityBinding = entityBinding; + inverseEntityBinding = associatedEntityBinding; + } + ownerTableLogicalName = + Table.class.isInstance( ownerEntityBinding.getPrimaryTable() ) + ? ( (Table) ownerEntityBinding.getPrimaryTable() ).getPhysicalName().getText() + : null; + inverseTableLogicalName = + Table.class.isInstance( inverseEntityBinding.getPrimaryTable() ) + ? ( (Table) inverseEntityBinding.getPrimaryTable() ).getPhysicalName().getText() + : null; + propertyName = attributePath; + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + return strategy.collectionTableName( + ownerEntityBinding.getEntityName(), + ownerTableLogicalName, + inverseEntityBinding.getEntityName(), + inverseTableLogicalName, + propertyName + ); + } + + @Override + public String getLogicalName(NamingStrategy strategy) { + return strategy.logicalCollectionTableName( + logicalName, + ownerEntityBinding.getPrimaryTable().getLogicalName().getText(), + inverseEntityBinding.getPrimaryTable().getLogicalName().getText(), + propertyName + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/NaturalIdUniqueKeyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/NaturalIdUniqueKeyHelper.java new file mode 100644 index 000000000000..4eb5acadd514 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/NaturalIdUniqueKeyHelper.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; + +/** + * @author Brett Meyer + */ +public class NaturalIdUniqueKeyHelper { + + private final BinderRootContext helperContext; + + private Map naturalIdUniqueKeys + = new HashMap(); + + public NaturalIdUniqueKeyHelper(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + /** + * Natural ID columns must reside in one single UniqueKey within the Table. + * To prevent separate UniqueKeys from being created, this keeps track of + * them in a HashMap. + * + * @param table + * @param column + */ + public void addUniqueConstraintForNaturalIdColumn( + final TableSpecification table, final Column column) { + UniqueKey uniqueKey; + if ( naturalIdUniqueKeys.containsKey( table ) ) { + uniqueKey = naturalIdUniqueKeys.get( table ); + } + else { + // TODO: For now, leave this out of the naming strategy. It has nothing to do with the columns. + String keyName = "UK_" + HashedNameUtil.hashedName( table.getLogicalName().getText() + "_NaturalID" ); + uniqueKey = new UniqueKey(); + uniqueKey.setTable( table ); + uniqueKey.setName( Identifier.toIdentifier( keyName ) ); + table.addUniqueKey( uniqueKey ); + naturalIdUniqueKeys.put( table, uniqueKey ); + } + uniqueKey.addColumn( column ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/RelationalIdentifierHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/RelationalIdentifierHelper.java new file mode 100644 index 000000000000..284fa19b7db2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/RelationalIdentifierHelper.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * @author Gail Badner + */ +public class RelationalIdentifierHelper { + + private final BinderRootContext helperContext; + + RelationalIdentifierHelper(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + public String normalizeDatabaseIdentifier( + final String explicitName, + final ObjectNameNormalizer.NamingStrategyHelper helper) { + return getObjectNameNormalizer().normalizeDatabaseIdentifier( explicitName, helper ); + } + + public Identifier createIdentifier(final String name){ + return createIdentifier( name, null ); + } + + public Identifier createIdentifier(final String name, final String defaultName) { + String identifier = StringHelper.isEmpty( name ) ? defaultName : name; + identifier = quotedIdentifier( identifier ); + return Identifier.toIdentifier( identifier ); + } + + public String quotedIdentifier(final String name) { + return getObjectNameNormalizer().normalizeIdentifierQuoting( name ); + } + + private ObjectNameNormalizer getObjectNameNormalizer() { + return helperContext.getMetadataCollector().getObjectNameNormalizer(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/RelationalValueBindingHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/RelationalValueBindingHelper.java new file mode 100644 index 000000000000..3b6f49f06941 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/RelationalValueBindingHelper.java @@ -0,0 +1,197 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.TruthValue; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.DerivedValueSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.RelationalValueSourceContainer; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Gail Badner + */ +public class RelationalValueBindingHelper { + + private final BinderRootContext helperContext; + + public RelationalValueBindingHelper(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + public boolean hasDerivedValue(List relationalValueBindings) { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if (relationalValueBinding.isDerived() ) { + return true; + } + } + return false; + } + + public List createRelationalValueBindings( + final AttributeBindingContainer attributeBindingContainer, + final RelationalValueSourceContainer valueSourceContainer, + final Attribute attribute, + final TableSpecification defaultTable, + final boolean forceNonNullable) { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( attribute.getName() ); + } + }; + return createRelationalValueBindings( + attributeBindingContainer, + valueSourceContainer, + defaultTable, + Collections.singletonList( defaultNamingStrategy ), + forceNonNullable + ); + } + + public List createRelationalValueBindings( + final AttributeBindingContainer attributeBindingContainer, + final RelationalValueSourceContainer valueSourceContainer, + final TableSpecification defaultTable, + final List defaultNameStrategies, + final boolean forceNonNullable) { + final List valueBindings = new ArrayList(); + final NaturalIdMutability naturalIdMutability; + if ( SingularAttributeSource.class.isInstance( valueSourceContainer ) ) { + naturalIdMutability = SingularAttributeSource.class.cast( valueSourceContainer ).getNaturalIdMutability(); + } + else { + naturalIdMutability = NaturalIdMutability.NOT_NATURAL_ID; + } + final boolean isNaturalId = naturalIdMutability != NaturalIdMutability.NOT_NATURAL_ID; + final boolean isImmutableNaturalId = isNaturalId && ( naturalIdMutability == NaturalIdMutability.IMMUTABLE ); + final boolean reallyForceNonNullable = forceNonNullable ; //|| isNaturalId; todo is a natural id column should be not nullable? + + if ( valueSourceContainer.relationalValueSources().isEmpty() ) { + for ( Binder.DefaultNamingStrategy defaultNameStrategy : defaultNameStrategies ) { + final Column column = helperContext.tableHelper().locateOrCreateColumn( + defaultTable, + null, + new DefaultColumnNamingStrategyHelper( defaultNameStrategy ) + ); + column.setNullable( !reallyForceNonNullable && valueSourceContainer.areValuesNullableByDefault() ); + if ( isNaturalId ) { + helperContext.naturalIdUniqueKeyHelper().addUniqueConstraintForNaturalIdColumn( defaultTable, column ); + } + valueBindings.add( + new RelationalValueBinding( + defaultTable, + column, + valueSourceContainer.areValuesIncludedInInsertByDefault(), + valueSourceContainer.areValuesIncludedInUpdateByDefault() && !isImmutableNaturalId + ) + ); + } + + } + else { + for ( int i = 0 ; i < valueSourceContainer.relationalValueSources().size(); i++ ) { + final RelationalValueSource valueSource = valueSourceContainer.relationalValueSources().get( i ); + final TableSpecification table = + valueSource.getContainingTableName() == null + ? defaultTable + : attributeBindingContainer.seekEntityBinding() + .locateTable( valueSource.getContainingTableName() ); + if ( valueSource.getNature() == RelationalValueSource.Nature.COLUMN ) { + final ColumnSource columnSource = (ColumnSource) valueSource; + final DefaultColumnNamingStrategyHelper defaultColumnNamingStrategyHelper = + new DefaultColumnNamingStrategyHelper( + StringHelper.isEmpty( columnSource.getName() ) ? + defaultNameStrategies.get( i ) : + null + ); + Column column = helperContext.tableHelper().locateOrCreateColumn( + table, + columnSource, + defaultColumnNamingStrategyHelper, + reallyForceNonNullable, + valueSourceContainer.areValuesNullableByDefault() + ); + if ( isNaturalId ) { + helperContext.naturalIdUniqueKeyHelper().addUniqueConstraintForNaturalIdColumn( table, column ); + } + final boolean isIncludedInInsert = + TruthValue.toBoolean( + columnSource.isIncludedInInsert(), + valueSourceContainer.areValuesIncludedInInsertByDefault() + ); + final boolean isIncludedInUpdate = + TruthValue.toBoolean( + columnSource.isIncludedInUpdate(), + valueSourceContainer.areValuesIncludedInUpdateByDefault() + ); + valueBindings.add( + new RelationalValueBinding( + table, + column, + isIncludedInInsert, + !isImmutableNaturalId && isIncludedInUpdate + ) + ); + } + else { + final DerivedValue derivedValue = + table.locateOrCreateDerivedValue( ( (DerivedValueSource) valueSource ).getExpression() ); + valueBindings.add( new RelationalValueBinding( table, derivedValue ) ); + } + } + } + return valueBindings; + } + + public List bindInverseRelationalValueBindings( + TableSpecification table, + List values) { + final List relationalValueBindings = + new ArrayList( values.size() ); + for ( Value value : values ) { + final RelationalValueBinding relationalValueBinding = + value.getValueType() == Value.ValueType.COLUMN ? + new RelationalValueBinding( table, (Column) value, false, false ) : + new RelationalValueBinding( table, (DerivedValue) value ); + relationalValueBindings.add( relationalValueBinding ); + } + return relationalValueBindings; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/SourceIndex.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/SourceIndex.java new file mode 100644 index 000000000000..6b0dd05a3554 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/SourceIndex.java @@ -0,0 +1,498 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.internal.CoreLogging; +import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSourceResolver; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.SimpleIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Column; + +import org.jboss.logging.Logger; + +/** + * Used to build indexes (x-refs) of various parts of an entity hierarchy and + * its attributes. + * + * @author Gail Badner + * @author Steve Ebersole + */ +public class SourceIndex { + private static final Logger log = CoreLogging.logger( SourceIndex.class ); + + private final Map entitySourceIndexByEntityName = new HashMap(); + private final Map attributeSourcesByKey = new HashMap(); + + private final Map mappedByAttributeKeysByOwnerAttributeKeys = + new HashMap(); + + + public void indexHierarchy(EntityHierarchySource hierarchy) { + final String hierarchyKey = hierarchy.getRoot().getEntityName(); + final HierarchyInfo hierarchyInfo = new HierarchyInfo( hierarchyKey, hierarchy ); + indexIdentifierAttributeSources( hierarchy, hierarchyInfo ); + + indexIdentifiableTypeSource( hierarchy.getRoot(), hierarchyInfo ); + } + + private void indexIdentifiableTypeSource(IdentifiableTypeSource identifiableTypeSource, HierarchyInfo hierarchyInfo) { + if ( EntitySource.class.isInstance( identifiableTypeSource ) ) { + indexEntitySource( (EntitySource) identifiableTypeSource, hierarchyInfo ); + } + + for ( IdentifiableTypeSource subTypes : identifiableTypeSource.getSubTypes() ) { + indexIdentifiableTypeSource( subTypes, hierarchyInfo ); + } + } + + private void indexEntitySource(EntitySource entitySource, HierarchyInfo hierarchyInfo) { + final String entityName = entitySource.getEntityName(); + EntitySourceIndex entitySourceIndex = new EntitySourceIndex( this, hierarchyInfo, entitySource ); + entitySourceIndexByEntityName.put( entityName, entitySourceIndex ); + log.debugf( "Indexing entity source [%s]", entityName ); + indexAttributes( entitySourceIndex ); + } + + private void indexIdentifierAttributeSources(EntityHierarchySource entityHierarchySource, HierarchyInfo hierarchyInfo) { + final IdentifierSource identifierSource = entityHierarchySource.getIdentifierSource(); + + switch ( identifierSource.getNature() ) { + case SIMPLE: { + final AttributeSource identifierAttributeSource = + ( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource(); + indexAttributeSources( hierarchyInfo, identifierAttributeSource, true ); + break; + } + case NON_AGGREGATED_COMPOSITE: { + final List nonAggregatedAttributeSources = + ( (NonAggregatedCompositeIdentifierSource) identifierSource ).getAttributeSourcesMakingUpIdentifier(); + for ( SingularAttributeSource nonAggregatedAttributeSource : nonAggregatedAttributeSources ) { + indexAttributeSources( hierarchyInfo, nonAggregatedAttributeSource, true ); + } + break; + } + case AGGREGATED_COMPOSITE: { + final EmbeddedAttributeSource aggregatedAttributeSource = + ( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource(); + indexAttributeSources( hierarchyInfo, aggregatedAttributeSource, true ); + break; + } + default: { + throw new AssertionFailure( + String.format( "Unknown type of identifier: [%s]", identifierSource.getNature() ) + ); + } + } + } + + private void indexAttributeSources( + AttributeIndexingTarget attributeIndexingTarget, + AttributeSource attributeSource, + boolean isInIdentifier) { + log.debugf( "Indexing attribute source [%s]", attributeSource.getAttributeRole() ); + attributeSourcesByKey.put( attributeSource.getAttributeRole(), attributeSource ); + + if ( attributeSource.isSingular() ) { + attributeIndexingTarget.indexSingularAttributeSource( (SingularAttributeSource) attributeSource, isInIdentifier ); + } + else { + attributeIndexingTarget.indexPluralAttributeSource( (PluralAttributeSource) attributeSource ); + } + + if ( attributeSource instanceof EmbeddedAttributeSource ) { + for ( AttributeSource subAttributeSource : ( (EmbeddedAttributeSource) attributeSource ).getEmbeddableSource().attributeSources() ) { + indexAttributeSources( + attributeIndexingTarget, + subAttributeSource, + isInIdentifier + ); + } + } + } + + private void indexAttributes(EntitySourceIndex entitySourceIndex) { + for ( final AttributeSource attributeSource : entitySourceIndex.entitySource.attributeSources() ) { + indexAttributeSources( entitySourceIndex, attributeSource, false ); + } + } + + + + + + + + + + + public void resolveAssociationSources(EntitySource source, BinderLocalBindingContext context) { + final EntityBinding binding = context.locateBinding( source ); + entitySourceIndexByEntityName.get( binding.getEntityName() ).resolveAttributeSources( context ); + } + + public Map getSingularAttributeSources( + String entityName, + boolean isMappedBy, + SingularAttributeNature singularAttributeNature) { + final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName ); + return entitySourceIndex.getSingularAttributeSources( isMappedBy, singularAttributeNature ); + } + + public Map getPluralAttributeSources( + String entityName, + boolean isInverse) { + final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName ); + return entitySourceIndex.getPluralAttributeSources( isInverse ); + } + + public AttributeSource attributeSource(final AttributeRole attributeRole) { + return attributeSourcesByKey.get( attributeRole ); + } + + public AttributeSource attributeSource(String entityName, String attributePath) { + final AttributeRole base = new AttributeRole( entityName ); + + AttributeRole role; + if ( attributePath.contains( "." ) ) { + role = base; + for ( String part : attributePath.split( "\\." ) ) { + role = role.append( part ); + } + } + else { + role = base.append( attributePath ); + } + return attributeSourcesByKey.get( role ); + } + + public AttributeSource attributeSource(EntityBinding entityBinding, AttributeBinding attributeBinding) { + return attributeSourcesByKey.get( attributeBinding.getAttributeRole() ); + } + + private static interface AttributeIndexingTarget { + public void indexSingularAttributeSource(SingularAttributeSource attributeSource, boolean isInIdentifier); + public void indexPluralAttributeSource(PluralAttributeSource attributeSource); + } + + private static abstract class AbstractAttributeIndexingTarget implements AttributeIndexingTarget { + private final Map unresolvedSingularAttributeSourcesByKey + = new HashMap(); + + private final Map> identifierAttributeSourcesByNature + = new EnumMap>( SingularAttributeNature.class ); + private final Map> nonMappedBySingularAttributeSourcesByNature + = new EnumMap>( SingularAttributeNature.class ); + private final Map> mappedBySingularAttributeSourcesByNature + = new EnumMap>( SingularAttributeNature.class ); + + // TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests + // depend on the ordering + // TODO: rework nonInversePluralAttributeSourcesByKey and inversePluralAttributeSourcesByKey + private final Map nonInversePluralAttributeSourcesByKey = + new LinkedHashMap(); + private final Map inversePluralAttributeSourcesByKey = + new LinkedHashMap(); + + @Override + public void indexSingularAttributeSource(SingularAttributeSource attributeSource, boolean isInIdentifier) { + if ( attributeSource.getSingularAttributeNature() == null ) { + unresolvedSingularAttributeSourcesByKey.put( attributeSource.getAttributeRole(), attributeSource ); + return; + } + + final Map> map; + if ( isInIdentifier ) { + map = identifierAttributeSourcesByNature; + } + else if ( ToOneAttributeSource.class.isInstance( attributeSource ) && + ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) { + map = mappedBySingularAttributeSourcesByNature; + } + else { + map = nonMappedBySingularAttributeSourcesByNature; + } + + indexSingularAttributeSource( attributeSource, map ); + } + + private static void indexSingularAttributeSource( + SingularAttributeSource attributeSource, + Map> map) { + final Map singularAttributeSources; + if ( map.containsKey( attributeSource.getSingularAttributeNature() ) ) { + singularAttributeSources = map.get( attributeSource.getSingularAttributeNature() ); + } + else { + singularAttributeSources = new LinkedHashMap(); + map.put( attributeSource.getSingularAttributeNature(), singularAttributeSources ); + } + if ( singularAttributeSources.put( attributeSource.getAttributeRole(), attributeSource ) != null ) { + throw new AssertionFailure( + String.format( + Locale.ENGLISH, + "Attempt to reindex attribute source for: [%s]", + attributeSource.getAttributeRole() + ) + ); + } + } + + + @Override + public void indexPluralAttributeSource(PluralAttributeSource attributeSource) { + final Map map = attributeSource.isInverse() + ? inversePluralAttributeSourcesByKey + : nonInversePluralAttributeSourcesByKey; + if ( map.put( attributeSource.getAttributeRole(), attributeSource ) != null ) { + throw new AssertionFailure( + String.format( + Locale.ENGLISH, + "Attempt to reindex attribute source for: [%s]", + attributeSource.getAttributeRole() ) + ); + } + } + + + public Map getSingularAttributeSources( + boolean isMappedBy, + SingularAttributeNature singularAttributeNature) { + final Map entries; + if ( isMappedBy && mappedBySingularAttributeSourcesByNature.containsKey( singularAttributeNature ) ) { + entries = Collections.unmodifiableMap( + mappedBySingularAttributeSourcesByNature.get( + singularAttributeNature + ) + ); + } + else if ( !isMappedBy && nonMappedBySingularAttributeSourcesByNature.containsKey( singularAttributeNature ) ) { + entries = Collections.unmodifiableMap( + nonMappedBySingularAttributeSourcesByNature.get( + singularAttributeNature + ) + ); + } + else { + entries = Collections.emptyMap(); + } + return entries; + } + + public Map getPluralAttributeSources(boolean isInverse) { + final Map map = isInverse + ? inversePluralAttributeSourcesByKey + : nonInversePluralAttributeSourcesByKey; + return Collections.unmodifiableMap( map ); + } + + + public void resolveAttributeSources(BinderLocalBindingContext context) { + final AttributeSourceResolutionContext sourceResolutionContext = makeAttributeSourceResolutionContext( context ); + + // Resolve plural attributes. + for ( PluralAttributeSource pluralAttributeSource : inversePluralAttributeSourcesByKey.values() ) { + if ( pluralAttributeSource.getMappedBy() != null ) { + // This plural attribute is mappedBy the opposite side of the association, + // so it needs to be resolved. + pluralAttributeSource.resolvePluralAttributeElementSource( sourceResolutionContext ); + } + + if ( IndexedPluralAttributeSource.class.isInstance( pluralAttributeSource ) ) { + final IndexedPluralAttributeSource indexedPluralAttributeSource = (IndexedPluralAttributeSource) pluralAttributeSource; + if ( PluralAttributeIndexSourceResolver.class.isInstance( indexedPluralAttributeSource.getIndexSource() ) ) { + ( (PluralAttributeIndexSourceResolver) indexedPluralAttributeSource.getIndexSource() ).resolvePluralAttributeIndexSource( + sourceResolutionContext + ); + } + } + } + + for ( PluralAttributeSource pluralAttributeSource : nonInversePluralAttributeSourcesByKey.values() ) { + if ( IndexedPluralAttributeSource.class.isInstance( pluralAttributeSource ) ) { + final IndexedPluralAttributeSource indexedPluralAttributeSource = (IndexedPluralAttributeSource) pluralAttributeSource; + if ( PluralAttributeIndexSourceResolver.class.isInstance( indexedPluralAttributeSource.getIndexSource() ) ) { + ( (PluralAttributeIndexSourceResolver) indexedPluralAttributeSource.getIndexSource() ).resolvePluralAttributeIndexSource( + sourceResolutionContext + ); + } + } + } + + // cycle through unresolved SingularAttributeSource. + // TODO: rework so approach is similar to one-to-many/many-to-many resolution. + for ( final SingularAttributeSource attributeSource : unresolvedSingularAttributeSourcesByKey.values() ) { + if ( !ToOneAttributeSource.class.isInstance( attributeSource ) ) { + throw new AssertionFailure( + String.format( + Locale.ENGLISH, + "Only a ToOneAttributeSource is expected to have a null nature; attribute: %s ", + attributeSource.getAttributeRole() + ) + ); + } + ToOneAttributeSource toOneAttributeSource = (ToOneAttributeSource) attributeSource; + toOneAttributeSource.resolveToOneAttributeSource( sourceResolutionContext ); + if ( toOneAttributeSource.getSingularAttributeNature() == null ) { + throw new AssertionFailure( + String.format( + Locale.ENGLISH, + "Null nature should have been resolved: %s ", + attributeSource.getAttributeRole() + ) + ); + } + indexSingularAttributeSource( + attributeSource, + toOneAttributeSource.isMappedBy() + ? mappedBySingularAttributeSourcesByNature + : nonMappedBySingularAttributeSourcesByNature + ); + } + } + + protected abstract AttributeSourceResolutionContext makeAttributeSourceResolutionContext(BinderLocalBindingContext context); + } + + private static class HierarchyInfo extends AbstractAttributeIndexingTarget { + private final String hierarchyKey; + private final EntityHierarchySource hierarchySource; + + private HierarchyInfo(String hierarchyKey, EntityHierarchySource hierarchySource) { + this.hierarchyKey = hierarchyKey; + this.hierarchySource = hierarchySource; + } + + @Override + public void indexPluralAttributeSource(PluralAttributeSource attributeSource) { + throw new AssertionFailure( + String.format( + "Identifiers should not contain plural attributes: [%s]", + attributeSource.getAttributeRole().getFullPath() + ) + ); + } + + @Override + public Map getPluralAttributeSources(boolean isInverse) { + return Collections.emptyMap(); + } + + @Override + protected AttributeSourceResolutionContext makeAttributeSourceResolutionContext(final BinderLocalBindingContext context) { + return new AttributeSourceResolutionContext() { + @Override + public IdentifierSource resolveIdentifierSource(String entityName) { + return hierarchySource.getIdentifierSource(); + } + + @Override + public AttributeSource resolveAttributeSource(String entityName, String attributeName) { + throw new UnsupportedOperationException( "Whaaa!?!" ); + } + + @Override + public List resolveIdentifierColumns() { + return context.locateBinding( hierarchySource ).getRootEntityBinding().getPrimaryTable().getPrimaryKey().getColumns(); + } + }; + } + } + + private static class EntitySourceIndex extends AbstractAttributeIndexingTarget { + private final SourceIndex sourceIndex; + private final HierarchyInfo hierarchyInfo; + private final EntitySource entitySource; + + private EntitySourceIndex( + final SourceIndex sourceIndex, + final HierarchyInfo hierarchyInfo, + final EntitySource entitySource) { + this.sourceIndex = sourceIndex; + this.hierarchyInfo = hierarchyInfo; + this.entitySource = entitySource; + } + + @Override + public Map getSingularAttributeSources( + boolean isMappedBy, + SingularAttributeNature singularAttributeNature) { + Map values = hierarchyInfo.getSingularAttributeSources( + isMappedBy, + singularAttributeNature + ); + if ( values == null || values.isEmpty() ) { + values = super.getSingularAttributeSources( isMappedBy, singularAttributeNature ); + } + + return values; + } + + @Override + protected AttributeSourceResolutionContext makeAttributeSourceResolutionContext( + final BinderLocalBindingContext context) { + return new AttributeSourceResolutionContext() { + @Override + public IdentifierSource resolveIdentifierSource(String entityName) { + return entitySource.getHierarchy().getIdentifierSource(); + } + + @Override + public AttributeSource resolveAttributeSource(String entityName, String attributeName) { + return sourceIndex.attributeSource( entityName, attributeName ); + } + + @Override + public List resolveIdentifierColumns() { + return context.locateBinding( entitySource ).getPrimaryTable().getPrimaryKey().getColumns(); + } + }; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/TableHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/TableHelper.java new file mode 100644 index 000000000000..bbdfb054f245 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/TableHelper.java @@ -0,0 +1,285 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.TruthValue; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.IndexNamingStrategyHelper; +import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.UniqueKeyNamingStrategyHelper; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.InLineViewSource; +import org.hibernate.metamodel.source.spi.MappingDefaults; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.source.spi.TableSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; + +import org.jboss.logging.Logger; + +/** + * @author Gail Badner + */ +public class TableHelper { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + TableHelper.class.getName() + ); + + private final BinderRootContext helperContext; + + public TableHelper(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + public TableSpecification createTable( + final TableSpecificationSource tableSpecSource, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + return createTable( tableSpecSource, namingStrategyHelper, null ); + } + + public TableSpecification createTable( + final TableSpecificationSource tableSpecSource, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper, + final Table includedTable) { + if ( tableSpecSource == null && namingStrategyHelper == null ) { + throw bindingContext().makeMappingException( + "An explicit name must be specified for the table" + ); + } + final boolean isTableSourceNull = tableSpecSource == null; + final Schema schema = resolveSchema( tableSpecSource ); + + TableSpecification tableSpec; + if ( isTableSourceNull || tableSpecSource instanceof TableSource ) { + String explicitName = isTableSourceNull ? null : TableSource.class.cast( tableSpecSource ).getExplicitTableName(); + String tableName = normalizeDatabaseIdentifier( explicitName, namingStrategyHelper ); + String logicTableName = TableNamingStrategyHelper.class.cast( namingStrategyHelper ).getLogicalName( + bindingContext().getBuildingOptions().getNamingStrategy() + ); + String rowId = isTableSourceNull ? null : TableSource.class.cast( tableSpecSource ).getRowId(); + tableSpec = createTableSpecification( + schema, + tableName, + logicTableName, + includedTable, + rowId + ); + } + else { + final InLineViewSource inLineViewSource = (InLineViewSource) tableSpecSource; + tableSpec = schema.createInLineView( + createIdentifier( inLineViewSource.getLogicalName() ), + inLineViewSource.getSelectStatement() + ); + } + return tableSpec; + } + + public Schema resolveSchema(final TableSpecificationSource tableSpecSource) { + final boolean tableSourceNull = tableSpecSource == null; + final MappingDefaults mappingDefaults = bindingContext().getMappingDefaults(); + final String explicitCatalogName = tableSourceNull ? null : tableSpecSource.getExplicitCatalogName(); + final String explicitSchemaName = tableSourceNull ? null : tableSpecSource.getExplicitSchemaName(); + final Schema.Name schemaName = + new Schema.Name( + createIdentifier( explicitCatalogName, mappingDefaults.getCatalogName() ), + createIdentifier( explicitSchemaName, mappingDefaults.getSchemaName() ) + ); + return bindingContext().getMetadataCollector().getDatabase().locateSchema( schemaName ); + } + + private TableSpecification createTableSpecification( + final Schema schema, + final String tableName, + final String logicTableName, + final Table includedTable, + String rowId) { + final Identifier logicalTableId = createIdentifier( logicTableName ); + final Identifier physicalTableId = createIdentifier( tableName ); + final Table table = schema.locateTable( logicalTableId ); + if ( table != null ) { + return table; + } + Table tableSpec; + if ( includedTable == null ) { + tableSpec = schema.createTable( logicalTableId, physicalTableId ); + } + else { + tableSpec = schema.createDenormalizedTable( logicalTableId, physicalTableId, includedTable ); + } + + tableSpec.setRowId( rowId ); + + return tableSpec; + } + + public Column locateOrCreateColumn( + final TableSpecification table, + final String columnName, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + if ( columnName == null && namingStrategyHelper == null ) { + throw bindingContext().makeMappingException( + "Cannot resolve name for column because no name was specified and namingStrategyHelper is null." + ); + } + final String resolvedColumnName = normalizeDatabaseIdentifier( + columnName, + namingStrategyHelper + ); + return table.locateOrCreateColumn( resolvedColumnName ); + } + + public Column locateColumn( + final TableSpecification table, + final String columnName, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + if ( columnName == null && namingStrategyHelper == null ) { + throw bindingContext().makeMappingException( + "Cannot resolve name for column because no name was specified and namingStrategyHelper is null." + ); + } + final String resolvedColumnName = normalizeDatabaseIdentifier( + columnName, + namingStrategyHelper + ); + return table.locateColumn( resolvedColumnName ); + } + + public Column locateOrCreateColumn( + final TableSpecification table, + final ColumnSource columnSource, + final ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper, + final boolean forceNotNull, + final boolean isNullableByDefault) { + final Column column = locateOrCreateColumn( table, columnSource.getName(), namingStrategyHelper ); + resolveColumnNullable( table, columnSource, forceNotNull, isNullableByDefault, column ); + column.setDefaultValue( columnSource.getDefaultValue() ); + column.setSqlType( columnSource.getSqlType() ); + if ( columnSource.getSizeSource() != null ) { + final SizeSource sizeSource = columnSource.getSizeSource(); + if ( sizeSource.isLengthDefined() ) { + column.getSize().setLength( sizeSource.getLength() ); + } + if ( sizeSource.isPrecisionDefined() ) { + column.getSize().setPrecision( sizeSource.getPrecision() ); + } + if ( sizeSource.isScaleDefined() ) { + column.getSize().setScale( sizeSource.getScale() ); + } + } + column.setJdbcDataType( columnSource.getDatatype() ); + column.setReadFragment( columnSource.getReadFragment() ); + column.setWriteFragment( columnSource.getWriteFragment() ); + column.setCheckCondition( columnSource.getCheckCondition() ); + column.setComment( columnSource.getComment() ); + + if (columnSource.isUnique()) { + createUniqueKey( table, Collections.singletonList( column ), null ); + } + return column; + } + + public void createUniqueKey( + final TableSpecification table, + final List columns, + final String name) { + final UniqueKey uk = new UniqueKey(); + for ( final Column column : columns ) { + uk.addColumn( column ); + } + uk.setTable( table ); + + final String normalizedName = normalizeDatabaseIdentifier( name, new UniqueKeyNamingStrategyHelper( table, columns ) ); + + uk.setName( Identifier.toIdentifier( normalizedName ) ); + table.addUniqueKey( uk ); + } + + public void createIndex( + final TableSpecification table, + final List columns, + final String name, + final boolean isUnique) { + final Index idx = new Index(isUnique); + for ( final Column column : columns ) { + idx.addColumn( column ); + } + idx.setTable( table ); + + final String normalizedName = normalizeDatabaseIdentifier( name, new IndexNamingStrategyHelper( table, columns ) ); + + idx.setName( Identifier.toIdentifier( normalizedName ) ); + table.addIndex( idx ); + } + + private void resolveColumnNullable( + final TableSpecification table, + final ColumnSource columnSource, + final boolean forceNotNull, + final boolean isNullableByDefault, + final Column column) { + if ( forceNotNull ) { + column.setNullable( false ); + if ( columnSource.isNullable() == TruthValue.TRUE ) { + log.warnf( + "Natural Id column[%s] from table[%s] has explicit set to allow nullable, we have to make it force not null ", + columnSource.getName(), + table.getLogicalName().getText() + ); + } + } + else { + // if the column is already non-nullable, leave it alone + if ( column.isNullable() ) { + column.setNullable( TruthValue.toBoolean( columnSource.isNullable(), isNullableByDefault ) ); + } + } + } + + private Identifier createIdentifier(String name) { + return helperContext.relationalIdentifierHelper().createIdentifier( name ); + } + + private Identifier createIdentifier(String name, String defaultName) { + return helperContext.relationalIdentifierHelper().createIdentifier( name, defaultName ); + } + + private String normalizeDatabaseIdentifier(String explicitName, ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper) { + return helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( explicitName, namingStrategyHelper ); + } + + private BinderLocalBindingContext bindingContext() { + return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/TableNamingStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/TableNamingStrategyHelper.java new file mode 100644 index 000000000000..5aafa433705e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/binder/TableNamingStrategyHelper.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.binder; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +/** + * @author Strong Liu + */ +class TableNamingStrategyHelper implements ObjectNameNormalizer.LogicalNamingStrategyHelper { + protected final EntityBinding entityBinding; + protected final String entityName; + protected String logicalName; + + TableNamingStrategyHelper(EntityBinding entityBinding) { + this.entityBinding = entityBinding; + this.entityName = getImplicitTableName(); + } + + @Override + public String determineImplicitName(NamingStrategy strategy) { + String name = getImplicitTableName(); + return strategy.classToTableName( name ); + } + + protected String getImplicitTableName() { + return StringHelper.isNotEmpty( entityBinding.getJpaEntityName() ) + ? entityBinding.getJpaEntityName() + : entityBinding.getEntityName(); + } + + @Override + public String handleExplicitName(NamingStrategy strategy, String tableName) { + this.logicalName = tableName; + return strategy.tableName( tableName ); + } + + @Override + public String getLogicalName(NamingStrategy strategy) { + return logicalName == null ? entityName : logicalName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java new file mode 100644 index 000000000000..dbf6071aadc1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/AssociationRelationalBindingResolver.java @@ -0,0 +1,113 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.resolver; + +import java.util.List; + +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + + * @author Gail Badner + + */ +public interface AssociationRelationalBindingResolver { + + SingularAttributeBinding resolveOneToOneReferencedAttributeBinding( + final ToOneAttributeSource attributeSource, + final EntityBinding referencedEntityBinding); + + List resolveOneToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeBinding referencedAttributeBinding); + + ForeignKey resolveOneToOneForeignKey( + ToOneAttributeSource attributeSource, + TableSpecification sourceTable, + List sourceColumns, + EntityBinding referencedEntityBinding); + + SingularAttributeBinding resolveManyToOneReferencedAttributeBinding( + final AttributeBindingContainer attributeBindingContainer, + final ToOneAttributeSource attributeSource, + final EntityBinding referencedEntityBinding); + + // TODO: referencedAttributeBinding and referencedEntityBinding are both included due to a bug that can + // cause entityBinding != entityBinding.hierarchyDetails.getEntityIdentifier().getAttributeBinding().getContainer() + List resolveManyToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeBinding referencedAttributeBinding, + final EntityBinding referencedEntityBinding); + + ForeignKey resolveManyToOneForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + List relationalValueBindings, + EntityBinding referencedEntityBinding); + + List resolveManyToManyElementRelationalValueBindings( + final EntityBinding entityBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding); + + ForeignKey resolveManyToManyElementForeignKey( + final EntityBinding entityBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding); + + TableSpecification resolveManyToManyCollectionTable( + PluralAttributeSource pluralAttributeSource, + String attributePath, + EntityBinding entityBinding, + EntityBinding referencedEntityBinding); + + List resolvePluralAttributeKeyRelationalValueBindings( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding); + + ForeignKey resolvePluralAttributeKeyForeignKey( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding); + + SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding( + final AttributeBindingContainer attributeBindingContainer, + final PluralAttributeSource attributeSource); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java new file mode 100644 index 000000000000..db48c0cf5e6e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/MappedByAssociationRelationalBindingResolverImpl.java @@ -0,0 +1,363 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.resolver; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.binder.BinderRootContext; +import org.hibernate.metamodel.internal.binder.ForeignKeyHelper; +import org.hibernate.metamodel.internal.binder.RelationalValueBindingHelper; +import org.hibernate.metamodel.source.spi.AssociationSource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingManyToMany; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.type.ForeignKeyDirection; + +/** + + * @author Gail Badner + + */ +public class MappedByAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver { + private final BinderRootContext helperContext; + + public MappedByAssociationRelationalBindingResolverImpl(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + @Override + public SingularAttributeBinding resolveOneToOneReferencedAttributeBinding( + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return (SingularAttributeBinding) referencedEntityBinding.locateAttributeBindingByPath( + getMappedByAssociationSource( attributeSource ).getMappedBy(), + true + ); + } + + @Override + public List resolveOneToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding) { + return Collections.emptyList(); + } + + @Override + public ForeignKey resolveOneToOneForeignKey( + ToOneAttributeSource attributeSource, + TableSpecification sourceTable, + List sourceColumns, + EntityBinding referencedEntityBinding) { + // TODO: get rid of this duplication!!! + if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) { + throw new AssertionFailure( "Cannot create a foreign key for one-to-one with foreign key direction going to the parent." ); + } + final List targetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + attributeSource + ); + final TableSpecification targetTable = foreignKeyHelper().determineForeignKeyTargetTable( + referencedEntityBinding, + attributeSource + ); + return foreignKeyHelper().locateOrCreateForeignKey( + attributeSource.getExplicitForeignKeyName(), + sourceTable, + sourceColumns, + targetTable, + targetColumns, + attributeSource.isCascadeDeleteEnabled(), + attributeSource.createForeignKeyConstraint() + ); + } + + @Override + public SingularAttributeBinding resolveManyToOneReferencedAttributeBinding( + AttributeBindingContainer attributeBindingContainer, + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + // This is a mappedBy many-to-one. This should only happen when the owning many-to-one uses a join table. + // TODO: confirm the above is true. + final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable( + getMappedByAssociationSource( attributeSource ), + referencedEntityBinding + ); + return referencedEntityBinding.locateAttributeBinding( + ownerSecondaryTable.getForeignKeyReference().getTargetTable(), + ownerSecondaryTable.getForeignKeyReference().getTargetColumns(), + true + ); + } + + @Override + public List resolveManyToOneRelationalValueBindings( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding, + EntityBinding referencedEntityBinding) { + // A many-to-one can only have mappedBy specified if there is a join table. + // TODO: confirm this is true. + // The relational value bindings for the attribute being processed + // will contain the columns that make up the FK join tables on the + // owner's secondary table. + final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable( + getMappedByAssociationSource( attributeSource ), + referencedEntityBinding + ); + return relationalValueBindingHelper().bindInverseRelationalValueBindings( + ownerSecondaryTable.getForeignKeyReference().getSourceTable(), + ownerSecondaryTable.getForeignKeyReference().getSourceColumns() + ); + } + + @Override + public ForeignKey resolveManyToOneForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + List relationalValueBindings, + EntityBinding referencedEntityBinding) { + // A many-to-one can only have mappedBy specified if there is a join table. + // TODO: confirm this is true. + final SecondaryTable ownerSecondaryTable = getOwnerSecondaryTable( + getMappedByAssociationSource( attributeSource ), + referencedEntityBinding + ); + return ownerSecondaryTable.getForeignKeyReference(); + } + + @Override + public List resolveManyToManyElementRelationalValueBindings( + final EntityBinding entityBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding) { + { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( elementSource ) + ); + final List relationalValueBindings; + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + // the owner is a many-to-one on a join table; the target will be the FK target + // for the secondary table. + final SecondaryTable ownerSecondaryTable = + referencedEntityBinding.getSecondaryTables().get( collectionTable.getLogicalName() ); + relationalValueBindings = relationalValueBindingHelper().bindInverseRelationalValueBindings( + collectionTable, + ownerSecondaryTable.getForeignKeyReference().getSourceColumns() + ); + } + else { + final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + relationalValueBindings = relationalValueBindingHelper().bindInverseRelationalValueBindings( + collectionTable, + ownerPluralAttributeBinding.getPluralAttributeKeyBinding().getValues() + ); + } + return relationalValueBindings; + } + } + + @Override + public ForeignKey resolveManyToManyElementForeignKey( + final EntityBinding entityBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( elementSource ) + ); + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + // the owner is a many-to-one on a join table; the target will be the FK target + // for the secondary table. + final SecondaryTable ownerSecondaryTable = + referencedEntityBinding.getSecondaryTables().get( collectionTable.getLogicalName() ); + return ownerSecondaryTable.getForeignKeyReference(); + } + else { + final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + return ownerPluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey(); + } + } + + @Override + public TableSpecification resolveManyToManyCollectionTable( + PluralAttributeSource pluralAttributeSource, + String attributePath, + EntityBinding entityBinding, + EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) pluralAttributeSource.getElementSource() ) + ); + return ownerAttributeBinding.getAttribute().isSingular() ? + ( (SingularAssociationAttributeBinding) ownerAttributeBinding ).getTable() : + ( (PluralAttributeBinding) ownerAttributeBinding ).getPluralAttributeKeyBinding().getCollectionTable(); + } + + @Override + public List resolvePluralAttributeKeyRelationalValueBindings( + PluralAttributeSource attributeSource, + EntityBinding entityBinding, + TableSpecification collectionTable, + EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() ) + ); + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + return ( (ManyToOneAttributeBinding) ownerAttributeBinding ).getRelationalValueBindings(); + } + else { + final PluralAttributeBinding pluralOwnerAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + final PluralAttributeElementBindingManyToMany ownerElementBinding = + (PluralAttributeElementBindingManyToMany) pluralOwnerAttributeBinding.getPluralAttributeElementBinding(); + return ownerElementBinding.getRelationalValueContainer().relationalValueBindings(); + } + } + + @Override + public ForeignKey resolvePluralAttributeKeyForeignKey( + PluralAttributeSource attributeSource, + EntityBinding entityBinding, + TableSpecification collectionTable, + List sourceRelationalValueBindings, + EntityBinding referencedEntityBinding) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() ) + ); + final ForeignKey foreignKey; + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + foreignKey = ( (ManyToOneAttributeBinding) ownerAttributeBinding ).getForeignKey(); + } + else { + final PluralAttributeBinding pluralOwnerAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + final PluralAttributeElementBindingManyToMany ownerElementBinding = + (PluralAttributeElementBindingManyToMany) pluralOwnerAttributeBinding.getPluralAttributeElementBinding(); + foreignKey = ownerElementBinding.getForeignKey(); + } + if ( attributeSource.getKeySource().isCascadeDeleteEnabled() ) { + foreignKey.setDeleteRule( ForeignKey.ReferentialAction.CASCADE ); + } + return foreignKey; + + } + + @Override + public SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding( + AttributeBindingContainer attributeBindingContainer, + PluralAttributeSource attributeSource) { + final AttributeBinding ownerAttributeBinding = getOwnerAttributeBinding( + getMappedByAssociationSource( (AssociationSource) attributeSource.getElementSource() ) + ); + final SingularAttributeBinding referencedAttributeBinding; + if ( ownerAttributeBinding.getAttribute().isSingular() ) { + referencedAttributeBinding = + ( (SingularAssociationAttributeBinding) ownerAttributeBinding ).getReferencedAttributeBinding(); + } + else { + final PluralAttributeBinding ownerPluralAttributeBinding = (PluralAttributeBinding) ownerAttributeBinding; + final PluralAttributeElementBindingManyToMany ownerElementBinding = + (PluralAttributeElementBindingManyToMany) ownerPluralAttributeBinding + .getPluralAttributeElementBinding(); + referencedAttributeBinding = attributeBindingContainer.seekEntityBinding().locateAttributeBinding( + ownerElementBinding.getForeignKey().getTargetTable(), + ownerElementBinding.getForeignKey().getTargetColumns(), + true + ); + if ( referencedAttributeBinding == null ) { + throw new NotYetImplementedException( "Referenced columns not used by an attribute binding is not supported yet." ); + } + } + return referencedAttributeBinding; + } + + private LocalBindingContext bindingContext() { + return helperContext.getLocalBindingContextSelector().getCurrentBinderLocalBindingContext(); + } + + private MappedByAssociationSource getMappedByAssociationSource(AssociationSource associationSource) { + if ( !associationSource.isMappedBy() || !MappedByAssociationSource.class.isInstance( associationSource ) ) { + throw new AssertionFailure( "Expected a MappedByAssociationSource." ); + } + return (MappedByAssociationSource) associationSource; + } + + private AttributeBinding getOwnerAttributeBinding(MappedByAssociationSource associationSource) { + final EntityBinding referencedEntityBinding = bindingContext().getMetadataCollector().getEntityBinding( + associationSource.getReferencedEntityName() + ); + final AttributeBinding ownerAttributeBinding = referencedEntityBinding.locateAttributeBindingByPath( + associationSource.getMappedBy(), + true + ); + if ( ownerAttributeBinding == null ) { + throw bindingContext().makeMappingException( + String.format( + "Attribute not found: [%s.%s]", + referencedEntityBinding.getEntityName(), + associationSource.getMappedBy() + ) + ); + } + return ownerAttributeBinding; + } + + private SecondaryTable getOwnerSecondaryTable( + MappedByAssociationSource attributeSource, + EntityBinding referencedEntityBinding) { + SingularAssociationAttributeBinding ownerAttributeBinding = + (SingularAssociationAttributeBinding) referencedEntityBinding.locateAttributeBinding( + attributeSource.getMappedBy() + ); + TableSpecification table = ownerAttributeBinding.getTable(); + if ( referencedEntityBinding.getPrimaryTable().equals( table ) ) { + throw new AssertionFailure( "many-to-one has mappedby specified but it does not use a join table." ); + } + return referencedEntityBinding.getSecondaryTables().get( table.getLogicalName() ); + } + + private ForeignKeyHelper foreignKeyHelper() { + return helperContext.foreignKeyHelper(); + } + + private RelationalValueBindingHelper relationalValueBindingHelper() { + return helperContext.relationalValueBindingHelper(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java new file mode 100644 index 000000000000..712c95d2e311 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/resolver/StandardAssociationRelationalBindingResolverImpl.java @@ -0,0 +1,430 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.resolver; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.internal.binder.BinderRootContext; +import org.hibernate.metamodel.internal.binder.ForeignKeyHelper; +import org.hibernate.metamodel.internal.binder.ManyToManyCollectionTableNamingStrategyHelper; +import org.hibernate.metamodel.internal.binder.RelationalValueBindingHelper; +import org.hibernate.metamodel.internal.binder.TableHelper; +import org.hibernate.metamodel.source.spi.AssociationSource; +import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeKeySource; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSourceContainer; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.type.ForeignKeyDirection; + +/** + + * @author Gail Badner + + */ +public class StandardAssociationRelationalBindingResolverImpl implements AssociationRelationalBindingResolver { + private final BinderRootContext helperContext; + + public StandardAssociationRelationalBindingResolverImpl(BinderRootContext helperContext) { + this.helperContext = helperContext; + } + + @Override + public SingularAttributeBinding resolveOneToOneReferencedAttributeBinding( + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return resolveReferencedAttributeBinding( attributeSource, referencedEntityBinding ); + } + + @Override + public List resolveOneToOneRelationalValueBindings( + final ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding) { + if ( ! attributeSource.relationalValueSources().isEmpty() ) { + final TableSpecification defaultTable = + locateDefaultTableSpecificationForAttribute( + attributeBindingContainer, + attributeSource + ); + return resolveRelationalValueBindings( + attributeSource, + attributeBindingContainer.seekEntityBinding(), + defaultTable, + false, + attributeSource.getDefaultNamingStrategies( + attributeBindingContainer.seekEntityBinding().getEntityName(), + defaultTable.getLogicalName().getText(), + referencedAttributeBinding + ) + ); + } + else { + return Collections.emptyList(); + } + } + + private TableSpecification locateDefaultTableSpecificationForAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return attributeSource.getContainingTableName() == null ? + attributeBindingContainer.getPrimaryTable() : + attributeBindingContainer.seekEntityBinding().locateTable( attributeSource.getContainingTableName() ); + } + + + @Override + public ForeignKey resolveOneToOneForeignKey( + ToOneAttributeSource attributeSource, + TableSpecification sourceTable, + List sourceColumns, + EntityBinding referencedEntityBinding) { + if ( attributeSource.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) { + throw new AssertionFailure( "Cannot create a foreign key for one-to-one with foreign key direction going to the parent." ); + } + + final TableSpecification targetTable = foreignKeyHelper().determineForeignKeyTargetTable( + referencedEntityBinding, + attributeSource + ); + final List targetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + attributeSource + ); + return foreignKeyHelper().locateOrCreateForeignKey( + attributeSource.getExplicitForeignKeyName(), + sourceTable, + sourceColumns, + targetTable, + targetColumns, + attributeSource.isCascadeDeleteEnabled(), + attributeSource.createForeignKeyConstraint() + ); + } + + @Override + public SingularAttributeBinding resolveManyToOneReferencedAttributeBinding( + AttributeBindingContainer attributeBindingContainer, + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return resolveReferencedAttributeBinding( attributeSource, referencedEntityBinding ); + } + + @Override + public List resolveManyToOneRelationalValueBindings( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + SingularAttributeBinding referencedAttributeBinding, + EntityBinding referencedEntityBinding) { + final TableSpecification defaultTable = + locateDefaultTableSpecificationForAttribute( + attributeBindingContainer, + attributeSource + ); + return resolveRelationalValueBindings( + attributeSource, + attributeBindingContainer.seekEntityBinding(), + defaultTable, + false, + attributeSource.getDefaultNamingStrategies( + attributeBindingContainer.seekEntityBinding().getEntityName(), + defaultTable.getLogicalName().getText(), + referencedAttributeBinding + ) + ); + + } + + @Override + public ForeignKey resolveManyToOneForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + List relationalValueBindings, + EntityBinding referencedEntityBinding) { + final List targetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + attributeSource + ); + return locateOrCreateForeignKey( + attributeSource, + referencedEntityBinding, + relationalValueBindings.get( 0 ).getTable(), + relationalValueBindings, + targetColumns + ); + } + + @Override + public List resolveManyToManyElementRelationalValueBindings( + final EntityBinding entityBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding) { + final List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + elementSource + ); + final List namingStrategies = new ArrayList( targetColumns.size() ); + for ( final Column targetColumn : targetColumns ) { + namingStrategies.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.foreignKeyColumnName( + elementSource.getAttributeSource().getName(), + referencedEntityBinding.getEntityName(), + referencedEntityBinding.getPrimaryTableName(), + targetColumn.getColumnName().getText() + ); + } + } + ); + } + return resolveRelationalValueBindings( + elementSource, + entityBinding, + collectionTable, + true, + namingStrategies + ); + } + + @Override + public ForeignKey resolveManyToManyElementForeignKey( + final EntityBinding entityBinding, + final PluralAttributeElementSourceManyToMany elementSource, + final TableSpecification collectionTable, + final List relationalValueBindings, + final EntityBinding referencedEntityBinding) { + final List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + elementSource + ); + return locateOrCreateForeignKey( + elementSource, + referencedEntityBinding, + collectionTable, + relationalValueBindings, + targetColumns + ); + } + + @Override + public TableSpecification resolveManyToManyCollectionTable( + PluralAttributeSource pluralAttributeSource, + String attributePath, + EntityBinding entityBinding, + EntityBinding referencedEntityBinding) { + + final TableSpecificationSource collectionTableSource = pluralAttributeSource.getCollectionTableSpecificationSource(); + return tableHelper().createTable( + collectionTableSource, + new ManyToManyCollectionTableNamingStrategyHelper( + attributePath, + pluralAttributeSource.isInverse(), + entityBinding, + referencedEntityBinding + ) + ); + } + + @Override + public List resolvePluralAttributeKeyRelationalValueBindings( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final EntityBinding referencedEntityBinding) { + final PluralAttributeKeySource keySource = attributeSource.getKeySource(); + + final ListtargetColumns = foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + keySource + ); + final List namingStrategies = new ArrayList( targetColumns.size() ); + + final String ownedAttributeName; + if ( attributeSource.getElementSource().getNature().isAssociation() ) { + final AssociationSource associationSource = (AssociationSource) attributeSource.getElementSource(); + if ( associationSource.getOwnedAssociationSources().size() > 1 ) { + throw new NotYetImplementedException( "Cannot determine default naming strategy when an association owns more than 1 other association." ); + } + if ( associationSource.getOwnedAssociationSources().isEmpty() ) { + ownedAttributeName = null; + } + else { + final AssociationSource ownedAssociationSource = associationSource.getOwnedAssociationSources().iterator().next(); + ownedAttributeName = ownedAssociationSource.getAttributeSource().getName(); + } + } + else { + ownedAttributeName = null; + } + + for ( final Column targetColumn : targetColumns ) { + namingStrategies.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.foreignKeyColumnName( + ownedAttributeName, + entityBinding.getEntityName(), + entityBinding.getPrimaryTableName(), + targetColumn.getColumnName().getText() + ); + } + } + ); + } + return resolveRelationalValueBindings( + keySource, + entityBinding, + collectionTable, + attributeSource.getElementSource().getNature() != PluralAttributeElementNature.ONE_TO_MANY, + namingStrategies + ); + } + + @Override + public ForeignKey resolvePluralAttributeKeyForeignKey( + final PluralAttributeSource attributeSource, + final EntityBinding entityBinding, + final TableSpecification collectionTable, + final List sourceRelationalValueBindings, + final EntityBinding referencedEntityBinding) { + final PluralAttributeKeySource keySource = attributeSource.getKeySource(); + List targetColumns = + foreignKeyHelper().determineForeignKeyTargetColumns( + referencedEntityBinding, + keySource + ); + return locateOrCreateForeignKey( + keySource, + referencedEntityBinding, + collectionTable, + sourceRelationalValueBindings, + targetColumns + ); + } + + @Override + public SingularAttributeBinding resolvePluralAttributeKeyReferencedBinding( + AttributeBindingContainer attributeBindingContainer, + PluralAttributeSource attributeSource) { + return foreignKeyHelper().determineReferencedAttributeBinding( + attributeSource.getKeySource(), + attributeBindingContainer.seekEntityBinding() + ); + } + + + private SingularAttributeBinding resolveReferencedAttributeBinding( + ToOneAttributeSource attributeSource, + EntityBinding referencedEntityBinding) { + return foreignKeyHelper().determineReferencedAttributeBinding( attributeSource, referencedEntityBinding ); + } + + public List resolveRelationalValueBindings( + final RelationalValueSourceContainer relationalValueSourceContainer, + EntityBinding entityBinding, + TableSpecification defaultTable, + boolean forceNonNullable, + List defaultNamingStrategies) { + return relationalValueBindingHelper().createRelationalValueBindings( + entityBinding, + relationalValueSourceContainer, + defaultTable, + defaultNamingStrategies, + forceNonNullable + ); + } + + private ForeignKey locateOrCreateForeignKey( + final ForeignKeyContributingSource foreignKeyContributingSource, + final EntityBinding referencedEntityBinding, + final TableSpecification sourceTable, + final List sourceRelationalValueBindings, + final List targetColumns) { + final TableSpecification targetTable = foreignKeyHelper().determineForeignKeyTargetTable( + referencedEntityBinding, + foreignKeyContributingSource + ); + return foreignKeyHelper().locateOrCreateForeignKey( + foreignKeyContributingSource.getExplicitForeignKeyName(), + sourceTable, + extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ), + targetTable, + targetColumns, + foreignKeyContributingSource.isCascadeDeleteEnabled(), + foreignKeyContributingSource.createForeignKeyConstraint() + ); + } + + private TableHelper tableHelper() { + return helperContext.tableHelper(); + } + + private ForeignKeyHelper foreignKeyHelper() { + return helperContext.foreignKeyHelper(); + } + + private RelationalValueBindingHelper relationalValueBindingHelper() { + return helperContext.relationalValueBindingHelper(); + } + + // TODO: try to get rid of this... + private static List extractColumnsFromRelationalValueBindings( + final List valueBindings) { + List columns = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : valueBindings ) { + final Value value = relationalValueBinding.getValue(); + // todo : currently formulas are not supported here... :( + if ( !Column.class.isInstance( value ) ) { + throw new NotYetImplementedException( + "Derived values are not supported when creating a foreign key that targets columns." + ); + } + columns.add( (Column) value ); + } + return columns; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ArrayDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ArrayDescriptorImpl.java new file mode 100644 index 000000000000..bd8962bf7606 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ArrayDescriptorImpl.java @@ -0,0 +1,143 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public class ArrayDescriptorImpl implements ArrayDescriptor { + private final DotName name; + private final int modifiers; + private JavaTypeDescriptor componentType; + + public ArrayDescriptorImpl(DotName name, int modifiers, JavaTypeDescriptor componentType) { + this.name = name; + this.modifiers = modifiers; + this.componentType = componentType; + } + + @Override + public DotName getName() { + return name; + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public Collection getDeclaredFields() { + return Collections.emptyList(); + } + + @Override + public Collection getDeclaredMethods() { + return Collections.emptyList(); + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public Collection findAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public boolean isAssignableFrom(JavaTypeDescriptor check) { + if ( check == null ) { + throw new IllegalArgumentException( "Descriptor to check cannot be null" ); + } + + if ( equals( check ) ) { + return true; + } + + if ( ArrayDescriptor.class.isInstance( check ) ) { + final ArrayDescriptor other = (ArrayDescriptor) check; + return getComponentType().isAssignableFrom( other.getComponentType() ); + } + + return false; + } + + @Override + public List getResolvedParameterTypes() { + return Collections.emptyList(); + } + + @Override + public ClassInfo getJandexClassInfo() { + return null; + } + + @Override + public JavaTypeDescriptor getComponentType() { + return componentType; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final ArrayDescriptorImpl that = (ArrayDescriptorImpl) o; + return name.equals( that.name ); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ClassDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ClassDescriptorImpl.java new file mode 100644 index 000000000000..ef691d1667ba --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ClassDescriptorImpl.java @@ -0,0 +1,247 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Implementation of a type descriptor + * + * @author Steve Ebersole + */ +public class ClassDescriptorImpl extends InternalJavaTypeDescriptor implements ClassDescriptor { + private final ClassInfo jandexClassInfo; + + private final int modifiers; + private final boolean hasDefaultConstructor; + private final Map typeAnnotationMap; + private final Map> annotationMap; + + private ClassDescriptor superType; + private Collection interfaces; + + private Collection fieldDescriptors; + private Collection methodDescriptors; + private List typeParameters; + + public ClassDescriptorImpl( + ClassInfo jandexClassInfo, + int modifiers, + boolean hasDefaultConstructor, + Map typeAnnotationMap, + Map> annotationMap) { + this.jandexClassInfo = jandexClassInfo; + this.modifiers = modifiers; + this.hasDefaultConstructor = hasDefaultConstructor; + this.typeAnnotationMap = typeAnnotationMap != null + ? typeAnnotationMap + : Collections.emptyMap(); + this.annotationMap = annotationMap != null + ? annotationMap + : Collections.>emptyMap(); + } + + @Override + public DotName getName() { + return jandexClassInfo.name(); + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public ClassDescriptor getSuperType() { + return superType; + } + + @Override + public Collection getInterfaceTypes() { + return interfaces; + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + final AnnotationInstance localTypeAnnotation = findLocalTypeAnnotation( annotationType ); + if ( localTypeAnnotation != null ) { + return localTypeAnnotation; + } + + if ( superType != null ) { + return superType.findTypeAnnotation( annotationType ); + } + + for ( InterfaceDescriptor interfaceDescriptor : interfaces ) { + final AnnotationInstance annotationInstance = interfaceDescriptor.findTypeAnnotation( annotationType ); + if ( annotationInstance != null ) { + return annotationInstance; + } + } + + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return typeAnnotationMap.get( annotationType ); + } + + @Override + public Collection findAnnotations(DotName annotationType) { + final List annotationInstances = new ArrayList(); + + annotationInstances.addAll( findLocalAnnotations( annotationType ) ); + + if ( superType != null ) { + annotationInstances.addAll( superType.findAnnotations( annotationType ) ); + } + + for ( InterfaceDescriptor interfaceDescriptor : interfaces ) { + annotationInstances.addAll( interfaceDescriptor.findAnnotations( annotationType ) ); + } + + return annotationInstances; + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + final Collection them = annotationMap.get( annotationType ); + return them == null ? Collections.emptyList() : them; + } + +// @Override +// public boolean isAssignableFrom(JavaTypeDescriptor check) { +// if ( check == null ) { +// throw new IllegalArgumentException( "Descriptor to check cannot be null" ); +// } +// +// if ( equals( check ) ) { +// return true; +// } +// +// if ( superType != null && superType.isAssignableFrom( check ) ) { +// return true; +// } +// +// for ( InterfaceDescriptor implementsInterface : getInterfaceTypes() ) { +// if ( implementsInterface.isAssignableFrom( check ) ) { +// return true; +// } +// } +// +// return false; +// } +// + @Override + public boolean hasDefaultConstructor() { + return hasDefaultConstructor; + } + + @Override + public Collection getDeclaredFields() { + return fieldDescriptors == null ? Collections.emptyList() : fieldDescriptors; + } + + @Override + public Collection getDeclaredMethods() { + return methodDescriptors == null ? Collections.emptyList() : methodDescriptors; + } + + @Override + public ClassInfo getJandexClassInfo() { + return jandexClassInfo; + } + + @Override + public String toString() { + return "ClassDescriptorImpl{" + getName().toString() + '}'; + } + + void setSuperType(ClassDescriptor superType) { + this.superType = superType; + } + + void setInterfaces(Collection interfaces) { + this.interfaces = interfaces; + } + + void setFields(Collection fieldDescriptors) { + this.fieldDescriptors = fieldDescriptors; + } + + void setMethods(Collection methodDescriptors) { + this.methodDescriptors = methodDescriptors; + } + + public void setTypeParameters(List typeParameters) { + this.typeParameters = typeParameters; + } + + @Override + public List getResolvedParameterTypes() { + return typeParameters; + } + @Override + public ClassDescriptor getSuperclass() { + return null; + } + + @Override + public Collection getInterfaces() { + return getInterfaceTypes(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final ClassDescriptorImpl that = (ClassDescriptorImpl) o; + return getName().equals( that.getName() ); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicAnnotationBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicAnnotationBuilder.java new file mode 100644 index 000000000000..e813408da806 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicAnnotationBuilder.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.List; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public interface DynamicAnnotationBuilder { + public AnnotationInstance makeAnnotation(DotName annotationTypeName, AnnotationValue... values); + public AnnotationInstance makeAnnotation(DotName annotationTypeName, List values); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicAttributeDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicAttributeDescriptorImpl.java new file mode 100644 index 000000000000..03480452b4ac --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicAttributeDescriptorImpl.java @@ -0,0 +1,160 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.DynamicAttributeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.ParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public class DynamicAttributeDescriptorImpl implements DynamicAttributeDescriptor, AnnotationTarget { + private final DynamicTypeDescriptorImpl declaringType; + private final String name; + + private ParameterizedType type; + + private DynamicAnnotationBuilder annotationBuilder; + private Map annotationMap; + + public DynamicAttributeDescriptorImpl( + DynamicTypeDescriptorImpl declaringType, + String name, + ParameterizedType type) { + this.declaringType = declaringType; + this.name = name; + this.type = type; + } + + @Override + public String getName() { + return name; + } + + @Override + public ParameterizedType getType() { + return type; + } + + public void setType(ParameterizedType type) { + if ( this.type != null ) { + throw new IllegalStateException( "Dynamic attribute type already set" ); + } + this.type = type; + } + + @Override + public int getModifiers() { + return Modifier.PUBLIC; + } + + @Override + public JavaTypeDescriptor getDeclaringType() { + return declaringType; + } + + public DynamicAnnotationBuilder getAnnotationBuilder() { + if ( annotationBuilder == null ) { + annotationBuilder = new DynamicAttributeAnnotationBuilder( this ); + } + return annotationBuilder; + } + + @Override + public Map getAnnotations() { + return annotationMap; + } + + @Override + public String toLoggableForm() { + return declaringType.getName().toString() + '#' + name; + } + + @Override + public String toSignatureForm() { + return type.getErasedType().getName().toString() + ' ' + name; + } + + @Override + public String toString() { + return "FieldDescriptorImpl{" + declaringType.getName().toString() + '#' + name + '}'; + } + + private static class DynamicAttributeAnnotationBuilder implements DynamicAnnotationBuilder { + private final DynamicAttributeDescriptorImpl attribute; + + private DynamicAttributeAnnotationBuilder(DynamicAttributeDescriptorImpl attribute) { + this.attribute = attribute; + } + + @Override + public AnnotationInstance makeAnnotation(DotName annotationTypeName, AnnotationValue... values) { + final AnnotationInstance annotationInstance = AnnotationInstance.create( annotationTypeName, attribute, values ); + + attribute.addAnnotation( annotationInstance ); + + return annotationInstance; + } + + @Override + public AnnotationInstance makeAnnotation(DotName annotationTypeName, List values) { + final AnnotationInstance annotationInstance = AnnotationInstance.create( annotationTypeName, attribute, values ); + + attribute.addAnnotation( annotationInstance ); + + return annotationInstance; + } + } + + private void addAnnotation(AnnotationInstance annotationInstance) { + if ( annotationMap == null ) { + annotationMap = new HashMap(); + } + + final AnnotationInstance old = annotationMap.get( annotationInstance.name() ); + if ( old != null ) { + throw new IllegalAnnotationException( + String.format( + Locale.ENGLISH, + "%s already contained a type annotation instance for %s : %s", + toLoggableForm(), + annotationInstance.name().toString(), + old + ) + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicTypeDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicTypeDescriptorImpl.java new file mode 100644 index 000000000000..a91ed5d4aa63 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/DynamicTypeDescriptorImpl.java @@ -0,0 +1,285 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.DynamicAttributeDescriptor; +import org.hibernate.metamodel.reflite.spi.DynamicTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.reflite.spi.ParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Standard implementation of the DynamicTypeDescriptor contract. + * + * @author Steve Ebersole + */ +public class DynamicTypeDescriptorImpl implements DynamicTypeDescriptor, AnnotationTarget { + private final DotName name; + private DynamicTypeDescriptorImpl superType; + private DynamicAnnotationBuilder annotationBuilder; + + private Collection attributes; + + private Map typeAnnotationMap; + private Map> classAnnotationMap; + + public DynamicTypeDescriptorImpl(DotName name, DynamicTypeDescriptorImpl superType) { + this.name = name; + this.superType = superType; + } + + public void setSuperType(DynamicTypeDescriptorImpl superType) { + if ( this.superType != null ) { + throw new IllegalStateException( "Dynamic type super-type already set" ); + } + this.superType = superType; + } + + /** + * Makes (and returns) a member definition as declared on this dynamic type. + * + * @param name The name of the member + * @param type The member type + */ + public DynamicAttributeDescriptor makeAttribute(String name, JavaTypeDescriptor type) { + return makeAttribute( + name, + new ParameterizedTypeImpl( type, Collections.emptyList() ) + ); + } + + /** + * Makes (and returns) a member definition as declared on this dynamic type. + * + * @param name The name of the member + * @param type The member type + */ + public DynamicAttributeDescriptor makeAttribute(String name, ParameterizedType type) { + if ( attributes == null ) { + attributes = new ArrayList(); + } + + final DynamicAttributeDescriptorImpl attributeDescriptor = new DynamicAttributeDescriptorImpl( this, name, type ); + attributes.add( attributeDescriptor ); + + return attributeDescriptor; + } + + public DynamicAnnotationBuilder getAnnotationBuilder() { + if ( annotationBuilder == null ) { + annotationBuilder = new DynamicTypeAnnotationBuilder( this ); + } + return annotationBuilder; + } + + @Override + public DynamicTypeDescriptorImpl getSuperType() { + return superType; + } + + @Override + public Collection getDeclaredAttributes() { + return attributes == null ? Collections.emptyList() : attributes; + } + + @Override + public DotName getName() { + return name; + } + + @Override + public int getModifiers() { + return Modifier.PUBLIC; + } + + @Override + public Collection getDeclaredFields() { + return Collections.emptyList(); + } + + @Override + public Collection getDeclaredMethods() { + return Collections.emptyList(); + } + + @Override + public List getResolvedParameterTypes() { + return Collections.emptyList(); + } + + @Override + public ClassInfo getJandexClassInfo() { + throw new UnsupportedOperationException( + "Illegal attempt to get Jandex ClassInfo from DynamicTypeDescriptor" + ); + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + final AnnotationInstance localTypeAnnotation = findLocalTypeAnnotation( annotationType ); + if ( localTypeAnnotation != null ) { + return localTypeAnnotation; + } + + if ( superType != null ) { + return superType.findTypeAnnotation( annotationType ); + } + + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return typeAnnotationMap.get( annotationType ); + } + + @Override + public Collection findAnnotations(DotName annotationType) { + final List annotationInstances = new ArrayList(); + + annotationInstances.addAll( findLocalAnnotations( annotationType ) ); + + if ( superType != null ) { + annotationInstances.addAll( superType.findAnnotations( annotationType ) ); + } + + return annotationInstances; + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + final Collection them = classAnnotationMap.get( annotationType ); + return them == null ? Collections.emptyList() : them; + } + + private static class DynamicTypeAnnotationBuilder implements DynamicAnnotationBuilder { + private final DynamicTypeDescriptorImpl type; + + private DynamicTypeAnnotationBuilder(DynamicTypeDescriptorImpl type) { + this.type = type; + } + + @Override + public AnnotationInstance makeAnnotation(DotName annotationTypeName, AnnotationValue... values) { + final AnnotationInstance annotationInstance = AnnotationInstance.create( annotationTypeName, type, values ); + return registerAnnotation( annotationInstance ); + } + + private AnnotationInstance registerAnnotation(AnnotationInstance annotationInstance) { + type.addTypeAnnotation( annotationInstance ); + type.addClassAnnotation( annotationInstance ); + + return annotationInstance; + } + + @Override + public AnnotationInstance makeAnnotation(DotName annotationTypeName, List values) { + final AnnotationInstance annotationInstance = AnnotationInstance.create( annotationTypeName, type, values ); + return registerAnnotation( annotationInstance ); + } + } + + void addClassAnnotation(AnnotationInstance annotationInstance) { + Collection annotationInstances; + if ( classAnnotationMap == null ) { + classAnnotationMap = new HashMap>(); + annotationInstances = new ArrayList(); + classAnnotationMap.put( annotationInstance.name(), annotationInstances ); + } + else { + annotationInstances = classAnnotationMap.get( annotationInstance.name() ); + if ( annotationInstances == null ) { + annotationInstances = new ArrayList(); + classAnnotationMap.put( annotationInstance.name(), annotationInstances ); + } + } + annotationInstances.add( annotationInstance ); + } + + private void addTypeAnnotation(AnnotationInstance annotationInstance) { + if ( typeAnnotationMap == null ) { + typeAnnotationMap = new HashMap(); + } + + final AnnotationInstance old = typeAnnotationMap.put( annotationInstance.name(), annotationInstance ); + if ( old != null ) { + throw new IllegalAnnotationException( + String.format( + Locale.ENGLISH, + "%s already contained a type annotation instance for %s : %s", + getName().toString(), + annotationInstance.name().toString(), + old + ) + ); + } + } + + + @Override + public boolean isAssignableFrom(JavaTypeDescriptor check) { + if ( check == null ) { + throw new IllegalArgumentException( "Descriptor to check cannot be null" ); + } + + if ( equals( check ) ) { + return true; + } + + //noinspection SimplifiableIfStatement + if ( DynamicTypeDescriptorImpl.class.isInstance( check ) ) { + return ( (DynamicTypeDescriptorImpl) check ).isAssignableTo( this ); + } + + return false; + } + + public boolean isAssignableTo(DynamicTypeDescriptorImpl check) { + if ( check.equals( superType ) ) { + return true; + } + + if ( superType.isAssignableTo( check ) ) { + return true; + } + + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/FieldDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/FieldDescriptorImpl.java new file mode 100644 index 000000000000..16e8f1648e43 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/FieldDescriptorImpl.java @@ -0,0 +1,102 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.Collections; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.ParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public class FieldDescriptorImpl implements FieldDescriptor { + private final String name; + private final ParameterizedType fieldType; + + private final int modifiers; + + private final JavaTypeDescriptor declaringType; + private final Map annotationMap; + + public FieldDescriptorImpl( + String name, + ParameterizedType fieldType, + int modifiers, + JavaTypeDescriptor declaringType, + Map annotationMap) { + this.name = name; + this.fieldType = fieldType; + this.modifiers = modifiers; + this.declaringType = declaringType; + this.annotationMap = annotationMap != null + ? annotationMap + : Collections.emptyMap(); + } + + @Override + public String getName() { + return name; + } + + @Override + public ParameterizedType getType() { + return fieldType; + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public JavaTypeDescriptor getDeclaringType() { + return declaringType; + } + + @Override + public Map getAnnotations() { + return annotationMap; + } + + @Override + public String toLoggableForm() { + return declaringType.getName().toString() + '#' + name; + } + + @Override + public String toSignatureForm() { + return fieldType.getErasedType().getName().toString() + ' ' + name; + } + + @Override + public String toString() { + return "FieldDescriptorImpl{" + declaringType.getName().toString() + '#' + name + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/IllegalAnnotationException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/IllegalAnnotationException.java new file mode 100644 index 000000000000..86bcd7bb2aac --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/IllegalAnnotationException.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import org.hibernate.HibernateException; + +/** + * Indicates some kind of illegality for an annotation + * + * @author Steve Ebersole + */ +public class IllegalAnnotationException extends HibernateException { + public IllegalAnnotationException(String message) { + super( message ); + } + + public IllegalAnnotationException(String message, Throwable cause) { + super( message, cause ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/InterfaceDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/InterfaceDescriptorImpl.java new file mode 100644 index 000000000000..47fca9574cce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/InterfaceDescriptorImpl.java @@ -0,0 +1,194 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public class InterfaceDescriptorImpl extends InternalJavaTypeDescriptor implements InterfaceDescriptor { + private final ClassInfo classInfo; + private final int modifiers; + private final Map typeAnnotationMap; + private final Map> annotationMap; + + private Collection extendedInterfaceTypes; + + private Collection fields; + private Collection methods; + private List typeParameters; + + public InterfaceDescriptorImpl( + ClassInfo classInfo, + int modifiers, + Map typeAnnotationMap, + Map> annotationMap) { + this.classInfo = classInfo; + this.modifiers = modifiers; + this.typeAnnotationMap = typeAnnotationMap != null + ? typeAnnotationMap + : Collections.emptyMap(); + this.annotationMap = annotationMap != null + ? annotationMap + : Collections.>emptyMap(); + } + + @Override + public DotName getName() { + return classInfo.name(); + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public Collection getExtendedInterfaceTypes() { + return extendedInterfaceTypes; + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + final AnnotationInstance localTypeAnnotation = findLocalTypeAnnotation( annotationType ); + if ( localTypeAnnotation != null ) { + return localTypeAnnotation; + } + + for ( InterfaceDescriptor extended : extendedInterfaceTypes ) { + final AnnotationInstance annotationInstance = extended.findTypeAnnotation( annotationType ); + if ( annotationInstance != null ) { + return annotationInstance; + } + } + + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return typeAnnotationMap.get( annotationType ); + } + + @Override + public Collection findAnnotations(DotName annotationType) { + final List annotationInstances = new ArrayList(); + annotationInstances.addAll( findLocalAnnotations( annotationType ) ); + + for ( InterfaceDescriptor extended : extendedInterfaceTypes ) { + annotationInstances.addAll( extended.findAnnotations( annotationType ) ); + } + + return annotationInstances; + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + final Collection them = annotationMap.get( annotationType ); + return them == null ? Collections.emptyList() : them; + } + + @Override + public Collection getDeclaredFields() { + return fields == null ? Collections.emptyList() : fields; + } + + @Override + public Collection getDeclaredMethods() { + return methods == null ? Collections.emptyList() : methods; + } + + @Override + public String toString() { + return "InterfaceDescriptorImpl{" + getName().toString() + '}'; + } + + void setExtendedInterfaceTypes(Collection extendedInterfaceTypes) { + this.extendedInterfaceTypes = extendedInterfaceTypes; + } + + void setFields(Collection fields) { + this.fields = fields; + } + + void setMethods(Collection methods) { + this.methods = methods; + } + + public List getResolvedParameterTypes() { + return typeParameters; + } + + @Override + public ClassInfo getJandexClassInfo() { + return classInfo; + } + + public void setTypeParameters(List typeParameters) { + this.typeParameters = typeParameters; + } + + @Override + public ClassDescriptor getSuperclass() { + return null; + } + + @Override + public Collection getInterfaces() { + return getExtendedInterfaceTypes(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final InterfaceDescriptorImpl that = (InterfaceDescriptorImpl) o; + return this.getName().equals( that.getName() ); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/InternalJavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/InternalJavaTypeDescriptor.java new file mode 100644 index 000000000000..dd49a7dbe349 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/InternalJavaTypeDescriptor.java @@ -0,0 +1,84 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.Collection; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * @author Steve Ebersole + */ +public abstract class InternalJavaTypeDescriptor implements JavaTypeDescriptor { + public abstract ClassDescriptor getSuperclass(); + public abstract Collection getInterfaces(); + + @Override + public boolean isAssignableFrom(JavaTypeDescriptor check) { + if ( check == null ) { + throw new IllegalArgumentException( "Descriptor to check cannot be null" ); + } + + if ( equals( check ) ) { + return true; + } + + //noinspection SimplifiableIfStatement + if ( InternalJavaTypeDescriptor.class.isInstance( check ) ) { + return ( (InternalJavaTypeDescriptor) check ).isAssignableTo( this ); + } + + return false; + } + + public boolean isAssignableTo(InternalJavaTypeDescriptor check) { + ClassDescriptor superClass = getSuperclass(); + if ( check.equals( superClass ) ) { + return true; + } + if ( superClass instanceof InternalJavaTypeDescriptor ) { + if ( ( (InternalJavaTypeDescriptor) superClass ).isAssignableTo( check ) ) { + return true; + } + } + + final Collection interfaces = getInterfaces(); + if ( interfaces != null ) { + for ( InterfaceDescriptor interfaceDescriptor : interfaces ) { + if ( check.equals( interfaceDescriptor ) ) { + return true; + } + if ( interfaceDescriptor instanceof InternalJavaTypeDescriptor ) { + if ( ( (InternalJavaTypeDescriptor) interfaceDescriptor ).isAssignableTo( check ) ) { + return true; + } + } + } + } + + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/JavaTypeDescriptorRepositoryImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/JavaTypeDescriptorRepositoryImpl.java new file mode 100644 index 000000000000..9c15496315ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/JavaTypeDescriptorRepositoryImpl.java @@ -0,0 +1,726 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.DynamicTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.InterfaceDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.reflite.spi.ParameterizedType; +import org.hibernate.metamodel.reflite.spi.PrimitiveTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.VoidDescriptor; +import org.hibernate.metamodel.source.internal.annotations.JandexAccessImpl; +import org.hibernate.metamodel.spi.ClassLoaderAccess; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.MethodParameterInfo; +import org.jboss.logging.Logger; + +import com.fasterxml.classmate.MemberResolver; +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.ResolvedTypeWithMembers; +import com.fasterxml.classmate.TypeResolver; +import com.fasterxml.classmate.members.ResolvedField; +import com.fasterxml.classmate.members.ResolvedMember; +import com.fasterxml.classmate.members.ResolvedMethod; + +/** + * This is the "interim" implementation of JavaTypeDescriptorRepository that loads Classes to ascertain this + * information. Ultimately the goal is to hand this responsibility off to Jandex once + * (if) it exposes these capabilities. + * + * @author Steve Ebersole + */ +public class JavaTypeDescriptorRepositoryImpl implements JavaTypeDescriptorRepository { + private static final Logger log = Logger.getLogger( JavaTypeDescriptorRepositoryImpl.class ); + + private final JandexAccessImpl jandexAccess; + private final ClassLoaderAccess classLoaderAccess; + + private final TypeResolver classmateTypeResolver; + private final MemberResolver classmateMemberResolver; + + private Map typeDescriptorMap = new HashMap(); + + private final InterfaceDescriptor jdkCollectionDescriptor; + private final InterfaceDescriptor jdkListDescriptor; + private final InterfaceDescriptor jdkSetDescriptor; + private final InterfaceDescriptor jdkMapDescriptor; + + public JavaTypeDescriptorRepositoryImpl( + JandexAccessImpl jandexAccess, + ClassLoaderAccess classLoaderAccess) { + this.jandexAccess = jandexAccess; + this.classLoaderAccess = classLoaderAccess; + + this.classmateTypeResolver = new TypeResolver(); + this.classmateMemberResolver = new MemberResolver( classmateTypeResolver ); + + this.jdkCollectionDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( Collection.class.getName() ) ); + this.jdkListDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( List.class.getName() ) ); + this.jdkSetDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( Set.class.getName() ) ); + this.jdkMapDescriptor = (InterfaceDescriptor) getType( DotName.createSimple( Map.class.getName() ) ); + } + + @Override + public DotName buildName(String name) { + return DotName.createSimple( name ); + } + + @Override + public DynamicTypeDescriptor makeDynamicType(DotName typeName, DynamicTypeDescriptor superType) { + final JavaTypeDescriptor existingRegistration = typeDescriptorMap.get( typeName ); + if ( existingRegistration != null ) { + if ( !DynamicTypeDescriptor.class.isInstance( existingRegistration ) ) { + throw new IllegalArgumentException( + String.format( + Locale.ENGLISH, + "Found existing type descriptor for given type name [%s], " + + "but it was not a dynamic type : %s", + typeName, + existingRegistration + ) + ); + } + + final DynamicTypeDescriptor existingDynamicTypeDescriptor = (DynamicTypeDescriptor) existingRegistration; + if ( existingDynamicTypeDescriptor.getSuperType() != null ) { + if ( !existingDynamicTypeDescriptor.getSuperType().equals( superType ) ) { + throw new IllegalArgumentException( + String.format( + Locale.ENGLISH, + "Found existing type descriptor for given type name [%s], " + + "but it had mismatched super-type; expecting : %s, found : %s", + typeName, + superType, + existingDynamicTypeDescriptor.getSuperType() + ) + ); + } + } + else { + ( (DynamicTypeDescriptorImpl) existingDynamicTypeDescriptor ).setSuperType( (DynamicTypeDescriptorImpl) superType ); + } + + return existingDynamicTypeDescriptor; + } + + DynamicTypeDescriptor type = new DynamicTypeDescriptorImpl( typeName, (DynamicTypeDescriptorImpl) superType ); + typeDescriptorMap.put( typeName, type ); + return type; + } + + @Override + public JavaTypeDescriptor getType(DotName typeName) { + final String typeNameString = typeName.toString(); + if ( "void".equals( typeNameString ) ) { + return VoidDescriptor.INSTANCE; + } + + if ( typeNameString.startsWith( "[" ) ) { + return decipherArrayTypeRequest( typeNameString ); + } + + JavaTypeDescriptor descriptor = typeDescriptorMap.get( typeName ); + if ( descriptor == null ) { + descriptor = Primitives.resolveByName( typeName ); + } + + if ( descriptor == null ) { + descriptor = makeTypeDescriptor( typeName ); + typeDescriptorMap.put( typeName, descriptor ); + } + + return descriptor; + } + + private JavaTypeDescriptor decipherArrayTypeRequest(String typeNameString) { + final String componentTypeNameString = typeNameString.substring( 1 ); + final JavaTypeDescriptor componentType = resolveArrayComponent( componentTypeNameString ); + if ( componentType == null ) { + throw new IllegalArgumentException( + "Could not interpret requested array component to descriptor : " + typeNameString + ); + } + + return new ArrayDescriptorImpl( + DotName.createSimple( typeNameString ), + Modifier.PUBLIC, + componentType + ); + } + + private JavaTypeDescriptor resolveArrayComponent(String componentTypeName) { + if ( componentTypeName.startsWith( "[" ) ) { + // the component itself is an array (multiple dimension array) + return decipherArrayTypeRequest( componentTypeName ); + } + + final char arrayComponentCode = componentTypeName.charAt( 0 ); + if ( arrayComponentCode == 'L' ) { + // the array component is an object.. we need to strip + // off the leading 'L' and the trailing ';' and resolve + // the component descriptor + final String componentClassName = componentTypeName.substring( 1, componentTypeName.length() - 1 ); + return getType( DotName.createSimple( componentClassName ) ); + } + else { + // should indicate we have a primitive array + // ask the Primitives class to help us decipher it + return Primitives.decipherArrayComponentCode( arrayComponentCode ); + } + } + + @Override + public ArrayDescriptor arrayType(JavaTypeDescriptor componentType) { + if ( PrimitiveTypeDescriptor.class.isInstance( componentType ) ) { + return Primitives.primitiveArrayDescriptor( (PrimitiveTypeDescriptor) componentType ); + } + + final String componentTypeName = componentType.getName().toString(); + final String arrayTypeName; + if ( ArrayDescriptor.class.isInstance( componentType ) ) { + arrayTypeName = '[' + componentTypeName; + } + else { + arrayTypeName = "[L" + componentTypeName + ';'; + } + return new ArrayDescriptorImpl( + DotName.createSimple( arrayTypeName ), + Modifier.PUBLIC, + componentType + ); + } + + @Override + public InterfaceDescriptor jdkCollectionDescriptor() { + return jdkCollectionDescriptor; + } + + @Override + public InterfaceDescriptor jdkListDescriptor() { + return jdkListDescriptor; + } + + @Override + public InterfaceDescriptor jdkSetDescriptor() { + return jdkSetDescriptor; + } + + @Override + public InterfaceDescriptor jdkMapDescriptor() { + return jdkMapDescriptor; + } + + protected JavaTypeDescriptor makeTypeDescriptor(DotName typeName) { + final String classNameToLoad = typeName.toString(); + try { + return makeTypeDescriptor( typeName, classLoaderAccess.classForName( classNameToLoad ) ); + } + catch (ClassLoadingException e) { + // assume a dynamic type + log.debugf( "Creating an implicit DynamicTypeDescriptor : %s", typeName ); + return new DynamicTypeDescriptorImpl( typeName, null ); + } + } + + private JavaTypeDescriptor makeTypeDescriptor(DotName typeName, Class clazz) { + final JandexPivot jandexPivot = pivotAnnotations( typeName ); + + if ( clazz.isInterface() ) { + final InterfaceDescriptorImpl typeDescriptor = new InterfaceDescriptorImpl( + jandexPivot.classInfo, + clazz.getModifiers(), + jandexPivot.typeAnnotations, + jandexPivot.allAnnotations + ); + typeDescriptorMap.put( typeName, typeDescriptor ); + + typeDescriptor.setExtendedInterfaceTypes( extractInterfaces( clazz ) ); + + final ResolvedType resolvedType = classmateTypeResolver.resolve( clazz ); + typeDescriptor.setTypeParameters( extractTypeParameters( resolvedType ) ); + final ResolvedTypeWithMembers resolvedTypeWithMembers = classmateMemberResolver.resolve( resolvedType, null, null ); + + //interface fields would need to be static, and we don't care about static fields + //we exclude the statics in extractFields but why even bother iterating them as here + //we will exclude them all + //typeDescriptor.setFields( extractFields( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) ); + typeDescriptor.setMethods( extractMethods( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) ); + + + return typeDescriptor; + } + else { + final ClassDescriptorImpl typeDescriptor = new ClassDescriptorImpl( + jandexPivot.classInfo, + clazz.getModifiers(), + hasDefaultCtor( clazz ), + jandexPivot.typeAnnotations, + jandexPivot.allAnnotations + ); + typeDescriptorMap.put( typeName, typeDescriptor ); + + typeDescriptor.setSuperType( extractSuper( clazz ) ); + typeDescriptor.setInterfaces( extractInterfaces( clazz ) ); + + if ( !Object.class.equals( clazz ) ) { + final ResolvedType resolvedType = classmateTypeResolver.resolve( clazz ); + typeDescriptor.setTypeParameters( extractTypeParameters( resolvedType ) ); + final ResolvedTypeWithMembers resolvedTypeWithMembers = classmateMemberResolver.resolve( resolvedType, null, null ); + + typeDescriptor.setFields( extractFields( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) ); + typeDescriptor.setMethods( extractMethods( clazz, typeDescriptor, jandexPivot, resolvedTypeWithMembers ) ); + } + + return typeDescriptor; + } + } + + private List extractTypeParameters(ResolvedType resolvedType) { + if ( resolvedType.getTypeParameters().isEmpty() ) { + return Collections.emptyList(); + } + + final List result = CollectionHelper.arrayList( resolvedType.getTypeParameters().size() ); + for ( ResolvedType typeParameter : resolvedType.getTypeParameters() ) { + result.add( getType( buildName( typeParameter.getErasedSignature() ) ) ); + } + return result; + } + + private static final JandexPivot NO_JANDEX_PIVOT = new JandexPivot( null ); + + private JandexPivot pivotAnnotations(DotName typeName) { + if ( jandexAccess.getIndex() == null ) { + return NO_JANDEX_PIVOT; + } + + final ClassInfo jandexClassInfo = jandexAccess.getIndex().getClassByName( typeName ); + if ( jandexClassInfo == null ) { + return new JandexPivot( + ClassInfo.create( + typeName, + null, + (short)0, + new DotName[0], + Collections.>emptyMap() + ) + ); + } + + final Map> annotations = jandexClassInfo.annotations(); + final JandexPivot pivot = new JandexPivot( jandexClassInfo ); + for ( Map.Entry> annotationInstances : annotations.entrySet() ) { + for ( AnnotationInstance annotationInstance : annotationInstances.getValue() ) { + if ( MethodParameterInfo.class.isInstance( annotationInstance.target() ) ) { + continue; + } + + if ( FieldInfo.class.isInstance( annotationInstance.target() ) ) { + final FieldInfo fieldInfo = (FieldInfo) annotationInstance.target(); + Map fieldAnnotations = pivot.fieldAnnotations.get( fieldInfo.name() ); + if ( fieldAnnotations == null ) { + fieldAnnotations = new HashMap(); + pivot.fieldAnnotations.put( fieldInfo.name(), fieldAnnotations ); + fieldAnnotations.put( annotationInstance.name(), annotationInstance ); + } + else { + final Object oldEntry = fieldAnnotations.put( annotationInstance.name(), annotationInstance ); + if ( oldEntry != null ) { + log.debugf( + "Encountered duplicate annotation [%s] on field [%s]", + annotationInstance.name(), + fieldInfo.name() + ); + } + } + } + else if ( MethodInfo.class.isInstance( annotationInstance.target() ) ) { + final MethodInfo methodInfo = (MethodInfo) annotationInstance.target(); + final String methodKey = buildBuildKey( methodInfo ); + Map methodAnnotations = pivot.methodAnnotations.get( methodKey ); + if ( methodAnnotations == null ) { + methodAnnotations = new HashMap(); + pivot.methodAnnotations.put( methodKey, methodAnnotations ); + methodAnnotations.put( annotationInstance.name(), annotationInstance ); + } + else { + final Object oldEntry = methodAnnotations.put( annotationInstance.name(), annotationInstance ); + if ( oldEntry != null ) { + log.debugf( + "Encountered duplicate annotation [%s] on method [%s -> %s]", + annotationInstance.name(), + jandexClassInfo.name(), + methodKey + ); + } + } + } + else if ( ClassInfo.class.isInstance( annotationInstance.target() ) ) { + // todo : validate its the type we are processing? + final Object oldEntry = pivot.typeAnnotations.put( annotationInstance.name(), annotationInstance ); + if ( oldEntry != null ) { + log.debugf( + "Encountered duplicate annotation [%s] on type [%s]", + annotationInstance.name(), + jandexClassInfo.name() + ); + } + } + } + } + + return pivot; + } + + private String buildBuildKey(MethodInfo methodInfo) { + final StringBuilder buff = new StringBuilder(); + buff.append( methodInfo.returnType().toString() ) + .append( ' ' ) + .append( methodInfo.name() ) + .append( '(' ); + for ( int i = 0; i < methodInfo.args().length; i++ ) { + if ( i > 0 ) { + buff.append( ',' ); + } + buff.append( methodInfo.args()[i].toString() ); + } + + return buff.append( ')' ).toString(); + } + + private ClassDescriptor extractSuper(Class clazz) { + final Class superclass = clazz.getSuperclass(); + if ( superclass == null ) { + return null; + } + + return (ClassDescriptor) getType( buildName( superclass.getName() ) ); + } + + private Collection extractInterfaces(Class clazz) { + final Class[] interfaces = clazz.getInterfaces(); + if ( interfaces == null || interfaces.length <= 0 ) { + return Collections.emptyList(); + } + + final Collection interfaceTypes = CollectionHelper.arrayList( interfaces.length ); + for ( Class anInterface : interfaces ) { + interfaceTypes.add( (InterfaceDescriptor) getType( buildName( anInterface.getName() ) ) ); + } + return interfaceTypes; + } + + private Collection extractFields( + Class clazz, + JavaTypeDescriptor declaringType, + JandexPivot jandexPivot, + ResolvedTypeWithMembers resolvedTypeWithMembers) { + final Field[] declaredFields = clazz.getDeclaredFields(); + final Field[] fields = clazz.getFields(); + + if ( declaredFields.length <= 0 && fields.length <= 0 ) { + return Collections.emptyList(); + } + + final ResolvedField[] resolvedFields = resolvedTypeWithMembers.getMemberFields(); + final List fieldDescriptors = CollectionHelper.arrayList( fields.length ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // first, extract declared fields + for ( Field field : declaredFields ) { + if ( Modifier.isStatic( field.getModifiers() ) ) { + continue; + } + fieldDescriptors.add( + new FieldDescriptorImpl( + field.getName(), + makeParameterizedType( + toTypeDescriptor( field.getType() ), + findResolvedFieldInfo( field, resolvedFields ) + ), + field.getModifiers(), + declaringType, + jandexPivot.fieldAnnotations.get( field.getName() ) + ) + ); + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // then, extract all fields +// for ( Field field : fields ) { +// if ( clazz.equals( field.getDeclaringClass() ) ) { +// // skip declared fields, since we already processed them above +// continue; +// } +// +// if ( Modifier.isStatic( field.getModifiers() ) ) { +// continue; +// } +// +// final JavaTypeDescriptor fieldDeclarer = getType( buildName( field.getDeclaringClass().getName() ) ); +// fieldDescriptors.add( +// new FieldDescriptorImpl( +// field.getName(), +// makeParameterizedType( +// toTypeDescriptor( field.getType() ), +// findResolvedFieldInfo( field, resolvedFields ) +// ), +// field.getModifiers(), +// fieldDeclarer, +// jandexPivot.fieldAnnotations.get( field.getName() ) +// ) +// ); +// } + return fieldDescriptors; + } + + private ResolvedField findResolvedFieldInfo(Field field, ResolvedField[] resolvedFields) { + for ( ResolvedField resolvedField : resolvedFields ) { + if ( resolvedField.getName().equals( field.getName() ) ) { + return resolvedField; + } + } +// throw new AssertionFailure( +// String.format( +// "Unable to resolve type information of field : %s", +// field.toGenericString() +// ) +// ); + return null; + } + + private ParameterizedType makeParameterizedType( + JavaTypeDescriptor erasedTypeDescriptor, + ResolvedMember resolvedMember) { + if ( resolvedMember == null + || resolvedMember.getType() == null ) { + return new ParameterizedTypeImpl( + erasedTypeDescriptor, + Collections.emptyList() + ); + } + + List classmateResolvedTypes = resolvedMember.getType().getTypeParameters(); + if ( classmateResolvedTypes.isEmpty() ) { + return new ParameterizedTypeImpl( erasedTypeDescriptor, Collections.emptyList() ); + } + + List resolvedTypeDescriptors = new ArrayList(); + for ( ResolvedType classmateResolvedType : classmateResolvedTypes ) { + resolvedTypeDescriptors.add( + toTypeDescriptor( classmateResolvedType.getErasedType() ) + ); + } + return new ParameterizedTypeImpl( erasedTypeDescriptor, resolvedTypeDescriptors ); + } + + + private JavaTypeDescriptor toTypeDescriptor(Class clazz) { + final JavaTypeDescriptor fieldTypeDescriptor; + if ( clazz.isArray() ) { + fieldTypeDescriptor = arrayOfType( clazz.getComponentType() ); + } + else { + fieldTypeDescriptor = getType( buildName( clazz.getName() ) ); + } + return fieldTypeDescriptor; + } + + private JavaTypeDescriptor arrayOfType(Class type) { + if ( type.isArray() ) { + return new ArrayDescriptorImpl( + buildName( "[" + type.getName() ), + type.getModifiers(), + arrayOfType( type.getComponentType() ) + ); + } + + if ( type.isPrimitive() ) { + return Primitives.primitiveArrayDescriptor( type ); + } + else { + return new ArrayDescriptorImpl( + buildName( "[L" + type.getName() + ";" ), + type.getModifiers(), + getType( buildName( type.getName() ) ) + ); + } + } + + private Collection extractMethods( + Class clazz, + JavaTypeDescriptor declaringType, + JandexPivot jandexPivot, + ResolvedTypeWithMembers resolvedTypeWithMembers) { + final Method[] declaredMethods = clazz.getDeclaredMethods(); + final Method[] methods = clazz.getMethods(); + + if ( declaredMethods.length <= 0 && methods.length <= 0 ) { + return Collections.emptyList(); + } + + final ResolvedMethod[] resolvedMethods = resolvedTypeWithMembers.getMemberMethods(); + final List methodDescriptors = CollectionHelper.arrayList( methods.length ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // first, extract declared methods + for ( Method method : declaredMethods ) { + if ( Modifier.isStatic( method.getModifiers() ) ) { + continue; + } + methodDescriptors.add( fromMethod( method, declaringType, jandexPivot, resolvedMethods ) ); + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // then, extract all methods +// for ( Method method : methods ) { +// if ( clazz.equals( method.getDeclaringClass() ) ) { +// // skip declared methods, since we already processed them above +// continue; +// } +// if ( Modifier.isStatic( method.getModifiers() ) ) { +// continue; +// } +// +// final JavaTypeDescriptor methodDeclarer = getType( buildName( method.getDeclaringClass().getName() ) ); +// methodDescriptors.add( fromMethod( method, methodDeclarer, jandexPivot, resolvedMethods ) ); +// } + + return methodDescriptors; + } + + private MethodDescriptor fromMethod( + Method method, + JavaTypeDescriptor declaringType, + JandexPivot jandexPivot, + ResolvedMethod[] resolvedMethods) { + final Class[] parameterTypes = method.getParameterTypes(); + final Collection argumentTypes; + if ( parameterTypes.length == 0 ) { + argumentTypes = Collections.emptyList(); + } + else { + argumentTypes = CollectionHelper.arrayList( parameterTypes.length ); + for ( Class parameterType : parameterTypes ) { + argumentTypes.add( toTypeDescriptor( parameterType ) ); + } + } + + return new MethodDescriptorImpl( + method.getName(), + declaringType, + method.getModifiers(), + makeParameterizedType( + toTypeDescriptor( method.getReturnType() ), + findResolvedMethodInfo( method, resolvedMethods ) + ), + argumentTypes, + jandexPivot.methodAnnotations.get( buildMethodAnnotationsKey( method ) ) + ); + } + + private ResolvedMethod findResolvedMethodInfo(Method method, ResolvedMethod[] resolvedMethods) { + for ( ResolvedMethod resolvedMethod : resolvedMethods ) { + if ( resolvedMethod.getName().equals( method.getName() ) ) { + // todo : we really need to check signatures too + return resolvedMethod; + } + } +// throw new AssertionFailure( +// String.format( +// "Unable to resolve type information of method : %s", +// method.toGenericString() +// ) +// ); + return null; + } + + private String buildMethodAnnotationsKey(Method method) { + StringBuilder buff = new StringBuilder(); + buff.append( method.getReturnType().getName() ) + .append( ' ' ) + .append( method.getName() ) + .append( '(' ); + for ( int i = 0; i < method.getParameterTypes().length; i++ ) { + if ( i > 0 ) { + buff.append( ',' ); + } + buff.append( method.getParameterTypes()[i].getName() ); + } + return buff.append( ')' ).toString(); + } + + + @SuppressWarnings("unchecked") + private static boolean hasDefaultCtor(Class clazz) { + try { + return !clazz.isInterface() && clazz.getConstructor() != null; + } + catch (NoSuchMethodException ignore) { + return false; + } + } + + private static class JandexPivot { + private final ClassInfo classInfo; + + private Map> allAnnotations; + private Map typeAnnotations = new HashMap(); + private Map> fieldAnnotations = new HashMap>(); + private Map> methodAnnotations = new HashMap>(); + + private JandexPivot(ClassInfo classInfo) { + this.classInfo = classInfo; + this.allAnnotations = classInfo == null + ? Collections.>emptyMap() + : classInfo.annotations(); + } + + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/MethodDescriptorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/MethodDescriptorImpl.java new file mode 100644 index 000000000000..54b4277f2c00 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/MethodDescriptorImpl.java @@ -0,0 +1,134 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.reflite.spi.ParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public class MethodDescriptorImpl implements MethodDescriptor { + private final String name; + private final JavaTypeDescriptor declaringType; + private final int modifiers; + private final ParameterizedType returnType; + private final Collection argumentTypes; + private final Map annotationMap; + + public MethodDescriptorImpl( + String name, + JavaTypeDescriptor declaringType, + int modifiers, + ParameterizedType returnType, + Collection argumentTypes, + Map annotationMap) { + this.name = name; + this.declaringType = declaringType; + this.modifiers = modifiers; + this.returnType = returnType; + this.argumentTypes = argumentTypes; + this.annotationMap = annotationMap != null + ? annotationMap + : Collections.emptyMap(); + } + + @Override + public String getName() { + return name; + } + + @Override + public ParameterizedType getType() { + return getReturnType(); + } + + @Override + public JavaTypeDescriptor getDeclaringType() { + return declaringType; + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public ParameterizedType getReturnType() { + return returnType; + } + + @Override + public Collection getArgumentTypes() { + return argumentTypes; + } + + @Override + public Map getAnnotations() { + return annotationMap; + } + + @Override + public String toLoggableForm() { + return declaringType.getName().toString() + '#' + name; + } + + private String signatureForm; + + @Override + public String toSignatureForm() { + if ( signatureForm == null ) { + signatureForm = buildSignatureForm(); + } + return signatureForm; + } + + private String buildSignatureForm() { + StringBuilder sb = new StringBuilder(); + sb.append( returnType.getErasedType().getName().toString() ); + sb.append( ' ' ); + sb.append( name ).append( '(' ); + String delimiter = ""; + for ( JavaTypeDescriptor argumentType : argumentTypes ) { + sb.append( delimiter ); + sb.append( argumentType.getName().toString() ); + delimiter = ", "; + } + sb.append( ')' ); + return sb.toString(); + } + + @Override + public String toString() { + return "MethodDescriptorImpl{" + declaringType.getName().toString() + '#' + name + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ModifierUtils.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ModifierUtils.java new file mode 100644 index 000000000000..ed3d29db34ff --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ModifierUtils.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; + +/** + * Fills-in non-public aspects of the {@link java.lang.reflect.Modifier} class + * + * @author Steve Ebersole + */ +public class ModifierUtils { + + private static final int BRIDGE = 0x00000040; + private static final int ENUM = 0x00004000; + private static final int SYNTHETIC = 0x00001000; + + /** + * Disallow instantiation. This is a utility class, use statically. + */ + private ModifierUtils() { + } + + /** + * Determine if the given method is a bridge. + * + * @param methodDescriptor The method descriptor to check + * + * @return {@code true} if the method is a bridge , {@code false} otherwise. + */ + public static boolean isBridge(MethodDescriptor methodDescriptor) { + return (methodDescriptor.getModifiers() & BRIDGE) != 0; + } + + /** + * Determine if the given Java type is an enum. + * + * @param javaType The descriptor of the Java type to check + * + * @return {@code true} if the Java type is an enum, {@code false} otherwise. + */ + public static boolean isEnum(JavaTypeDescriptor javaType) { + return (javaType.getModifiers() & ENUM) != 0; + } + + /** + * Determine is the given member (field/method) is synthetic + * + * @param memberDescriptor The descriptor for the member to check + * + * @return {@code true} if the member is synthetic, {@code false} otherwise. + */ + public static boolean isSynthetic(MemberDescriptor memberDescriptor) { + return (memberDescriptor.getModifiers() & SYNTHETIC) != 0; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ParameterizedTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ParameterizedTypeImpl.java new file mode 100644 index 000000000000..20e2397ffafb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/ParameterizedTypeImpl.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.List; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.ParameterizedType; + +/** + * Implementation of the ParameterizedType contract + * + * @author Steve Ebersole + */ +public class ParameterizedTypeImpl implements ParameterizedType { + private final JavaTypeDescriptor erasedType; + private final List resolvedParameterTypes; + + public ParameterizedTypeImpl( + JavaTypeDescriptor erasedType, + List resolvedParameterTypes) { + this.erasedType = erasedType; + this.resolvedParameterTypes = resolvedParameterTypes; + } + + @Override + public JavaTypeDescriptor getErasedType() { + return erasedType; + } + + @Override + public List getResolvedParameterTypes() { + return resolvedParameterTypes; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/Primitives.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/Primitives.java new file mode 100644 index 000000000000..03f14f2c3ab0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/internal/Primitives.java @@ -0,0 +1,414 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.reflite.spi.PrimitiveTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.PrimitiveWrapperTypeDescriptor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public class Primitives { + public static class PrimitiveGroup { + private final PrimitiveTypeDescriptor primitiveType; + private final PrimitiveWrapperTypeDescriptor primitiveWrapperType; + + private final ArrayDescriptor primitiveArrayType; + + public PrimitiveGroup(Class primitiveClass, Class primitiveArrayClass, Class wrapperClass) { + assert primitiveClass.isPrimitive(); + assert primitiveArrayClass.isArray(); + assert !wrapperClass.isPrimitive(); + + this.primitiveType = new PrimitiveDescriptorImpl( primitiveClass, this ); + this.primitiveWrapperType = new WrapperDescriptorImpl( wrapperClass, this ); + + this.primitiveArrayType = new ArrayDescriptorImpl( + DotName.createSimple( primitiveArrayClass.getName() ), + primitiveArrayClass.getModifiers(), + this.primitiveType + ); + } + + public PrimitiveTypeDescriptor getPrimitiveType() { + return primitiveType; + } + + public PrimitiveWrapperTypeDescriptor getPrimitiveWrapperType() { + return primitiveWrapperType; + } + + public ArrayDescriptor getPrimitiveArrayType() { + return primitiveArrayType; + } + } + + public static final PrimitiveGroup CHAR = new PrimitiveGroup( char.class, char[].class, Character.class ); + public static final PrimitiveGroup BOOLEAN = new PrimitiveGroup( boolean.class, boolean[].class, Boolean.class ); + public static final PrimitiveGroup BYTE = new PrimitiveGroup( byte.class, byte[].class, Byte.class ); + public static final PrimitiveGroup SHORT = new PrimitiveGroup( short.class, short[].class, Short.class ); + public static final PrimitiveGroup INTEGER = new PrimitiveGroup( int.class, int[].class, Integer.class ); + public static final PrimitiveGroup LONG = new PrimitiveGroup( long.class, long[].class, Long.class ); + public static final PrimitiveGroup FLOAT = new PrimitiveGroup( float.class, float[].class, Float.class ); + public static final PrimitiveGroup DOUBLE = new PrimitiveGroup( double.class, double[].class, Double.class ); + + public static JavaTypeDescriptor resolveByName(DotName name) { + assert name != null; + + final String typeNameString = name.toString(); + + if ( char.class.getName().equals( typeNameString ) ) { + return CHAR.primitiveType; + } + else if ( Character.class.getName().equals( typeNameString ) ) { + return CHAR.primitiveWrapperType; + } + else if ( boolean.class.getName().equals( typeNameString ) ) { + return BOOLEAN.primitiveType; + } + else if ( Boolean.class.getName().equals( typeNameString ) ) { + return BOOLEAN.primitiveWrapperType; + } + else if ( byte.class.getName().equals( typeNameString ) ) { + return BYTE.primitiveType; + } + else if ( Byte.class.getName().equals( typeNameString ) ) { + return BYTE.primitiveWrapperType; + } + else if ( short.class.getName().equals( typeNameString ) ) { + return SHORT.primitiveType; + } + else if ( Short.class.getName().equals( typeNameString ) ) { + return SHORT.primitiveArrayType; + } + else if ( int.class.getName().equals( typeNameString ) ) { + return INTEGER.primitiveType; + } + else if ( Integer.class.getName().equals( typeNameString ) ) { + return INTEGER.primitiveWrapperType; + } + else if ( long.class.getName().equals( typeNameString ) ) { + return LONG.primitiveType; + } + else if ( Long.class.getName().equals( typeNameString ) ) { + return LONG.primitiveWrapperType; + } + else if ( float.class.getName().equals( typeNameString ) ) { + return FLOAT.primitiveType; + } + else if ( Float.class.getName().equals( typeNameString ) ) { + return FLOAT.primitiveWrapperType; + } + else if ( double.class.getName().equals( typeNameString ) ) { + return DOUBLE.primitiveType; + } + else if ( double.class.getName().equals( typeNameString ) ) { + return DOUBLE.primitiveWrapperType; + } + + return null; + } + + public static JavaTypeDescriptor primitiveArrayDescriptor(Class type) { + assert type != null; + assert type.isPrimitive(); + + final String typeNameString = type.getName(); + + if ( char.class.getName().equals( typeNameString ) ) { + return CHAR.primitiveArrayType; + } + else if ( boolean.class.getName().equals( typeNameString ) ) { + return BOOLEAN.primitiveArrayType; + } + else if ( byte.class.getName().equals( typeNameString ) ) { + return BYTE.primitiveArrayType; + } + else if ( short.class.getName().equals( typeNameString ) ) { + return SHORT.primitiveArrayType; + } + else if ( int.class.getName().equals( typeNameString ) ) { + return INTEGER.primitiveArrayType; + } + else if ( long.class.getName().equals( typeNameString ) ) { + return LONG.primitiveArrayType; + } + else if ( float.class.getName().equals( typeNameString ) ) { + return FLOAT.primitiveArrayType; + } + else if ( double.class.getName().equals( typeNameString ) ) { + return DOUBLE.primitiveArrayType; + } + + return null; + } + + public static ArrayDescriptor primitiveArrayDescriptor(PrimitiveTypeDescriptor componentType) { + if ( componentType == null ) { + return null; + } + + return ( (PrimitiveDescriptorImpl) componentType ).group.primitiveArrayType; + } + + public static JavaTypeDescriptor decipherArrayComponentCode(char arrayComponentCode) { + switch ( arrayComponentCode ) { + case 'C': { + return CHAR.primitiveType; + } + case 'Z': { + return BOOLEAN.primitiveType; + } + case 'B': { + return BYTE.primitiveType; + } + case 'S': { + return SHORT.primitiveType; + } + case 'I': { + return INTEGER.primitiveType; + } + case 'J': { + return LONG.primitiveType; + } + case 'F': { + return FLOAT.primitiveType; + } + case 'D': { + return DOUBLE.primitiveType; + } + default: { + throw new IllegalArgumentException( + "Unexpected character passed in as primitive array component code : " + + arrayComponentCode + ); + } + } + } + + public static void main(String... args) { + System.out.println( " char : " + char[].class ); + System.out.println( "boolean : " + boolean[].class ); + System.out.println( " byte : " + byte[].class ); + System.out.println( " short : " + short[].class ); + System.out.println( " int : " + int[].class ); + System.out.println( " long : " + long[].class ); + System.out.println( " float : " + float[].class ); + System.out.println( " double : " + double[].class ); + } + + private static class PrimitiveDescriptorImpl implements PrimitiveTypeDescriptor { + private final Class clazz; + private final DotName name; + private final int modifiers; + private final PrimitiveGroup group; + + protected PrimitiveDescriptorImpl(Class clazz, PrimitiveGroup group) { + this.clazz = clazz; + this.name = DotName.createSimple( clazz.getName() ); + this.modifiers = clazz.getModifiers(); + this.group = group; + } + + @Override + public Class getClassType() { + return clazz; + } + + @Override + public DotName getName() { + return name; + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public Collection getDeclaredFields() { + return Collections.emptyList(); + } + + @Override + public Collection getDeclaredMethods() { + return Collections.emptyList(); + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public Collection findAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public boolean isAssignableFrom(JavaTypeDescriptor check) { + if ( check == null ) { + throw new IllegalArgumentException( "Descriptor to check cannot be null" ); + } + + if ( equals( check ) ) { + return true; + } + +// if ( PrimitiveWrapperTypeDescriptor.class.isInstance( check ) ) { +// final PrimitiveWrapperTypeDescriptor wrapper = (PrimitiveWrapperTypeDescriptor) check; +// if ( equals( wrapper.getPrimitiveTypeDescriptor() ) ) { +// return true; +// } +// } +// + return false; + } + + @Override + public List getResolvedParameterTypes() { + return Collections.emptyList(); + } + + @Override + public ClassInfo getJandexClassInfo() { + return null; + } + + @Override + public PrimitiveWrapperTypeDescriptor getWrapperTypeDescriptor() { + return group.primitiveWrapperType; + } + } + + private static class WrapperDescriptorImpl implements PrimitiveWrapperTypeDescriptor { + private final DotName name; + private final int modifiers; + private final PrimitiveGroup group; + + private WrapperDescriptorImpl(Class clazz, PrimitiveGroup group) { + this.name = DotName.createSimple( clazz.getName() ); + this.modifiers = clazz.getModifiers(); + this.group = group; + } + + @Override + public DotName getName() { + return name; + } + + @Override + public int getModifiers() { + return modifiers; + } + + @Override + public Collection getDeclaredFields() { + return Collections.emptyList(); + } + + @Override + public Collection getDeclaredMethods() { + return Collections.emptyList(); + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public Collection findAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public boolean isAssignableFrom(JavaTypeDescriptor check) { + if ( check == null ) { + throw new IllegalArgumentException( "Descriptor to check cannot be null" ); + } + + if ( equals( check ) ) { + return true; + } + +// if ( PrimitiveTypeDescriptor.class.isInstance( check ) ) { +// final PrimitiveTypeDescriptor primitive = (PrimitiveTypeDescriptor) check; +// if ( equals( primitive.getWrapperTypeDescriptor() ) ) { +// return true; +// } +// } +// + return false; + } + + @Override + public List getResolvedParameterTypes() { + return Collections.emptyList(); + } + + @Override + public ClassInfo getJandexClassInfo() { + return null; + } + + @Override + public PrimitiveTypeDescriptor getPrimitiveTypeDescriptor() { + return group.primitiveType; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ArrayDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ArrayDescriptor.java new file mode 100644 index 000000000000..0915e882b679 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ArrayDescriptor.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +/** + * Describes a java type that represents an array definition. + * + * @author Steve Ebersole + */ +public interface ArrayDescriptor extends JavaTypeDescriptor { + /** + * Obtain the type descriptor for the elements of the array + * + * @return The array element descriptor + */ + public JavaTypeDescriptor getComponentType(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ClassDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ClassDescriptor.java new file mode 100644 index 000000000000..0755ee408b1d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ClassDescriptor.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Collection; + +/** + * Describes a java type that represents a class definition. + * + * @author Steve Ebersole + */ +public interface ClassDescriptor extends JavaTypeDescriptor { + /** + * Did the class define a default (no-arg) constructor? + * + * @return {@code true} indicates the class did have a default (no arg) constructor. + */ + public boolean hasDefaultConstructor(); + + /** + * The super type for this type (if it is a class) + * + * @return The super type + */ + public ClassDescriptor getSuperType(); + + /** + * Get the interfaces implemented by this type + * + * @return The implemented interfaces + */ + public Collection getInterfaceTypes(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/DynamicAttributeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/DynamicAttributeDescriptor.java new file mode 100644 index 000000000000..198f42a9e28a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/DynamicAttributeDescriptor.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +/** + * Support for members in a dynamic (map mode) model. + * + * @author Steve Ebersole + */ +public interface DynamicAttributeDescriptor extends MemberDescriptor { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/DynamicTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/DynamicTypeDescriptor.java new file mode 100644 index 000000000000..212e538b4c01 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/DynamicTypeDescriptor.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Collection; + +/** + * Support for dynamic (map mode) models. + * + * @author Steve Ebersole + */ +public interface DynamicTypeDescriptor extends JavaTypeDescriptor { + /** + * The super type for this type. + * + * @return The super type + */ + public DynamicTypeDescriptor getSuperType(); + + /** + * Get the attributes declared as part of this dynamic model + * + * @return The declared attributes. + */ + public Collection getDeclaredAttributes(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/FieldDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/FieldDescriptor.java new file mode 100644 index 000000000000..3c550edd0c0f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/FieldDescriptor.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +/** + * Describes a field in a java type + * + * @author Steve Ebersole + */ +public interface FieldDescriptor extends MemberDescriptor { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/InterfaceDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/InterfaceDescriptor.java new file mode 100644 index 000000000000..74760f45bcdc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/InterfaceDescriptor.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Collection; + +/** + * Describes a java type that represents an interface definition. + * + * @author Steve Ebersole + */ +public interface InterfaceDescriptor extends JavaTypeDescriptor { + /** + * Get the interfaces extended by this interface + * + * @return The implemented interfaces + */ + public Collection getExtendedInterfaceTypes(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/JavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/JavaTypeDescriptor.java new file mode 100644 index 000000000000..b7e246ce0161 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/JavaTypeDescriptor.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Collection; +import java.util.List; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Describes information about a Java type. Might (more concretely) be any of:

      + *
    • {@link ClassDescriptor}
    • + *
    • {@link InterfaceDescriptor}
    • + *
    • {@link PrimitiveTypeDescriptor}
    • + *
    • {@link PrimitiveWrapperTypeDescriptor}
    • + *
    • {@link ArrayDescriptor}
    • + *
    • {@link VoidDescriptor}
    • + *
    + * + * @author Steve Ebersole + */ +public interface JavaTypeDescriptor { + /** + * Retrieve the type name + * + * @return The type name + */ + public DotName getName(); + + /** + * Access the type's modifiers. See {@link java.lang.reflect.Modifier} + * + * @return The modifiers + */ + public int getModifiers(); + + /** + * Get all the fields declared by this type. + * + * @return All fields declared by this type + */ + public Collection getDeclaredFields(); + + /** + * Get all the methods declared by this type. + * + * @return All fields declared by this type + */ + public Collection getDeclaredMethods(); + + /** + * Get the resolved type descriptors for any parameterized type arguments defined on the type. + *

    + * For example, given a JavaTypeDescriptor describing a parameterized Java type resolved to + * be {@code List}, this method would return JavaTypeDescriptor for {@code Person} + * + * @return The resolved parameter type descriptors + */ + public List getResolvedParameterTypes(); + + /** + * Get the Jandex ClassInfo object for this type. + * + * @return The annotations. + */ + public ClassInfo getJandexClassInfo(); + + /** + * Get the annotation of the named type, if one, defined on this type + * or any of its super-types + * + * @param annotationType DotName of the type of annotation to find. + * + * @return The annotation. + */ + public AnnotationInstance findTypeAnnotation(DotName annotationType); + + /** + * Get the annotation of the named type, if one, defined on this type. + * + * @param annotationType DotName of the type of annotation to find. + * + * @return The annotation. + */ + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType); + + /** + * Locate all annotations of the given type within the bounds of this type. + * "Within bounds" means on the type itself, on its fields and on its + * methods. + *

    + * This form (as opposed to {@link #findLocalAnnotations}) also checks super + * types. + * + * @param annotationType DotName of the type of annotation to find. + * + * @return The annotations found. + */ + public Collection findAnnotations(DotName annotationType); + + /** + * Locate all annotations of the given type within the bounds of this type. + * "Within bounds" means on the type itself, on its fields and on its + * methods. + * + * @param annotationType DotName of the type of annotation to find. + * + * @return The annotations found. + */ + public Collection findLocalAnnotations(DotName annotationType); + + /** + * Same function as the {@link Class#isAssignableFrom(Class)} method. + * + * @param check The type to be checked + * + * @return the {@code boolean} value indicating whether objects of the + * type {@code cls} can be assigned to references of this type + */ + public boolean isAssignableFrom(JavaTypeDescriptor check); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/JavaTypeDescriptorRepository.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/JavaTypeDescriptorRepository.java new file mode 100644 index 000000000000..37035d8c8c5f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/JavaTypeDescriptorRepository.java @@ -0,0 +1,99 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import org.jboss.jandex.DotName; + +/** + * The repository of reflite JavaTypeDescriptor info. + * + * @author Steve Ebersole + */ +public interface JavaTypeDescriptorRepository { + /** + * Builds a type-safe wrapper around a type/package name + * + * @param name The type/package name to wrap + * + * @return The type-safe wrapper. + */ + public DotName buildName(String name); + + /** + * Obtain the reflite JavaTypeDescriptor for the given name + * + * @param typeName The name of the type for which to obtain the descriptor + * + * @return The descriptor + */ + public JavaTypeDescriptor getType(DotName typeName); + + /** + * Makes a dynamic (map model) type descriptor + * + * @param typeName The type name + * @param superType The type's super-type; can be {@code null} + * + * @return The generated dynamic type (or the existing one) + */ + public DynamicTypeDescriptor makeDynamicType(DotName typeName, DynamicTypeDescriptor superType); + + /** + * Create a reflite JavaTypeDescriptor representing an array of the + * given type + * + * @param componentType The array component (element) type + * + * @return The array descriptor + */ + public ArrayDescriptor arrayType(JavaTypeDescriptor componentType); + + /** + * Convenient access to the descriptor for the JDK {@link java.util.Collection} type + * + * @return The descriptor for the JDK {@link java.util.Collection} type + */ + public InterfaceDescriptor jdkCollectionDescriptor(); + + /** + * Convenient access to the descriptor for the JDK {@link java.util.List} type + * + * @return The descriptor for the JDK {@link java.util.List} type + */ + public InterfaceDescriptor jdkListDescriptor(); + + /** + * Convenient access to the descriptor for the JDK {@link java.util.Set} type + * + * @return The descriptor for the JDK {@link java.util.Set} type + */ + public InterfaceDescriptor jdkSetDescriptor(); + + /** + * Convenient access to the descriptor for the JDK {@link java.util.Map} type + * + * @return The descriptor for the JDK {@link java.util.Map} type + */ + public InterfaceDescriptor jdkMapDescriptor(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/MemberDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/MemberDescriptor.java new file mode 100644 index 000000000000..a542a7d8f6fd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/MemberDescriptor.java @@ -0,0 +1,87 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * Common contract for method and field descriptors. + * + * @author Steve Ebersole + */ +public interface MemberDescriptor { + /** + * The member name + * + * @return The member name + */ + public String getName(); + + /** + * The member type. For fields, this is the field type. For methods, + * this is the method return type. + * + * @return The member type. + */ + public ParameterizedType getType(); + + /** + * Access to the modifiers for the member. + * + * @return The modifiers. + */ + public int getModifiers(); + + /** + * The declaring type + * + * @return The declaring type + */ + public JavaTypeDescriptor getDeclaringType(); + + /** + * Get the annotations defined on this field. + * + * @return The annotations. + */ + public Map getAnnotations(); + + /** + * Get a String representation this member that is usable in logging. In + * general this is in the form {declaringType}#{name} + * + * @return The loggable representation + */ + public String toLoggableForm(); + + /** + * Get the String representation of this members signature. + * + * @return The signature representation + */ + public String toSignatureForm(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/MethodDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/MethodDescriptor.java new file mode 100644 index 000000000000..f0c66537c7bc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/MethodDescriptor.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Collection; + +/** + * Describes a method in a java type + * + * @author Steve Ebersole + */ +public interface MethodDescriptor extends MemberDescriptor { + /** + * The descriptor of the method's return type + * + * @return The descriptor of the method's return type + */ + public ParameterizedType getReturnType(); + + /** + * The descriptor of the method's argument types + * + * @return The descriptor of the method's argument types + */ + public Collection getArgumentTypes(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ParameterizedType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ParameterizedType.java new file mode 100644 index 000000000000..ce108c4957b3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/ParameterizedType.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.List; + +/** + * @author Steve Ebersole + */ +public interface ParameterizedType { + public JavaTypeDescriptor getErasedType(); + public List getResolvedParameterTypes(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/PrimitiveTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/PrimitiveTypeDescriptor.java new file mode 100644 index 000000000000..b13e699f20e9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/PrimitiveTypeDescriptor.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +/** + * Describes the java type for the Java primitive types. + * + * @author Steve Ebersole + */ +public interface PrimitiveTypeDescriptor extends JavaTypeDescriptor { + /** + * The descriptor for the wrapper "equivalent". + * + * @return The descriptor for the wrapper "equivalent". + */ + public PrimitiveWrapperTypeDescriptor getWrapperTypeDescriptor(); + + /** + * Since primitives are ClassLoader safe, allow the Class itself to be available. Needed for ArrayType + * handling, etc. + * + * @return The primitive's Class + */ + public Class getClassType(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/PrimitiveWrapperTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/PrimitiveWrapperTypeDescriptor.java new file mode 100644 index 000000000000..692faa1ebc32 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/PrimitiveWrapperTypeDescriptor.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +/** + * Describes the java type for the Java primitive wrapper types. + * + * @author Steve Ebersole + */ +public interface PrimitiveWrapperTypeDescriptor extends JavaTypeDescriptor { + /** + * The descriptor for the primitive "equivalent". + * + * @return The descriptor for the primitive "equivalent". + */ + public PrimitiveTypeDescriptor getPrimitiveTypeDescriptor(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/VoidDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/VoidDescriptor.java new file mode 100644 index 000000000000..cab9b0ad6cdb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/reflite/spi/VoidDescriptor.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.reflite.spi; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Descriptor for the special java 'void' type. + * + * @author Steve Ebersole + */ +public class VoidDescriptor implements JavaTypeDescriptor { + /** + * Singleton access + */ + public static final VoidDescriptor INSTANCE = new VoidDescriptor(); + + public static final DotName NAME = DotName.createSimple( "void" ); + + @Override + public DotName getName() { + return NAME; + } + + @Override + public int getModifiers() { + return Void.class.getModifiers(); + } + + @Override + public Collection getDeclaredFields() { + return Collections.emptyList(); + } + + @Override + public Collection getDeclaredMethods() { + return Collections.emptyList(); + } + + @Override + public AnnotationInstance findTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public AnnotationInstance findLocalTypeAnnotation(DotName annotationType) { + return null; + } + + @Override + public Collection findAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public Collection findLocalAnnotations(DotName annotationType) { + return Collections.emptyList(); + } + + @Override + public boolean isAssignableFrom(JavaTypeDescriptor check) { + if ( check == null ) { + throw new IllegalArgumentException( "Descriptor to check cannot be null" ); + } + + return equals( check ); + } + + @Override + public List getResolvedParameterTypes() { + return Collections.emptyList(); + } + + @Override + public ClassInfo getJandexClassInfo() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java deleted file mode 100644 index bad9ae1c7408..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.dialect.Dialect; - -/** - * Support for writing {@link Constraint} implementations - * - * @todo do we need to support defining these on particular schemas/catalogs? - * - * @author Steve Ebersole - * @author Gail Badner - */ -public abstract class AbstractConstraint implements Constraint { - private final TableSpecification table; - private final String name; - private List columns = new ArrayList(); - - protected AbstractConstraint(TableSpecification table, String name) { - this.table = table; - this.name = name; - } - - public TableSpecification getTable() { - return table; - } - - public String getName() { - return name; - } - - public Iterable getColumns() { - return columns; - } - - protected int getColumnSpan() { - return columns.size(); - } - - protected List internalColumnAccess() { - return columns; - } - - public void addColumn(Column column) { - internalAddColumn( column ); - } - - protected void internalAddColumn(Column column) { - if ( column.getTable() != getTable() ) { - throw new AssertionFailure( - String.format( - "Unable to add column to constraint; tables [%s, %s] did not match", - column.getTable().toLoggableString(), - getTable().toLoggableString() - ) - ); - } - columns.add( column ); - } - - protected boolean isCreationVetoed(Dialect dialect) { - return false; - } - - protected abstract String sqlConstraintStringInAlterTable(Dialect dialect); - - public String[] sqlDropStrings(Dialect dialect) { - if ( isCreationVetoed( dialect ) ) { - return null; - } - else { - return new String[] { - new StringBuilder() - .append( "alter table " ) - .append( getTable().getQualifiedName( dialect ) ) - .append( " drop constraint " ) - .append( dialect.quote( getName() ) ) - .toString() - }; - } - } - - public String[] sqlCreateStrings(Dialect dialect) { - if ( isCreationVetoed( dialect ) ) { - return null; - } - else { - return new String[] { - new StringBuilder( "alter table " ) - .append( getTable().getQualifiedName( dialect ) ) - .append( sqlConstraintStringInAlterTable( dialect ) ) - .toString() - }; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractSimpleValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractSimpleValue.java deleted file mode 100644 index 8bec29682f57..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractSimpleValue.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.ValidationException; - -import org.jboss.logging.Logger; - -/** - * Basic support for {@link SimpleValue} implementations. - * - * @author Steve Ebersole - */ -public abstract class AbstractSimpleValue implements SimpleValue { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractSimpleValue.class.getName()); - - private final TableSpecification table; - private final int position; - private Datatype datatype; - - protected AbstractSimpleValue(TableSpecification table, int position) { - this.table = table; - this.position = position; - } - - @Override - public TableSpecification getTable() { - return table; - } - - public int getPosition() { - return position; - } - - @Override - public Datatype getDatatype() { - return datatype; - } - - @Override - public void setDatatype(Datatype datatype) { - LOG.debugf( "setting datatype for column %s : %s", toLoggableString(), datatype ); - if ( this.datatype != null && ! this.datatype.equals( datatype ) ) { - LOG.debugf( "overriding previous datatype : %s", this.datatype ); - } - this.datatype = datatype; - } - - @Override - public void validateJdbcTypes(JdbcCodes typeCodes) { - // todo : better compatibility testing... - if ( datatype.getTypeCode() != typeCodes.nextJdbcCde() ) { - throw new ValidationException( "Mismatched types" ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java deleted file mode 100644 index 3165c6b107e6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Convenience base class for implementing the {@link ValueContainer} contract centralizing commonality - * between modeling tables, views and inline views. - * - * @author Steve Ebersole - */ -public abstract class AbstractTableSpecification implements TableSpecification { - private final static AtomicInteger tableCounter = new AtomicInteger( 0 ); - private final int tableNumber; - - private final LinkedHashMap values = new LinkedHashMap(); - - private final PrimaryKey primaryKey = new PrimaryKey( this ); - private final List foreignKeys = new ArrayList(); - - public AbstractTableSpecification() { - this.tableNumber = tableCounter.getAndIncrement(); - } - - @Override - public int getTableNumber() { - return tableNumber; - } - - @Override - public Iterable values() { - return values.values(); - } - - @Override - public Column locateOrCreateColumn(String name) { - if(values.containsKey( name )){ - return (Column) values.get( name ); - } - final Column column = new Column( this, values.size(), name ); - values.put( name, column ); - return column; - } - - @Override - public DerivedValue locateOrCreateDerivedValue(String fragment) { - if(values.containsKey( fragment )){ - return (DerivedValue) values.get( fragment ); - } - final DerivedValue value = new DerivedValue( this, values.size(), fragment ); - values.put( fragment, value ); - return value; - } - - @Override - public Tuple createTuple(String name) { - return new Tuple( this, name ); - } - - @Override - public Iterable getForeignKeys() { - return foreignKeys; - } - - @Override - public ForeignKey createForeignKey(TableSpecification targetTable, String name) { - ForeignKey fk = new ForeignKey( this, targetTable, name ); - foreignKeys.add( fk ); - return fk; - } - - @Override - public PrimaryKey getPrimaryKey() { - return primaryKey; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AuxiliaryDatabaseObject.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AuxiliaryDatabaseObject.java deleted file mode 100644 index 9b0b6dc7704f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AuxiliaryDatabaseObject.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.io.Serializable; - -import org.hibernate.dialect.Dialect; - -/** - * Auxiliary database objects (i.e., triggers, stored procedures, etc) defined - * in the mappings. Allows Hibernate to manage their lifecycle as part of - * creating/dropping the schema. - * - * @author Steve Ebersole - */ -public interface AuxiliaryDatabaseObject extends Exportable, Serializable { - /** - * Does this database object apply to the given dialect? - * - * @param dialect The dialect to check against. - * @return True if this database object does apply to the given dialect. - */ - boolean appliesToDialect(Dialect dialect); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java deleted file mode 100644 index 577712bc4421..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.relational.state.ColumnRelationalState; - -/** - * Models a physical column - * - * @author Gavin King - * @author Steve Ebersole - */ -public class Column extends AbstractSimpleValue { - private final Identifier columnName; - private boolean nullable; - private boolean unique; - - private String defaultValue; - private String checkCondition; - private String sqlType; - - private String readFragment; - private String writeFragment; - - private String comment; - - private Size size = new Size(); - - protected Column(TableSpecification table, int position, String name) { - this( table, position, Identifier.toIdentifier( name ) ); - } - - protected Column(TableSpecification table, int position, Identifier name) { - super( table, position ); - this.columnName = name; - } - - public void initialize(ColumnRelationalState state, boolean forceNonNullable, boolean forceUnique) { - size.initialize( state.getSize() ); - nullable = ! forceNonNullable && state.isNullable(); - unique = ! forceUnique && state.isUnique(); - checkCondition = state.getCheckCondition(); - defaultValue = state.getDefault(); - sqlType = state.getSqlType(); - - // TODO: this should go into binding instead (I think???) - writeFragment = state.getCustomWriteFragment(); - readFragment = state.getCustomReadFragment(); - comment = state.getComment(); - for ( String uniqueKey : state.getUniqueKeys() ) { - getTable().getOrCreateUniqueKey( uniqueKey ).addColumn( this ); - } - for ( String index : state.getIndexes() ) { - getTable().getOrCreateIndex( index ).addColumn( this ); - } - } - - public Identifier getColumnName() { - return columnName; - } - - public boolean isNullable() { - return nullable; - } - - public void setNullable(boolean nullable) { - this.nullable = nullable; - } - - public boolean isUnique() { - return unique; - } - - public void setUnique(boolean unique) { - this.unique = unique; - } - - public String getDefaultValue() { - return defaultValue; - } - - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - public String getCheckCondition() { - return checkCondition; - } - - public void setCheckCondition(String checkCondition) { - this.checkCondition = checkCondition; - } - - public String getSqlType() { - return sqlType; - } - - public void setSqlType(String sqlType) { - this.sqlType = sqlType; - } - - public String getReadFragment() { - return readFragment; - } - - public void setReadFragment(String readFragment) { - this.readFragment = readFragment; - } - - public String getWriteFragment() { - return writeFragment; - } - - public void setWriteFragment(String writeFragment) { - this.writeFragment = writeFragment; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public Size getSize() { - return size; - } - - public void setSize(Size size) { - this.size = size; - } - - @Override - public String toLoggableString() { - return getTable().getLoggableValueQualifier() + '.' + getColumnName(); - } - - @Override - public String getAlias(Dialect dialect) { - String alias = columnName.getName(); - int lastLetter = StringHelper.lastIndexOfLetter( columnName.getName() ); - if ( lastLetter == -1 ) { - alias = "column"; - } - boolean useRawName = - columnName.getName().equals( alias ) && - alias.length() <= dialect.getMaxAliasLength() && - ! columnName.isQuoted() && - ! columnName.getName().toLowerCase().equals( "rowid" ); - if ( ! useRawName ) { - String unique = - new StringBuilder() - .append( getPosition() ) - .append( '_' ) - .append( getTable().getTableNumber() ) - .append( '_' ) - .toString(); - if ( unique.length() >= dialect.getMaxAliasLength() ) { - throw new MappingException( - "Unique suffix [" + unique + "] length must be less than maximum [" + dialect.getMaxAliasLength() + "]" - ); - } - if ( alias.length() + unique.length() > dialect.getMaxAliasLength()) { - alias = alias.substring( 0, dialect.getMaxAliasLength() - unique.length() ); - } - alias = alias + unique; - } - return alias; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java deleted file mode 100644 index 3291b967ed78..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.Metadata; - -/** - * Represents a database and manages the named schema/catalog pairs defined within. - * - * @author Steve Ebersole - * @author Gail Badner - */ -public class Database { - private final Schema.Name implicitSchemaName; - - private final Map schemaMap = new HashMap(); - private final List auxiliaryDatabaseObjects = new ArrayList(); - - public Database(Metadata.Options options) { - String schemaName = options.getDefaultSchemaName(); - String catalogName = options.getDefaultCatalogName(); - if ( options.isGloballyQuotedIdentifiers() ) { - schemaName = StringHelper.quote( schemaName ); - catalogName = StringHelper.quote( catalogName ); - } - implicitSchemaName = new Schema.Name( schemaName, catalogName ); - makeSchema( implicitSchemaName ); - } - - public Schema getDefaultSchema() { - return schemaMap.get( implicitSchemaName ); - } - - public Schema locateSchema(Schema.Name name) { - if ( name.getSchema() == null && name.getCatalog() == null ) { - return getDefaultSchema(); - } - Schema schema = schemaMap.get( name ); - if ( schema == null ) { - schema = makeSchema( name ); - } - return schema; - } - - private Schema makeSchema(Schema.Name name) { - Schema schema; - schema = new Schema( name ); - schemaMap.put( name, schema ); - return schema; - } - - public Schema getSchema(Identifier schema, Identifier catalog) { - return locateSchema( new Schema.Name( schema, catalog ) ); - } - - public Schema getSchema(String schema, String catalog) { - return locateSchema( new Schema.Name( Identifier.toIdentifier( schema ), Identifier.toIdentifier( catalog ) ) ); - } - - public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) { - if ( auxiliaryDatabaseObject == null ) { - throw new IllegalArgumentException( "Auxiliary database object is null." ); - } - auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject ); - } - - public Iterable getAuxiliaryDatabaseObjects() { - return auxiliaryDatabaseObjects; - } - - public String[] generateSchemaCreationScript(Dialect dialect) { - Set exportIdentifiers = new HashSet( 50 ); - List script = new ArrayList( 50 ); - - for ( Schema schema : schemaMap.values() ) { - // TODO: create schema/catalog??? - for ( Table table : schema.getTables() ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, table ); - } - } - - for ( Schema schema : schemaMap.values() ) { - for ( Table table : schema.getTables() ) { - - for ( UniqueKey uniqueKey : table.getUniqueKeys() ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, uniqueKey ); - } - - for ( Index index : table.getIndexes() ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, index ); - } - - if ( dialect.hasAlterTable() ) { - for ( ForeignKey foreignKey : table.getForeignKeys() ) { - // only add the foreign key if its target is a physical table - if ( Table.class.isInstance( foreignKey.getTargetTable() ) ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, foreignKey ); - } - } - } - - } - } - - // TODO: add sql create strings from PersistentIdentifierGenerator.sqlCreateStrings() - - for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : auxiliaryDatabaseObjects ) { - if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) ) { - addSqlCreateStrings( dialect, exportIdentifiers, script, auxiliaryDatabaseObject ); - } - } - - return ArrayHelper.toStringArray( script ); - } - - public String[] generateDropSchemaScript(Dialect dialect) { - Set exportIdentifiers = new HashSet( 50 ); - List script = new ArrayList( 50 ); - - - // drop them in reverse order in case db needs it done that way... - for ( int i = auxiliaryDatabaseObjects.size() - 1 ; i >= 0 ; i-- ) { - AuxiliaryDatabaseObject object = auxiliaryDatabaseObjects.get( i ); - if ( object.appliesToDialect( dialect ) ) { - addSqlDropStrings( dialect, exportIdentifiers, script, object ); - } - } - - if ( dialect.dropConstraints() ) { - for ( Schema schema : schemaMap.values() ) { - for ( Table table : schema.getTables() ) { - for ( ForeignKey foreignKey : table.getForeignKeys() ) { - // only include foreign key if the target table is physical - if ( foreignKey.getTargetTable() instanceof Table ) { - addSqlDropStrings( dialect, exportIdentifiers, script, foreignKey ); - } - } - } - } - } - - for ( Schema schema : schemaMap.values() ) { - for ( Table table : schema.getTables() ) { - addSqlDropStrings( dialect, exportIdentifiers, script, table ); - } - } - - // TODO: add sql drop strings from PersistentIdentifierGenerator.sqlCreateStrings() - - // TODO: drop schemas/catalogs??? - - return ArrayHelper.toStringArray( script ); - } - - private static void addSqlDropStrings( - Dialect dialect, - Set exportIdentifiers, - List script, - Exportable exportable) { - addSqlStrings( - exportIdentifiers, script, exportable.getExportIdentifier(), exportable.sqlDropStrings( dialect ) - ); - } - - private static void addSqlCreateStrings( - Dialect dialect, - Set exportIdentifiers, - List script, - Exportable exportable) { - addSqlStrings( - exportIdentifiers, script, exportable.getExportIdentifier(), exportable.sqlCreateStrings( dialect ) - ); - } - - private static void addSqlStrings( - Set exportIdentifiers, - List script, - String exportIdentifier, - String[] sqlStrings) { - if ( sqlStrings == null ) { - return; - } - if ( exportIdentifiers.contains( exportIdentifier ) ) { - throw new MappingException( - "SQL strings added more than once for: " + exportIdentifier - ); - } - exportIdentifiers.add( exportIdentifier ); - script.addAll( Arrays.asList( sqlStrings ) ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Datatype.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Datatype.java deleted file mode 100644 index f0f5189b6d79..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Datatype.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -/** - * Models a JDBC {@link java.sql.Types DATATYPE} - * - * @todo Do we somehow link this in with {@link org.hibernate.internal.util.jdbc.TypeInfo} ? - * - * @author Steve Ebersole - */ -public class Datatype { - private final int typeCode; - private final String typeName; - private final Class javaType; - private final int hashCode; - - public Datatype(int typeCode, String typeName, Class javaType) { - this.typeCode = typeCode; - this.typeName = typeName; - this.javaType = javaType; - this.hashCode = generateHashCode(); - } - - private int generateHashCode() { - int result = typeCode; - if ( typeName != null ) { - result = 31 * result + typeName.hashCode(); - } - if ( javaType != null ) { - result = 31 * result + javaType.hashCode(); - } - return result; - } - - public int getTypeCode() { - return typeCode; - } - - public String getTypeName() { - return typeName; - } - - public Class getJavaType() { - return javaType; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - Datatype datatype = (Datatype) o; - - return typeCode == datatype.typeCode - && javaType.equals( datatype.javaType ) - && typeName.equals( datatype.typeName ); - - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public String toString() { - return super.toString() + "[code=" + typeCode + ", name=" + typeName + ", javaClass=" + javaType.getName() + "]"; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Exportable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Exportable.java deleted file mode 100644 index 7d720c232290..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Exportable.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; - -/** - * Contract for entities (in the ERD sense) which can be exported via {@code CREATE}, {@code ALTER}, etc - * - * @author Steve Ebersole - */ -public interface Exportable { - /** - * Get a unique identifier to make sure we are not exporting the same database structure multiple times. - * - * @return The exporting identifier. - */ - public String getExportIdentifier(); - - /** - * Gets the SQL strings for creating the database object. - * - * @param dialect The dialect for which to generate the SQL creation strings - * - * @return the SQL strings for creating the database object. - */ - public String[] sqlCreateStrings(Dialect dialect); - - /** - * Gets the SQL strings for dropping the database object. - * - * @param dialect The dialect for which to generate the SQL drop strings - * - * @return the SQL strings for dropping the database object. - */ - public String[] sqlDropStrings(Dialect dialect); - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java deleted file mode 100644 index bcb8c84510e6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; - -import org.jboss.logging.Logger; - -/** - * Models the notion of a foreign key. - *

    - * Note that this need not mean a physical foreign key; we just mean a relationship between 2 table - * specifications. - * - * @author Gavin King - * @author Steve Ebersole - */ -public class ForeignKey extends AbstractConstraint implements Constraint, Exportable { - private static final Logger LOG = Logger.getLogger( ForeignKey.class ); - - private static final String ON_DELETE = " on delete "; - private static final String ON_UPDATE = " on update "; - - private final TableSpecification targetTable; - private List targetColumns; - - private ReferentialAction deleteRule = ReferentialAction.NO_ACTION; - private ReferentialAction updateRule = ReferentialAction.NO_ACTION; - - protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, String name) { - super( sourceTable, name ); - this.targetTable = targetTable; - } - - protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable) { - this( sourceTable, targetTable, null ); - } - - public TableSpecification getSourceTable() { - return getTable(); - } - - public TableSpecification getTargetTable() { - return targetTable; - } - - public Iterable getSourceColumns() { - return getColumns(); - } - - public Iterable getTargetColumns() { - return targetColumns == null - ? getTargetTable().getPrimaryKey().getColumns() - : targetColumns; - } - - @Override - public void addColumn(Column column) { - addColumnMapping( column, null ); - } - - public void addColumnMapping(Column sourceColumn, Column targetColumn) { - if ( targetColumn == null ) { - if ( targetColumns != null ) { - LOG.debugf( - "Attempt to map column [%s] to no target column after explicit target column(s) named for FK [name=%s]", - sourceColumn.toLoggableString(), - getName() - ); - } - } - else { - checkTargetTable( targetColumn ); - if ( targetColumns == null ) { - if (!internalColumnAccess().isEmpty()) { - LOG.debugf( - "Value mapping mismatch as part of FK [table=%s, name=%s] while adding source column [%s]", - getTable().toLoggableString(), - getName(), - sourceColumn.toLoggableString() - ); - } - targetColumns = new ArrayList(); - } - targetColumns.add( targetColumn ); - } - internalAddColumn( sourceColumn ); - } - - private void checkTargetTable(Column targetColumn) { - if ( targetColumn.getTable() != getTargetTable() ) { - throw new AssertionFailure( - String.format( - "Unable to add column to constraint; tables [%s, %s] did not match", - targetColumn.getTable().toLoggableString(), - getTargetTable().toLoggableString() - ) - ); - } - } - - @Override - public String getExportIdentifier() { - return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName(); - } - - public ReferentialAction getDeleteRule() { - return deleteRule; - } - - public void setDeleteRule(ReferentialAction deleteRule) { - this.deleteRule = deleteRule; - } - - public ReferentialAction getUpdateRule() { - return updateRule; - } - - public void setUpdateRule(ReferentialAction updateRule) { - this.updateRule = updateRule; - } - - @Override - public String[] sqlDropStrings(Dialect dialect) { - return new String[] { - "alter table " + - getTable().getQualifiedName( dialect ) + - dialect.getDropForeignKeyString() + - getName() - }; - } - - public String sqlConstraintStringInAlterTable(Dialect dialect) { - String[] columnNames = new String[ getColumnSpan() ]; - String[] targetColumnNames = new String[ getColumnSpan() ]; - int i=0; - Iterator itTargetColumn = getTargetColumns().iterator(); - for ( Column column : getColumns() ) { - if ( ! itTargetColumn.hasNext() ) { - throw new MappingException( "More constraint columns that foreign key target columns." ); - } - columnNames[i] = column.getColumnName().encloseInQuotesIfQuoted( dialect ); - targetColumnNames[i] = ( itTargetColumn.next() ).getColumnName().encloseInQuotesIfQuoted( dialect ); - i++; - } - if ( itTargetColumn.hasNext() ) { - throw new MappingException( "More foreign key target columns than constraint columns." ); - } - StringBuilder sb = - new StringBuilder( - dialect.getAddForeignKeyConstraintString( - getName(), - columnNames, - targetTable.getQualifiedName( dialect ), - targetColumnNames, - this.targetColumns == null - ) - ); - // TODO: If a dialect does not support cascade-delete, can it support other actions? (HHH-6428) - // For now, assume not. - if ( dialect.supportsCascadeDelete() ) { - if ( deleteRule != ReferentialAction.NO_ACTION ) { - sb.append( ON_DELETE ).append( deleteRule.getActionString() ); - } - if ( updateRule != ReferentialAction.NO_ACTION ) { - sb.append( ON_UPDATE ).append( updateRule.getActionString() ); - } - } - return sb.toString(); - } - - public static enum ReferentialAction { - NO_ACTION( "no action" ), - CASCADE( "cascade" ), - SET_NULL( "set null" ), - SET_DEFAULT( "set default" ), - RESTRICT( "restrict" ); - - private final String actionString; - - private ReferentialAction(String actionString) { - this.actionString = actionString; - } - - public String getActionString() { - return actionString; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Identifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Identifier.java deleted file mode 100644 index 3cd04f947970..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Identifier.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - - -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; - -/** - * Models an identifier (name). - * - * @author Steve Ebersole - */ -public class Identifier { - private final String name; - private final boolean isQuoted; - - /** - * Means to generate an {@link Identifier} instance from its simple name - * - * @param name The name - * - * @return The identifier form of the name. - */ - public static Identifier toIdentifier(String name) { - if ( StringHelper.isEmpty( name ) ) { - return null; - } - final String trimmedName = name.trim(); - if ( isQuoted( trimmedName ) ) { - final String bareName = trimmedName.substring( 1, trimmedName.length() - 1 ); - return new Identifier( bareName, true ); - } - else { - return new Identifier( trimmedName, false ); - } - } - - public static boolean isQuoted(String name) { - return name.startsWith( "`" ) && name.endsWith( "`" ); - } - - /** - * Constructs an identifier instance. - * - * @param name The identifier text. - * @param quoted Is this a quoted identifier? - */ - public Identifier(String name, boolean quoted) { - if ( StringHelper.isEmpty( name ) ) { - throw new IllegalIdentifierException( "Identifier text cannot be null" ); - } - if ( isQuoted( name ) ) { - throw new IllegalIdentifierException( "Identifier text should not contain quote markers (`)" ); - } - this.name = name; - this.isQuoted = quoted; - } - - /** - * Get the identifiers name (text) - * - * @return The name - */ - public String getName() { - return name; - } - - /** - * Is this a quoted identifier> - * - * @return True if this is a quote identifier; false otherwise. - */ - public boolean isQuoted() { - return isQuoted; - } - - /** - * If this is a quoted identifier, then return the identifier name - * enclosed in dialect-specific open- and end-quotes; otherwise, - * simply return the identifier name. - * - * @param dialect The dialect whose dialect-specific quoting should be used. - * @return if quoted, identifier name enclosed in dialect-specific open- and end-quotes; otherwise, the - * identifier name. - */ - public String encloseInQuotesIfQuoted(Dialect dialect) { - return isQuoted ? - new StringBuilder( name.length() + 2 ) - .append( dialect.openQuote() ) - .append( name ) - .append( dialect.closeQuote() ) - .toString() : - name; - } - - @Override - public String toString() { - return isQuoted - ? '`' + getName() + '`' - : getName(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - Identifier that = (Identifier) o; - - return isQuoted == that.isQuoted - && name.equals( that.name ); - } - - @Override - public int hashCode() { - return name.hashCode(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java deleted file mode 100644 index 2eb119c91439..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; - -/** - * Models a SQL INDEX - * - * @author Gavin King - * @author Steve Ebersole - */ -public class Index extends AbstractConstraint implements Constraint { - protected Index(Table table, String name) { - super( table, name ); - } - - - @Override - public String getExportIdentifier() { - StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier()); - sb.append( ".IDX" ); - for ( Column column : getColumns() ) { - sb.append( '_' ).append( column.getColumnName().getName() ); - } - return sb.toString(); - } - - public String[] sqlCreateStrings(Dialect dialect) { - return new String[] { - buildSqlCreateIndexString( - dialect, getName(), getTable(), getColumns(), false - ) - }; - } - - public static String buildSqlCreateIndexString( - Dialect dialect, - String name, - TableSpecification table, - Iterable columns, - boolean unique - ) { - StringBuilder buf = new StringBuilder( "create" ) - .append( unique ? - " unique" : - "" ) - .append( " index " ) - .append( dialect.qualifyIndexName() ? - name : - StringHelper.unqualify( name ) ) - .append( " on " ) - .append( table.getQualifiedName( dialect ) ) - .append( " (" ); - boolean first = true; - for ( Column column : columns ) { - if ( first ) { - first = false; - } - else { - buf.append( ", " ); - } - buf.append( ( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ) ); - } - buf.append( ")" ); - return buf.toString(); - } - - public static String buildSqlDropIndexString( - Dialect dialect, - TableSpecification table, - String name - ) { - return "drop index " + - StringHelper.qualify( - table.getQualifiedName( dialect ), - name - ); - } - - public String sqlConstraintStringInAlterTable(Dialect dialect) { - StringBuilder buf = new StringBuilder( " index (" ); - boolean first = true; - for ( Column column : getColumns() ) { - if ( first ) { - first = false; - } - else { - buf.append( ", " ); - } - buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); - } - return buf.append( ')' ).toString(); - } - - public String[] sqlDropStrings(Dialect dialect) { - return new String[] { - new StringBuilder( "drop index " ) - .append( - StringHelper.qualify( - getTable().getQualifiedName( dialect ), - getName() - ) - ).toString() - }; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ObjectName.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ObjectName.java deleted file mode 100644 index b27b73ac27f7..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ObjectName.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.HibernateException; -import org.hibernate.dialect.Dialect; - -/** - * Models the qualified name of a database object. - *

    - * Some things to keep in mind wrt catalog/schema: - * 1) {@link java.sql.DatabaseMetaData#isCatalogAtStart} - * 2) {@link java.sql.DatabaseMetaData#getCatalogSeparator()} - * - * @author Steve Ebersole - */ -public class ObjectName { - // todo - should depend on DatabaseMetaData. For now hard coded (HF) - private static String SEPARATOR = "."; - - private final Identifier schema; - private final Identifier catalog; - private final Identifier name; - - private final String identifier; - private final int hashCode; - - /** - * Tries to create an {@code ObjectName} from a name. - * - * @param objectName simple or qualified name of the database object. - */ - public ObjectName(String objectName) { - this( - extractSchema( objectName ), - extractCatalog( objectName ), - extractName( objectName ) - ); - } - - public ObjectName(Identifier name) { - this( null, null, name ); - } - - public ObjectName(Schema schema, String name) { - this( schema.getName().getSchema(), schema.getName().getCatalog(), Identifier.toIdentifier( name ) ); - } - - public ObjectName(Schema schema, Identifier name) { - this( schema.getName().getSchema(), schema.getName().getCatalog(), name ); - } - - public ObjectName(String schemaName, String catalogName, String name) { - this( - Identifier.toIdentifier( schemaName ), - Identifier.toIdentifier( catalogName ), - Identifier.toIdentifier( name ) - ); - } - - /** - * Creates a qualified name reference. - * - * @param schema The in which the object is defined (optional) - * @param catalog The catalog in which the object is defined (optional) - * @param name The name (required) - */ - public ObjectName(Identifier schema, Identifier catalog, Identifier name) { - if ( name == null ) { - // Identifier cannot be constructed with an 'empty' name - throw new IllegalIdentifierException( "Object name must be specified" ); - } - this.name = name; - this.schema = schema; - this.catalog = catalog; - - this.identifier = qualify( - schema == null ? null : schema.toString(), - catalog == null ? null : catalog.toString(), - name.toString() - ); - - int tmpHashCode = schema != null ? schema.hashCode() : 0; - tmpHashCode = 31 * tmpHashCode + ( catalog != null ? catalog.hashCode() : 0 ); - tmpHashCode = 31 * tmpHashCode + name.hashCode(); - this.hashCode = tmpHashCode; - } - - public Identifier getSchema() { - return schema; - } - - public Identifier getCatalog() { - return catalog; - } - - public Identifier getName() { - return name; - } - - public String toText() { - return identifier; - } - - public String toText(Dialect dialect) { - if ( dialect == null ) { - throw new IllegalArgumentException( "dialect must be non-null." ); - } - return qualify( - encloseInQuotesIfQuoted( schema, dialect ), - encloseInQuotesIfQuoted( catalog, dialect ), - encloseInQuotesIfQuoted( name, dialect ) - ); - } - - private static String encloseInQuotesIfQuoted(Identifier identifier, Dialect dialect) { - return identifier == null ? - null : - identifier.encloseInQuotesIfQuoted( dialect ); - } - - private static String qualify(String schema, String catalog, String name) { - StringBuilder buff = new StringBuilder( name ); - if ( catalog != null ) { - buff.insert( 0, catalog + '.' ); - } - if ( schema != null ) { - buff.insert( 0, schema + '.' ); - } - return buff.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - ObjectName that = (ObjectName) o; - - return name.equals( that.name ) - && areEqual( catalog, that.catalog ) - && areEqual( schema, that.schema ); - } - - @Override - public int hashCode() { - return hashCode; - } - - - @Override - public String toString() { - return "ObjectName{" + - "name='" + name + '\'' + - ", schema='" + schema + '\'' + - ", catalog='" + catalog + '\'' + - '}'; - } - - private boolean areEqual(Identifier one, Identifier other) { - return one == null - ? other == null - : one.equals( other ); - } - - private static String extractSchema(String qualifiedName) { - if ( qualifiedName == null ) { - return null; - } - String[] tokens = qualifiedName.split( SEPARATOR ); - if ( tokens.length == 0 || tokens.length == 1 ) { - return null; - } - else if ( tokens.length == 2 ) { - // todo - this case needs to be refined w/ help of DatabaseMetaData (HF) - return null; - } - else if ( tokens.length == 3 ) { - return tokens[0]; - } - else { - throw new HibernateException( "Unable to parse object name: " + qualifiedName ); - } - } - - private static String extractCatalog(String qualifiedName) { - if ( qualifiedName == null ) { - return null; - } - String[] tokens = qualifiedName.split( SEPARATOR ); - if ( tokens.length == 0 || tokens.length == 1 ) { - return null; - } - else if ( tokens.length == 2 ) { - // todo - this case needs to be refined w/ help of DatabaseMetaData (HF) - return null; - } - else if ( tokens.length == 3 ) { - return tokens[1]; - } - else { - throw new HibernateException( "Unable to parse object name: " + qualifiedName ); - } - } - - private static String extractName(String qualifiedName) { - if ( qualifiedName == null ) { - return null; - } - String[] tokens = qualifiedName.split( SEPARATOR ); - if ( tokens.length == 0 ) { - return qualifiedName; - } - else { - return tokens[tokens.length - 1]; - } - } -} - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java deleted file mode 100644 index 3962571ef4e2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; - -/** - * Models a table's primary key. - *

    - * NOTE : This need not be a physical primary key; we just mean a column or columns which uniquely identify rows in - * the table. Of course it is recommended to define proper integrity constraints, including primary keys. - * - * @author Gavin King - * @author Steve Ebersole - */ -public class PrimaryKey extends AbstractConstraint implements Constraint, Exportable { - // IMPL NOTE : I override the name behavior here because: - // (1) primary keys are not required to be named. - // (2) because a primary key is required for each table, it is easier to allow setting the constraint name - // later in terms of building the metamodel - // - // todo : default name? {TABLE_NAME}_PK maybe? - private String name; - - protected PrimaryKey(TableSpecification table) { - super( table, null ); - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String getExportIdentifier() { - return getTable().getLoggableValueQualifier() + ".PK"; - } - - public String sqlConstraintStringInCreateTable(Dialect dialect) { - StringBuilder buf = new StringBuilder("primary key ("); - boolean first = true; - for ( Column column : getColumns() ) { - if ( first ) { - first = false; - } - else { - buf.append(", "); - } - buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); - } - return buf.append(')').toString(); - } - - public String sqlConstraintStringInAlterTable(Dialect dialect) { - StringBuilder buf = new StringBuilder( - dialect.getAddPrimaryKeyConstraintString( getName() ) - ).append('('); - boolean first = true; - for ( Column column : getColumns() ) { - if ( first ) { - first = false; - } - else { - buf.append(", "); - } - buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); - } - return buf.append(')').toString(); - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java deleted file mode 100644 index 25a36aac8b69..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Schema.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.HashMap; -import java.util.Map; - -/** - * Represents a named schema/catalog pair and manages objects defined within. - * - * @author Steve Ebersole - */ -public class Schema { - private final Name name; - private Map inLineViews = new HashMap(); - private Map tables = new HashMap(); - - public Schema(Name name) { - this.name = name; - } - - public Schema(Identifier schema, Identifier catalog) { - this( new Name( schema, catalog ) ); - } - - public Name getName() { - return name; - } - - public Table locateTable(Identifier name) { - return tables.get( name ); - } - - public Table createTable(Identifier name) { - Table table = new Table( this, name ); - tables.put( name, table ); - return table; - } - - public Table locateOrCreateTable(Identifier name) { - final Table existing = locateTable( name ); - if ( existing == null ) { - return createTable( name ); - } - return existing; - } - - public Iterable

    getTables() { - return tables.values(); - } - - public InLineView getInLineView(String logicalName) { - return inLineViews.get( logicalName ); - } - - public InLineView createInLineView(String logicalName, String subSelect) { - InLineView inLineView = new InLineView( this, logicalName, subSelect ); - inLineViews.put( logicalName, inLineView ); - return inLineView; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "Schema" ); - sb.append( "{name=" ).append( name ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - Schema schema = (Schema) o; - - if ( name != null ? !name.equals( schema.name ) : schema.name != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return name != null ? name.hashCode() : 0; - } - - public static class Name { - private final Identifier schema; - private final Identifier catalog; - - public Name(Identifier schema, Identifier catalog) { - this.schema = schema; - this.catalog = catalog; - } - - public Name(String schema, String catalog) { - this( Identifier.toIdentifier( schema ), Identifier.toIdentifier( catalog ) ); - } - - public Identifier getSchema() { - return schema; - } - - public Identifier getCatalog() { - return catalog; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "Name" ); - sb.append( "{schema=" ).append( schema ); - sb.append( ", catalog=" ).append( catalog ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - Name name = (Name) o; - - if ( catalog != null ? !catalog.equals( name.catalog ) : name.catalog != null ) { - return false; - } - if ( schema != null ? !schema.equals( name.schema ) : name.schema != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = schema != null ? schema.hashCode() : 0; - result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 ); - return result; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Sequence.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Sequence.java deleted file mode 100644 index fcaf7b886d5e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Sequence.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; - -/** - * Models a database {@code SEQUENCE}. - * - * @author Steve Ebersole - */ -public class Sequence implements Exportable { - private final Schema schema; - private final String name; - private final String qualifiedName; - private int initialValue = 1; - private int incrementSize = 1; - - public Sequence(Schema schema, String name) { - this.schema = schema; - this.name = name; - this.qualifiedName = new ObjectName( schema, name ).toText(); - } - - public Sequence(Schema schema, String name, int initialValue, int incrementSize) { - this( schema, name ); - this.initialValue = initialValue; - this.incrementSize = incrementSize; - } - - public Schema getSchema() { - return schema; - } - - public String getName() { - return name; - } - - @Override - public String getExportIdentifier() { - return qualifiedName; - } - - public int getInitialValue() { - return initialValue; - } - - public int getIncrementSize() { - return incrementSize; - } - - @Override - public String[] sqlCreateStrings(Dialect dialect) throws MappingException { - return dialect.getCreateSequenceStrings( name, initialValue,incrementSize ); - } - - @Override - public String[] sqlDropStrings(Dialect dialect) throws MappingException { - return dialect.getDropSequenceStrings( name ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/SimpleValue.java deleted file mode 100644 index 8cc4854bc965..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/SimpleValue.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; - -/** - * Models a simple, non-compound value. - * - * @author Steve Ebersole - */ -public interface SimpleValue extends Value { - /** - * Retrieve the datatype of this value. - * - * @return The value's datatype - */ - public Datatype getDatatype(); - - /** - * Set the datatype of this value. - * - * @param datatype The value's datatype - */ - public void setDatatype(Datatype datatype); - - /** - * For any column name, generate an alias that is unique - * to that column name, unique across tables, and within - * alias size constraints determined by - * {@link org.hibernate.dialect.Dialect#getMaxAliasLength()}. - * - * @param dialect the dialect. - * @return the alias. - */ - public String getAlias(Dialect dialect); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java deleted file mode 100644 index f88c2fdf0889..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; - -import org.hibernate.dialect.Dialect; - -/** - * Models the concept of a relational TABLE (or VIEW). - * - * @author Gavin King - * @author Steve Ebersole - */ -public class Table extends AbstractTableSpecification implements Exportable { - private final Schema database; - private final Identifier tableName; - private final ObjectName objectName; - private final String qualifiedName; - - private final LinkedHashMap indexes = new LinkedHashMap(); - private final LinkedHashMap uniqueKeys = new LinkedHashMap(); - private final List checkConstraints = new ArrayList(); - private final List comments = new ArrayList(); - - public Table(Schema database, String tableName) { - this( database, Identifier.toIdentifier( tableName ) ); - } - - public Table(Schema database, Identifier tableName) { - this.database = database; - this.tableName = tableName; - objectName = new ObjectName( database.getName().getSchema(), database.getName().getCatalog(), tableName ); - this.qualifiedName = objectName.toText(); - } - - @Override - public Schema getSchema() { - return database; - } - - public Identifier getTableName() { - return tableName; - } - - @Override - public String getLoggableValueQualifier() { - return qualifiedName; - } - - @Override - public String getExportIdentifier() { - return qualifiedName; - } - - @Override - public String toLoggableString() { - return qualifiedName; - } - - @Override - public Iterable getIndexes() { - return indexes.values(); - } - - public Index getOrCreateIndex(String name) { - if( indexes.containsKey( name ) ){ - return indexes.get( name ); - } - Index index = new Index( this, name ); - indexes.put(name, index ); - return index; - } - - @Override - public Iterable getUniqueKeys() { - return uniqueKeys.values(); - } - - public UniqueKey getOrCreateUniqueKey(String name) { - if( uniqueKeys.containsKey( name ) ){ - return uniqueKeys.get( name ); - } - UniqueKey uniqueKey = new UniqueKey( this, name ); - uniqueKeys.put(name, uniqueKey ); - return uniqueKey; - } - - @Override - public Iterable getCheckConstraints() { - return checkConstraints; - } - - @Override - public void addCheckConstraint(String checkCondition) { - //todo ? StringHelper.isEmpty( checkCondition ); - //todo default name? - checkConstraints.add( new CheckConstraint( this, "", checkCondition ) ); - } - - @Override - public Iterable getComments() { - return comments; - } - - @Override - public void addComment(String comment) { - comments.add( comment ); - } - - @Override - public String getQualifiedName(Dialect dialect) { - return objectName.toText( dialect ); - } - - public String[] sqlCreateStrings(Dialect dialect) { - boolean hasPrimaryKey = getPrimaryKey().getColumns().iterator().hasNext(); - StringBuilder buf = - new StringBuilder( - hasPrimaryKey ? dialect.getCreateTableString() : dialect.getCreateMultisetTableString() ) - .append( ' ' ) - .append( objectName.toText( dialect ) ) - .append( " (" ); - - - // TODO: fix this when identity columns are supported by new metadata (HHH-6436) - // for now, assume false - //boolean identityColumn = idValue != null && idValue.isIdentityColumn( metadata.getIdentifierGeneratorFactory(), dialect ); - boolean isPrimaryKeyIdentity = false; - - // Try to find out the name of the primary key to create it as identity if the IdentityGenerator is used - String pkColName = null; - if ( hasPrimaryKey && isPrimaryKeyIdentity ) { - Column pkColumn = getPrimaryKey().getColumns().iterator().next(); - pkColName = pkColumn.getColumnName().encloseInQuotesIfQuoted( dialect ); - } - - boolean isFirst = true; - for ( SimpleValue simpleValue : values() ) { - if ( ! Column.class.isInstance( simpleValue ) ) { - continue; - } - if ( isFirst ) { - isFirst = false; - } - else { - buf.append( ", " ); - } - Column col = ( Column ) simpleValue; - String colName = col.getColumnName().encloseInQuotesIfQuoted( dialect ); - - buf.append( colName ).append( ' ' ); - - if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) { - // to support dialects that have their own identity data type - if ( dialect.hasDataTypeInIdentityColumn() ) { - buf.append( getTypeString( col, dialect ) ); - } - buf.append( ' ' ) - .append( dialect.getIdentityColumnString( col.getDatatype().getTypeCode() ) ); - } - else { - buf.append( getTypeString( col, dialect ) ); - - String defaultValue = col.getDefaultValue(); - if ( defaultValue != null ) { - buf.append( " default " ).append( defaultValue ); - } - - if ( col.isNullable() ) { - buf.append( dialect.getNullColumnString() ); - } - else { - buf.append( " not null" ); - } - - } - - if ( col.isUnique() ) { - UniqueKey uk = getOrCreateUniqueKey( col.getColumnName() - .encloseInQuotesIfQuoted( dialect ) + '_' ); - uk.addColumn( col ); - buf.append( dialect.getUniqueDelegate() - .getColumnDefinitionUniquenessFragment( col ) ); - } - - if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) { - buf.append( " check (" ) - .append( col.getCheckCondition() ) - .append( ")" ); - } - - String columnComment = col.getComment(); - if ( columnComment != null ) { - buf.append( dialect.getColumnComment( columnComment ) ); - } - } - if ( hasPrimaryKey ) { - buf.append( ", " ) - .append( getPrimaryKey().sqlConstraintStringInCreateTable( dialect ) ); - } - - buf.append( dialect.getUniqueDelegate().getTableCreationUniqueConstraintsFragment( this ) ); - - if ( dialect.supportsTableCheck() ) { - for ( CheckConstraint checkConstraint : checkConstraints ) { - buf.append( ", check (" ) - .append( checkConstraint ) - .append( ')' ); - } - } - - buf.append( ')' ); - buf.append( dialect.getTableTypeString() ); - - String[] sqlStrings = new String[ comments.size() + 1 ]; - sqlStrings[ 0 ] = buf.toString(); - - for ( int i = 0 ; i < comments.size(); i++ ) { - sqlStrings[ i + 1 ] = dialect.getTableComment( comments.get( i ) ); - } - - return sqlStrings; - } - - private static String getTypeString(Column col, Dialect dialect) { - String typeString = null; - if ( col.getSqlType() != null ) { - typeString = col.getSqlType(); - } - else { - Size size = col.getSize() == null ? - new Size( ) : - col.getSize(); - - typeString = dialect.getTypeName( - col.getDatatype().getTypeCode(), - size.getLength(), - size.getPrecision(), - size.getScale() - ); - } - return typeString; - } - - @Override - public String[] sqlDropStrings(Dialect dialect) { - return new String[] { dialect.getDropTableString( getQualifiedName( dialect ) ) }; - } - - @Override - public String toString() { - return "Table{name=" + qualifiedName + '}'; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java deleted file mode 100644 index 69fbd02d557a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; - -/** - * Models what ANSI SQL terms a table specification which is a table or a view or an inline view. - * - * @author Steve Ebersole - */ -public interface TableSpecification extends ValueContainer, Loggable { - /** - * Obtain a reference to the schema to which this table specification belongs. - * - * @return The schema to which this table specification belongs. - */ - public Schema getSchema(); - - /** - * Get the table number. - * - * @return the table number. - */ - public int getTableNumber(); - - /** - * Get the primary key definition for this table spec. - * - * @return The PK definition. - */ - public PrimaryKey getPrimaryKey(); - - /** - * Factory method for creating a {@link Column} associated with this container. - * - * @param name The column name - * - * @return The generated column - */ - public Column locateOrCreateColumn(String name); - - /** - * Factory method for creating a {@link Column} associated with this container. - * - * @param name The column name - * - * @return The generated column - */ - public Tuple createTuple(String name); - - /** - * Factory method for creating a {@link DerivedValue} associated with this container. - * - * @param fragment The value expression - * - * @return The generated value. - */ - public DerivedValue locateOrCreateDerivedValue(String fragment); - - public Iterable getForeignKeys(); - - public ForeignKey createForeignKey(TableSpecification targetTable, String name); - - public Iterable getIndexes(); - - public Index getOrCreateIndex(String name); - - public Iterable getUniqueKeys(); - - public UniqueKey getOrCreateUniqueKey(String name); - - public Iterable getCheckConstraints(); - - public void addCheckConstraint(String checkCondition); - - public Iterable getComments(); - - public void addComment(String comment); - - public String getQualifiedName(Dialect dialect); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java deleted file mode 100644 index c566dead53cd..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Tuple.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.util.LinkedHashSet; - -/** - * Models a compound value (a tuple or row-value-constructor is SQL terms). It is both a {@link Value} and - * a {@link ValueContainer} simultaneously. - *

    - * IMPL NOTE : in terms of the tables themselves, SQL has no notion of a tuple/compound-value. We simply model - * it this way because: - *

      - *
    • it is a cleaner mapping to the logical model
    • - *
    • it allows more meaningful traversals from simple values back up to table through any intermediate tuples - * because it gives us a better understanding of the model.
    • - *
    • it better conveys intent
    • - *
    • it adds richness to the model
    • - *
    - * - * @author Steve Ebersole - */ -public class Tuple implements Value, ValueContainer, Loggable { - private final TableSpecification table; - private final String name; - private final LinkedHashSet values = new LinkedHashSet(); - - public Tuple(TableSpecification table, String name) { - this.table = table; - this.name = name; - } - - @Override - public TableSpecification getTable() { - return table; - } - - public int valuesSpan() { - return values.size(); - } - - @Override - public Iterable values() { - return values; - } - - public void addValue(SimpleValue value) { - if ( ! value.getTable().equals( getTable() ) ) { - throw new IllegalArgumentException( "Tuple can only group values from same table" ); - } - values.add( value ); - } - - @Override - public String getLoggableValueQualifier() { - return getTable().getLoggableValueQualifier() + '.' + name + "{tuple}"; - } - - @Override - public String toLoggableString() { - return getLoggableValueQualifier(); - } - - @Override - public void validateJdbcTypes(JdbcCodes typeCodes) { - for ( Value value : values() ) { - value.validateJdbcTypes( typeCodes ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java deleted file mode 100644 index f130f2ebe952..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.hibernate.dialect.Dialect; -import org.hibernate.internal.util.StringHelper; - -/** - * Models a SQL INDEX defined as UNIQUE - * - * @author Gavin King - * @author Steve Ebersole - */ -public class UniqueKey extends AbstractConstraint implements Constraint { - protected UniqueKey(Table table, String name) { - super( table, name ); - } - - @Override - public String getExportIdentifier() { - StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier() ); - sb.append( ".UK" ); - for ( Column column : getColumns() ) { - sb.append( '_' ).append( column.getColumnName().getName() ); - } - return sb.toString(); - } - - @Override - public String[] sqlCreateStrings(Dialect dialect) { - String s = dialect.getUniqueDelegate().getAlterTableToAddUniqueKeyCommand( this ); - return StringHelper.toArrayElement( s ); - } - - @Override - public String[] sqlDropStrings(Dialect dialect) { - String s = dialect.getUniqueDelegate().getAlterTableToDropUniqueKeyCommand( this ); - return StringHelper.toArrayElement( s ); - } - - @Override - protected String sqlConstraintStringInAlterTable(Dialect dialect) { - // not used - return ""; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Value.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Value.java deleted file mode 100644 index 0549bb7cc186..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Value.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -/** - * Models a value within a {@link ValueContainer}. This will generally be either a {@link Column column} or a - * {@link DerivedValue derived value}, but we also allow the notion of {@link Tuple} at this level - * - * @author Steve Ebersole - */ -public interface Value { - /** - * Retrieve the table that owns this value. - * - * @return The owning table. - */ - public TableSpecification getTable(); - - /** - * Obtain the string representation of this value usable in log statements. - * - * @return The loggable representation - */ - public String toLoggableString(); - - /** - * Used to track JDBC type usage throughout a series of potential recursive calls to component - * values since we do not know ahead of time which values correspond to which indexes of the - * jdbc type array. - */ - public static class JdbcCodes { - private final int[] typeCodes; - private int index = 0; - - public JdbcCodes(int[] typeCodes) { - this.typeCodes = typeCodes; - } - - public int nextJdbcCde() { - return typeCodes[index++]; - } - - public int getIndex() { - return index; - } - } - - /** - * Validate the value against the incoming JDBC type code array, both in terms of number of types - * and compatibility of types. - * - * @param typeCodes The type codes. - * - * @throws org.hibernate.metamodel.ValidationException if validaton fails. - */ - public void validateJdbcTypes(JdbcCodes typeCodes); - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ColumnRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ColumnRelationalState.java deleted file mode 100644 index ae141bcbd887..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ColumnRelationalState.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational.state; - -import java.util.Set; - -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.metamodel.relational.Size; - -/** - * @author Gail Badner - */ -public interface ColumnRelationalState extends SimpleValueRelationalState { - NamingStrategy getNamingStrategy(); - - boolean isGloballyQuotedIdentifiers(); - - String getExplicitColumnName(); - - boolean isUnique(); - - Size getSize(); - - boolean isNullable(); - - String getCheckCondition(); - - String getDefault(); - - String getSqlType(); - - String getCustomWriteFragment(); - - String getCustomReadFragment(); - - String getComment(); - - Set getUniqueKeys(); - - Set getIndexes(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/DerivedValueRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/DerivedValueRelationalState.java deleted file mode 100644 index 19021f58c364..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/DerivedValueRelationalState.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational.state; - -/** - * @author Gail Badner - */ -public interface DerivedValueRelationalState extends SimpleValueRelationalState { - String getFormula(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ManyToOneRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ManyToOneRelationalState.java deleted file mode 100644 index c441b3e6217f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ManyToOneRelationalState.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational.state; - -/** - * @author Gail Badner - */ -public interface ManyToOneRelationalState extends ValueRelationalState { - boolean isLogicalOneToOne(); - - String getForeignKeyName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/SimpleValueRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/SimpleValueRelationalState.java deleted file mode 100644 index a0ea13a92cd8..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/SimpleValueRelationalState.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational.state; - -/** - * @author Gail Badner - */ -public interface SimpleValueRelationalState extends ValueRelationalState { -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/TupleRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/TupleRelationalState.java deleted file mode 100644 index 6bec20e59e55..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/TupleRelationalState.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational.state; - -import java.util.List; - -/** - * @author Gail Badner - */ -public interface TupleRelationalState extends ValueRelationalState { - List getRelationalStates(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueRelationalState.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueRelationalState.java deleted file mode 100644 index d8fb1ff8bdc9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueRelationalState.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational.state; - -/** - * @author Gail Badner - */ -public interface ValueRelationalState { -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/BindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/BindingContext.java deleted file mode 100644 index 6fbcfc0c0c4c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/BindingContext.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source; - -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.service.ServiceRegistry; - -/** - * @author Steve Ebersole - */ -public interface BindingContext { - public ServiceRegistry getServiceRegistry(); - - public NamingStrategy getNamingStrategy(); - - public MappingDefaults getMappingDefaults(); - - public MetadataImplementor getMetadataImplementor(); - - public Class locateClassByName(String name); - - public Type makeJavaType(String className); - - public boolean isGloballyQuotedIdentifiers(); - - public ValueHolder> makeClassReference(String className); - - public String qualifyClassName(String name); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/LocalBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/LocalBindingContext.java deleted file mode 100644 index 818beba54c05..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/LocalBindingContext.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source; - -import org.hibernate.internal.jaxb.Origin; - -/** - * @author Steve Ebersole - */ -public interface LocalBindingContext extends BindingContext { - public Origin getOrigin(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java deleted file mode 100644 index 985272bc479b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataImplementor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source; - -import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.Mapping; -import org.hibernate.engine.spi.NamedQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.metamodel.Metadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.relational.Database; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.type.TypeResolver; - -/** - * @author Steve Ebersole - */ -public interface MetadataImplementor extends Metadata, BindingContext, Mapping { - public ServiceRegistry getServiceRegistry(); - - public Database getDatabase(); - - public TypeResolver getTypeResolver(); - - public void addImport(String entityName, String entityName1); - - public void addEntity(EntityBinding entityBinding); - - public void addCollection(PluralAttributeBinding collectionBinding); - - public void addFetchProfile(FetchProfile profile); - - public void addTypeDefinition(TypeDef typeDef); - - public void addFilterDefinition(FilterDefinition filterDefinition); - - public void addIdGenerator(IdGenerator generator); - - public void registerIdentifierGenerator(String name, String clazz); - - public void addNamedNativeQuery(NamedSQLQueryDefinition def); - - public void addNamedQuery(NamedQueryDefinition def); - - public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition); - - // todo : this needs to move to AnnotationBindingContext - public void setGloballyQuotedIdentifiers(boolean b); - - public MetaAttributeContext getGlobalMetaAttributeContext(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataSourceProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataSourceProcessor.java deleted file mode 100644 index 985d28aac051..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetadataSourceProcessor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source; - -import java.util.List; - -import org.hibernate.metamodel.MetadataSources; - -/** - * Handles the processing of metadata sources in a dependency-ordered manner. - * - * @author Steve Ebersole - */ -public interface MetadataSourceProcessor { - /** - * Prepare for processing the given sources. - * - * @param sources The metadata sources. - */ - public void prepare(MetadataSources sources); - - /** - * Process the independent metadata. These have no dependency on other types of metadata being processed. - * - * @param sources The metadata sources. - * - * @see #prepare - */ - public void processIndependentMetadata(MetadataSources sources); - - /** - * Process the parts of the metadata that depend on type information (type definitions) having been processed - * and available. - * - * @param sources The metadata sources. - * - * @see #processIndependentMetadata - */ - public void processTypeDependentMetadata(MetadataSources sources); - - /** - * Process the mapping (entities, et al) metadata. - * - * @param sources The metadata sources. - * @param processedEntityNames Collection of any already processed entity names. - * - * @see #processTypeDependentMetadata - */ - public void processMappingMetadata(MetadataSources sources, List processedEntityNames); - - /** - * Process the parts of the metadata that depend on mapping (entities, et al) information having been - * processed and available. - * - * @param sources The metadata sources. - * - * @see #processMappingMetadata - */ - public void processMappingDependentMetadata(MetadataSources sources); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContext.java deleted file mode 100644 index dc8dbe784331..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContext.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import org.hibernate.metamodel.source.BindingContext; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.Index; - -import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; - -/** - * Defines an interface for providing additional annotation related context information. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public interface AnnotationBindingContext extends BindingContext { - Index getIndex(); - - ClassInfo getClassInfo(String name); - - void resolveAllTypes(String className); - - ResolvedType getResolvedType(Class clazz); - - ResolvedTypeWithMembers resolveMemberTypes(ResolvedType type); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContextImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContextImpl.java deleted file mode 100644 index 20dd10da9b83..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBindingContextImpl.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.service.ServiceRegistry; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.Index; - -import com.fasterxml.classmate.MemberResolver; -import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; -import com.fasterxml.classmate.TypeResolver; - -/** - * @author Steve Ebersole - */ -public class AnnotationBindingContextImpl implements AnnotationBindingContext { - private final MetadataImplementor metadata; - private final ValueHolder classLoaderService; - private final Index index; - private final TypeResolver typeResolver = new TypeResolver(); - private final Map, ResolvedType> resolvedTypeCache = new HashMap, ResolvedType>(); - - public AnnotationBindingContextImpl(MetadataImplementor metadata, Index index) { - this.metadata = metadata; - this.classLoaderService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public ClassLoaderService initialize() { - return AnnotationBindingContextImpl.this.metadata - .getServiceRegistry() - .getService( ClassLoaderService.class ); - } - } - ); - this.index = index; - } - - @Override - public Index getIndex() { - return index; - } - - @Override - public ClassInfo getClassInfo(String name) { - DotName dotName = DotName.createSimple( name ); - return index.getClassByName( dotName ); - } - - @Override - public void resolveAllTypes(String className) { - // the resolved type for the top level class in the hierarchy - Class clazz = classLoaderService.getValue().classForName( className ); - ResolvedType resolvedType = typeResolver.resolve( clazz ); - while ( resolvedType != null ) { - // todo - check whether there is already something in the map - resolvedTypeCache.put( clazz, resolvedType ); - resolvedType = resolvedType.getParentClass(); - if ( resolvedType != null ) { - clazz = resolvedType.getErasedType(); - } - } - } - - @Override - public ResolvedType getResolvedType(Class clazz) { - // todo - error handling - return resolvedTypeCache.get( clazz ); - } - - @Override - public ResolvedTypeWithMembers resolveMemberTypes(ResolvedType type) { - // todo : is there a reason we create this resolver every time? - MemberResolver memberResolver = new MemberResolver( typeResolver ); - return memberResolver.resolve( type, null, null ); - } - - @Override - public ServiceRegistry getServiceRegistry() { - return getMetadataImplementor().getServiceRegistry(); - } - - @Override - public NamingStrategy getNamingStrategy() { - return metadata.getNamingStrategy(); - } - - @Override - public MappingDefaults getMappingDefaults() { - return metadata.getMappingDefaults(); - } - - @Override - public MetadataImplementor getMetadataImplementor() { - return metadata; - } - - @Override - public Class locateClassByName(String name) { - return classLoaderService.getValue().classForName( name ); - } - - private Map nameToJavaTypeMap = new HashMap(); - - @Override - public Type makeJavaType(String className) { - Type javaType = nameToJavaTypeMap.get( className ); - if ( javaType == null ) { - javaType = metadata.makeJavaType( className ); - nameToJavaTypeMap.put( className, javaType ); - } - return javaType; - } - - @Override - public ValueHolder> makeClassReference(String className) { - return new ValueHolder>( locateClassByName( className ) ); - } - - @Override - public String qualifyClassName(String name) { - return name; - } - - @Override - public boolean isGloballyQuotedIdentifiers() { - return metadata.isGloballyQuotedIdentifiers(); - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java deleted file mode 100644 index cf375fb65a7d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.hibernate.AssertionFailure; -import org.hibernate.HibernateException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.MetadataSourceProcessor; -import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder; -import org.hibernate.metamodel.source.annotations.global.FilterDefBinder; -import org.hibernate.metamodel.source.annotations.global.IdGeneratorBinder; -import org.hibernate.metamodel.source.annotations.global.QueryBinder; -import org.hibernate.metamodel.source.annotations.global.TableBinder; -import org.hibernate.metamodel.source.annotations.global.TypeDefBinder; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; -import org.hibernate.metamodel.source.annotations.xml.mocker.EntityMappingsMocker; -import org.hibernate.metamodel.source.binder.Binder; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.internal.MetadataImpl; - -import org.jboss.jandex.Index; -import org.jboss.jandex.Indexer; -import org.jboss.logging.Logger; - -/** - * Main class responsible to creating and binding the Hibernate meta-model from annotations. - * This binder only has to deal with the (jandex) annotation index/repository. XML configuration is already processed - * and pseudo annotations are created. - * - * @author Hardy Ferentschik - * @author Steve Ebersole - */ -public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProcessor { - private static final Logger LOG = Logger.getLogger( AnnotationMetadataSourceProcessorImpl.class ); - - private final MetadataImplementor metadata; - private AnnotationBindingContext bindingContext; - - public AnnotationMetadataSourceProcessorImpl(MetadataImpl metadata) { - this.metadata = metadata; - } - - @Override - @SuppressWarnings( { "unchecked" }) - public void prepare(MetadataSources sources) { - // create a jandex index from the annotated classes - Indexer indexer = new Indexer(); - for ( Class clazz : sources.getAnnotatedClasses() ) { - indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" ); - } - - // add package-info from the configured packages - for ( String packageName : sources.getAnnotatedPackages() ) { - indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" ); - } - - Index index = indexer.complete(); - - List> mappings = new ArrayList>(); - for ( JaxbRoot root : sources.getJaxbRootList() ) { - if ( root.getRoot() instanceof JaxbEntityMappings ) { - mappings.add( (JaxbRoot) root ); - } - } - if ( !mappings.isEmpty() ) { - index = parseAndUpdateIndex( mappings, index ); - } - - if ( index.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ) != null ) { - // todo : this needs to move to AnnotationBindingContext - // what happens right now is that specifying this in an orm.xml causes it to effect all orm.xmls - metadata.setGloballyQuotedIdentifiers( true ); - } - bindingContext = new AnnotationBindingContextImpl( metadata, index ); - } - - @Override - public void processIndependentMetadata(MetadataSources sources) { - assertBindingContextExists(); - TypeDefBinder.bind( bindingContext ); - } - - private void assertBindingContextExists() { - if ( bindingContext == null ) { - throw new AssertionFailure( "The binding context should exist. Has prepare been called!?" ); - } - } - - @Override - public void processTypeDependentMetadata(MetadataSources sources) { - assertBindingContextExists(); - IdGeneratorBinder.bind( bindingContext ); - } - - @Override - public void processMappingMetadata(MetadataSources sources, List processedEntityNames) { - assertBindingContextExists(); - // need to order our annotated entities into an order we can process - Set hierarchies = EntityHierarchyBuilder.createEntityHierarchies( bindingContext ); - - Binder binder = new Binder( bindingContext.getMetadataImplementor(), new ArrayList() ); - for ( EntityHierarchy hierarchy : hierarchies ) { - binder.processEntityHierarchy( hierarchy ); - } - } - - @Override - public void processMappingDependentMetadata(MetadataSources sources) { - TableBinder.bind( bindingContext ); - FetchProfileBinder.bind( bindingContext ); - QueryBinder.bind( bindingContext ); - FilterDefBinder.bind( bindingContext ); - } - - private Index parseAndUpdateIndex(List> mappings, Index annotationIndex) { - List list = new ArrayList( mappings.size() ); - for ( JaxbRoot jaxbRoot : mappings ) { - list.add( jaxbRoot.getRoot() ); - } - return new EntityMappingsMocker( list, annotationIndex, metadata.getServiceRegistry() ).mockNewIndex(); - } - - private void indexClass(Indexer indexer, String className) { - InputStream stream = metadata.getServiceRegistry().getService( ClassLoaderService.class ).locateResourceStream( - className - ); - try { - indexer.index( stream ); - } - catch ( IOException e ) { - throw new HibernateException( "Unable to open input stream for class " + className, e ); - } - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java deleted file mode 100644 index 1584c5c0d0e0..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.AccessType; - -import org.hibernate.AnnotationException; -import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.annotations.entity.EntityClass; -import org.hibernate.metamodel.source.annotations.entity.RootEntitySourceImpl; -import org.hibernate.metamodel.source.annotations.entity.SubclassEntitySourceImpl; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.binder.EntitySource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.Index; -import org.jboss.jandex.MethodInfo; - -/** - * Given a (jandex) annotation index build processes all classes with JPA relevant annotations and pre-orders - * JPA entities respectively their inheritance hierarchy. - * - * @author Hardy Ferentschik - */ -public class EntityHierarchyBuilder { - private static final DotName OBJECT = DotName.createSimple( Object.class.getName() ); - - /** - * Pre-processes the annotated entities from the index and create a set of entity hierarchies which can be bound - * to the metamodel. - * - * @param bindingContext The binding context, giving access to needed services and information - * - * @return a set of {@code EntityHierarchy} instances. - */ - public static Set createEntityHierarchies(AnnotationBindingContext bindingContext) { - Set hierarchies = new HashSet(); - - List processedEntities = new ArrayList(); - Map> classToDirectSubClassMap = new HashMap>(); - Index index = bindingContext.getIndex(); - for ( ClassInfo info : index.getKnownClasses() ) { - if ( !isEntityClass( info ) ) { - continue; - } - - if ( processedEntities.contains( info.name() ) ) { - continue; - } - - ClassInfo rootClassInfo = findRootEntityClassInfo( index, info ); - List rootClassWithAllSubclasses = new ArrayList(); - // the root entity might have some mapped super classes which we have to take into consideration - // for inheritance type and default access - addMappedSuperclasses( index, rootClassInfo, rootClassWithAllSubclasses ); - - // collect the current root entity and all its subclasses - processHierarchy( - bindingContext, - rootClassInfo, - rootClassWithAllSubclasses, - processedEntities, - classToDirectSubClassMap - ); - - AccessType defaultAccessType = determineDefaultAccessType( rootClassWithAllSubclasses ); - InheritanceType hierarchyInheritanceType = determineInheritanceType( - rootClassInfo, - rootClassWithAllSubclasses - ); - - // create the root entity source - EntityClass rootEntityClass = new EntityClass( - rootClassInfo, - null, - defaultAccessType, - hierarchyInheritanceType, - bindingContext - ); - RootEntitySourceImpl rootSource = new RootEntitySourceImpl( rootEntityClass ); - - addSubclassEntitySources( - bindingContext, - classToDirectSubClassMap, - defaultAccessType, - hierarchyInheritanceType, - rootEntityClass, - rootSource - ); - - - hierarchies.add( new EntityHierarchyImpl( rootSource, hierarchyInheritanceType ) ); - } - return hierarchies; - } - - private static void addSubclassEntitySources(AnnotationBindingContext bindingContext, - Map> classToDirectSubClassMap, - AccessType defaultAccessType, - InheritanceType hierarchyInheritanceType, - EntityClass entityClass, - EntitySource entitySource) { - List subClassInfoList = classToDirectSubClassMap.get( DotName.createSimple( entitySource.getClassName() ) ); - if ( subClassInfoList == null ) { - return; - } - for ( ClassInfo subClassInfo : subClassInfoList ) { - EntityClass subclassEntityClass = new EntityClass( - subClassInfo, - entityClass, - defaultAccessType, - hierarchyInheritanceType, - bindingContext - ); - SubclassEntitySource subclassEntitySource = new SubclassEntitySourceImpl( subclassEntityClass ); - entitySource.add( subclassEntitySource ); - addSubclassEntitySources( - bindingContext, - classToDirectSubClassMap, - defaultAccessType, - hierarchyInheritanceType, - subclassEntityClass, - subclassEntitySource - ); - } - } - - /** - * Finds the root entity starting at the entity given by {@code info}. The root entity is not the highest superclass - * in a java type sense, but the highest superclass which is also an entity (annotated w/ {@code @Entity}. - * - * @param index the annotation repository - * @param info the class info representing an entity - * - * @return Finds the root entity starting at the entity given by {@code info} - */ - private static ClassInfo findRootEntityClassInfo(Index index, ClassInfo info) { - ClassInfo rootEntity = info; - - DotName superName = info.superName(); - ClassInfo tmpInfo; - // walk up the hierarchy until java.lang.Object - while ( !OBJECT.equals( superName ) ) { - tmpInfo = index.getClassByName( superName ); - if ( isEntityClass( tmpInfo ) ) { - rootEntity = tmpInfo; - } - superName = tmpInfo.superName(); - } - return rootEntity; - } - - private static void addMappedSuperclasses(Index index, ClassInfo info, List classInfoList) { - DotName superName = info.superName(); - ClassInfo tmpInfo; - // walk up the hierarchy until java.lang.Object - while ( !OBJECT.equals( superName ) ) { - tmpInfo = index.getClassByName( superName ); - if ( isMappedSuperclass( tmpInfo ) ) { - classInfoList.add( tmpInfo ); - } - superName = tmpInfo.superName(); - } - } - - /** - * This method does several things. - *
      - *
    • Collect all java subclasses (recursive) of {@code classInfo} in {@code rootClassWithAllSubclasses}.
    • - *
    • Keeping track of all processed classed annotated with {@code @Entity}
    • - *
    • Building up a map of class to direct subclass list
    • - *
    - * - * @param bindingContext the binding context - * @param classInfo the current class info - * @param rootClassWithAllSubclasses used to collect all classes in the hierarchy starting at {@code classInfo} - * @param processedEntities Used to keep track of all processed entities - * @param classToDirectSubclassMap Create a map of class to direct subclass - */ - private static void processHierarchy(AnnotationBindingContext bindingContext, - ClassInfo classInfo, - List rootClassWithAllSubclasses, - List processedEntities, - Map> classToDirectSubclassMap) { - processedEntities.add( classInfo.name() ); - rootClassWithAllSubclasses.add( classInfo ); - List subClasses = bindingContext.getIndex().getKnownDirectSubclasses( classInfo.name() ); - - // if there are no more subclasses we reached the leaf class. In order to properly resolve generics we - // need to resolve the type information using this leaf class - if ( subClasses.isEmpty() ) { - bindingContext.resolveAllTypes( classInfo.name().toString() ); - } - - for ( ClassInfo subClassInfo : subClasses ) { - addSubClassToSubclassMap( classInfo.name(), subClassInfo, classToDirectSubclassMap ); - processHierarchy( - bindingContext, - subClassInfo, - rootClassWithAllSubclasses, - processedEntities, - classToDirectSubclassMap - ); - } - } - - private static void addSubClassToSubclassMap(DotName name, ClassInfo subClassInfo, Map> classToDirectSubclassMap) { - if ( classToDirectSubclassMap.containsKey( name ) ) { - classToDirectSubclassMap.get( name ).add( subClassInfo ); - } - else { - List subclassList = new ArrayList(); - subclassList.add( subClassInfo ); - classToDirectSubclassMap.put( name, subclassList ); - } - } - - /** - * Checks whether the class info represents an entity. - * - * @param info the jandex class info - * - * @return {@code true} if the class represented by {@code info} is annotated with {@code @Entity}, {@code false} otherwise. - */ - private static boolean isEntityClass(ClassInfo info) { - if ( info == null ) { - return false; - } - - // we are only interested in building the class hierarchies for @Entity - AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( info, JPADotNames.ENTITY ); - if ( jpaEntityAnnotation == null ) { - return false; - } - - // some sanity checks - AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation( - info, JPADotNames.MAPPED_SUPERCLASS - ); - String className = info.toString(); - assertNotEntityAndMappedSuperClass( jpaEntityAnnotation, mappedSuperClassAnnotation, className ); - - AnnotationInstance embeddableAnnotation = JandexHelper.getSingleAnnotation( - info, JPADotNames.EMBEDDABLE - ); - assertNotEntityAndEmbeddable( jpaEntityAnnotation, embeddableAnnotation, className ); - - return true; - } - - /** - * Checks whether the class info represents a mapped superclass. - * - * @param info the jandex class info - * - * @return {@code true} if the class represented by {@code info} is annotated with {@code @MappedSuperclass}, {@code false} otherwise. - */ - private static boolean isMappedSuperclass(ClassInfo info) { - if ( info == null ) { - return false; - } - - // we are only interested in building the class hierarchies for @Entity - AnnotationInstance mappedSuperclassAnnotation = JandexHelper.getSingleAnnotation( - info, - JPADotNames.MAPPED_SUPERCLASS - ); - return mappedSuperclassAnnotation != null; - } - - private static void assertNotEntityAndMappedSuperClass(AnnotationInstance jpaEntityAnnotation, AnnotationInstance mappedSuperClassAnnotation, String className) { - if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) { - throw new AnnotationException( - "An entity cannot be annotated with both @Entity and @MappedSuperclass. " + className + " has both annotations." - ); - } - } - - private static void assertNotEntityAndEmbeddable(AnnotationInstance jpaEntityAnnotation, AnnotationInstance embeddableAnnotation, String className) { - if ( jpaEntityAnnotation != null && embeddableAnnotation != null ) { - throw new AnnotationException( - "An entity cannot be annotated with both @Entity and @Embeddable. " + className + " has both annotations." - ); - } - } - - /** - * @param classes the classes in the hierarchy - * - * @return Returns the default access type for the configured class hierarchy independent of explicit - * {@code AccessType} annotations. The default access type is determined by the placement of the - * annotations. - */ - private static AccessType determineDefaultAccessType(List classes) { - AccessType accessTypeByEmbeddedIdPlacement = null; - AccessType accessTypeByIdPlacement = null; - for ( ClassInfo info : classes ) { - List idAnnotations = info.annotations().get( JPADotNames.ID ); - List embeddedIdAnnotations = info.annotations().get( JPADotNames.EMBEDDED_ID ); - - if ( CollectionHelper.isNotEmpty( embeddedIdAnnotations ) ) { - accessTypeByEmbeddedIdPlacement = determineAccessTypeByIdPlacement( embeddedIdAnnotations ); - } - if ( CollectionHelper.isNotEmpty( idAnnotations ) ) { - accessTypeByIdPlacement = determineAccessTypeByIdPlacement( idAnnotations ); - } - } - if ( accessTypeByEmbeddedIdPlacement != null ) { - return accessTypeByEmbeddedIdPlacement; - } - else if ( accessTypeByIdPlacement != null ) { - return accessTypeByIdPlacement; - } - else { - return throwIdNotFoundAnnotationException( classes ); - } - } - - private static AccessType determineAccessTypeByIdPlacement(List idAnnotations) { - AccessType accessType = null; - for ( AnnotationInstance annotation : idAnnotations ) { - AccessType tmpAccessType; - if ( annotation.target() instanceof FieldInfo ) { - tmpAccessType = AccessType.FIELD; - } - else if ( annotation.target() instanceof MethodInfo ) { - tmpAccessType = AccessType.PROPERTY; - } - else { - throw new AnnotationException( "Invalid placement of @Id annotation" ); - } - - if ( accessType == null ) { - accessType = tmpAccessType; - } - else { - if ( !accessType.equals( tmpAccessType ) ) { - throw new AnnotationException( "Inconsistent placement of @Id annotation within hierarchy " ); - } - } - } - return accessType; - } - - private static InheritanceType determineInheritanceType(ClassInfo rootClassInfo, List classes) { - if(classes.size() == 1) { - return InheritanceType.NO_INHERITANCE; - } - - // if we have more than one entity class the default is SINGLE_TABLE - InheritanceType inheritanceType = InheritanceType.SINGLE_TABLE; - AnnotationInstance inheritanceAnnotation = JandexHelper.getSingleAnnotation( - rootClassInfo, JPADotNames.INHERITANCE - ); - if ( inheritanceAnnotation != null ) { - String enumName = inheritanceAnnotation.value( "strategy" ).asEnum(); - javax.persistence.InheritanceType jpaInheritanceType = Enum.valueOf( - javax.persistence.InheritanceType.class, enumName - ); - inheritanceType = InheritanceType.get( jpaInheritanceType ); - } - - // sanity check that the is no other @Inheritance annotation in the hierarchy - for ( ClassInfo info : classes ) { - if ( rootClassInfo.equals( info ) ) { - continue; - } - inheritanceAnnotation = JandexHelper.getSingleAnnotation( - info, JPADotNames.INHERITANCE - ); - if ( inheritanceAnnotation != null ) { - throw new AnnotationException( - String.format( - "The inheritance type for %s must be specified on the root entity %s", - hierarchyListString( classes ), - rootClassInfo.name().toString() - ) - ); - } - } - - return inheritanceType; - } - - private static AccessType throwIdNotFoundAnnotationException(List classes) { - StringBuilder builder = new StringBuilder(); - builder.append( "Unable to determine identifier attribute for class hierarchy consisting of the classe(s) " ); - builder.append( hierarchyListString( classes ) ); - throw new AnnotationException( builder.toString() ); - } - - private static String hierarchyListString(List classes) { - StringBuilder builder = new StringBuilder(); - builder.append( "[" ); - - int count = 0; - for ( ClassInfo info : classes ) { - builder.append( info.name().toString() ); - if ( count < classes.size() - 1 ) { - builder.append( ", " ); - } - count++; - } - builder.append( "]" ); - return builder.toString(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyImpl.java deleted file mode 100644 index 2d970afbb6ee..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.binder.RootEntitySource; - -/** - * @author Hardy Ferentschik - */ -public class EntityHierarchyImpl implements EntityHierarchy { - private final RootEntitySource rootEntitySource; - private final InheritanceType inheritanceType; - - public EntityHierarchyImpl(RootEntitySource source, InheritanceType inheritanceType) { - this.rootEntitySource = source; - this.inheritanceType = inheritanceType; - } - - @Override - public InheritanceType getHierarchyInheritanceType() { - return inheritanceType; - } - - @Override - public RootEntitySource getRootEntitySource() { - return rootEntitySource; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java deleted file mode 100644 index 98ae17a7209c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import javax.persistence.CascadeType; -import javax.persistence.GenerationType; - -import org.hibernate.AssertionFailure; -import org.hibernate.FetchMode; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.id.MultipleHiLoPerTableGenerator; -import org.hibernate.internal.util.collections.CollectionHelper; - -/** - * Helper class which converts between different enum types. - * - * @author Hardy Ferentschik - */ -public class EnumConversionHelper { - private EnumConversionHelper() { - } - - public static String generationTypeToGeneratorStrategyName(GenerationType generatorEnum, boolean useNewGeneratorMappings) { - switch ( generatorEnum ) { - case IDENTITY: - return "identity"; - case AUTO: - return useNewGeneratorMappings - ? "enhanced-sequence" - : "native"; - case TABLE: - return useNewGeneratorMappings - ? "enhanced-table" - : MultipleHiLoPerTableGenerator.class.getName(); - case SEQUENCE: - return useNewGeneratorMappings - ? "enhanced-sequence" - : "seqhilo"; - } - throw new AssertionFailure( "Unknown GeneratorType: " + generatorEnum ); - } - - public static CascadeStyle cascadeTypeToCascadeStyle(CascadeType cascadeType) { - switch ( cascadeType ) { - case ALL: { - return CascadeStyles.ALL; - } - case PERSIST: { - return CascadeStyles.PERSIST; - } - case MERGE: { - return CascadeStyles.MERGE; - } - case REMOVE: { - return CascadeStyles.DELETE; - } - case REFRESH: { - return CascadeStyles.REFRESH; - } - case DETACH: { - return CascadeStyles.EVICT; - } - default: { - throw new AssertionFailure( "Unknown cascade type" ); - } - } - } - - public static FetchMode annotationFetchModeToHibernateFetchMode(org.hibernate.annotations.FetchMode annotationFetchMode) { - switch ( annotationFetchMode ) { - case JOIN: { - return FetchMode.JOIN; - } - case SELECT: { - return FetchMode.SELECT; - } - case SUBSELECT: { - // todo - is this correct? can the conversion be made w/o any additional information, eg - // todo - association nature - return FetchMode.SELECT; - } - default: { - throw new AssertionFailure( "Unknown fetch mode" ); - } - } - } - - public static Set cascadeTypeToCascadeStyleSet(Set cascadeTypes) { - if ( CollectionHelper.isEmpty( cascadeTypes ) ) { - return Collections.emptySet(); - } - Set cascadeStyleSet = new HashSet(); - for ( CascadeType cascadeType : cascadeTypes ) { - cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); - } - return cascadeStyleSet; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java deleted file mode 100644 index 0a7270300d17..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.beans.Introspector; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.HibernateException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.util.type.PrimitiveWrapperHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.Index; -import org.jboss.jandex.Indexer; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.Type; - -/** - * Utility methods for working with the jandex annotation index. - * - * @author Hardy Ferentschik - */ -public class JandexHelper { - private static final Map DEFAULT_VALUES_BY_ELEMENT = new HashMap(); - - private JandexHelper() { - } - - /** - * Retrieves a jandex annotation element value. If the value is {@code null}, the default value specified in the - * annotation class is retrieved instead. - *

    - * There are two special cases. {@code Class} parameters should be retrieved as strings (and then can later be - * loaded) and enumerated values should be retrieved via {@link #getEnumValue(AnnotationInstance, String, Class)}. - *

    - * - * @param annotation the annotation containing the element with the supplied name - * @param element the name of the element value to be retrieve - * @param type the type of element to retrieve. The following types are supported: - *
      - *
    • Byte
    • - *
    • Short
    • - *
    • Integer
    • - *
    • Character
    • - *
    • Float
    • - *
    • Double
    • - *
    • Long
    • - *
    • Boolean
    • - *
    • String
    • - *
    • AnnotationInstance
    • - * - * @return the value if not {@code null}, else the default value if not - * {@code null}, else {@code null}. - * - * @throws AssertionFailure in case the specified {@code type} is a class instance or the specified type causes a {@code ClassCastException} - * when retrieving the value. - */ - @SuppressWarnings("unchecked") - public static T getValue(AnnotationInstance annotation, String element, Class type) throws AssertionFailure { - if ( Class.class.equals( type ) ) { - throw new AssertionFailure( - "Annotation parameters of type Class should be retrieved as strings (fully qualified class names)" - ); - } - - if ( type.isPrimitive() ) { - type = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( type ).getWrapperClass(); - } - - // try getting the untyped value from Jandex - AnnotationValue annotationValue = annotation.value( element ); - - try { - if ( annotationValue != null ) { - return explicitAnnotationParameter( annotationValue, type ); - } - else { - return defaultAnnotationParameter( getDefaultValue( annotation, element ), type ); - } - } - catch ( ClassCastException e ) { - throw new AssertionFailure( - String.format( - "the annotation property %s of annotation %s is not of type %s", - element, - annotation.name(), - type.getName() - ), - e - ); - } - } - - // THIS IS FOR 4.3.x AND SHOULD BE CONSIDERED TEMPORARY. HHH-8118 corrected CL use in JandexHelper by adding - // CLS as method arguments. But that was done in the metamodel branch only before I knew that master added a few - // uses. HHH-8316 needs it for 4.3. DO NOT LET THIS GET MERGED INTO METAMODEL! - public static T getValue(AnnotationInstance annotation, String element, Class type, - ClassLoaderService classLoaderService) throws AssertionFailure { - if ( Class.class.equals( type ) ) { - throw new AssertionFailure( - "Annotation parameters of type Class should be retrieved as strings (fully qualified class names)" - ); - } - - if ( type.isPrimitive() ) { - type = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( type ).getWrapperClass(); - } - - // try getting the untyped value from Jandex - AnnotationValue annotationValue = annotation.value( element ); - - try { - if ( annotationValue != null ) { - return explicitAnnotationParameter( annotationValue, type ); - } - else { - return defaultAnnotationParameter( getDefaultValue( annotation, element, classLoaderService ), type ); - } - } - catch ( ClassCastException e ) { - throw new AssertionFailure( - String.format( - "the annotation property %s of annotation %s is not of type %s", - element, - annotation.name(), - type.getName() - ), - e - ); - } - } - - /** - * Retrieves a jandex annotation element value, converting it to the supplied enumerated type. If the value is - * null, the default value specified in the annotation class is retrieved instead. - * - * @param an enumerated type - * @param annotation the annotation containing the enumerated element with the supplied name - * @param element the name of the enumerated element value to be retrieve - * @param type the type to which to convert the value before being returned - * - * @return the value converted to the supplied enumerated type if the value is not null, else the default value if - * not null, else null. - * - * @see #getValue(AnnotationInstance, String, Class) - */ - @SuppressWarnings("unchecked") - public static > T getEnumValue(AnnotationInstance annotation, String element, Class type) { - AnnotationValue val = annotation.value( element ); - if ( val == null ) { - return (T) getDefaultValue( annotation, element ); - } - return Enum.valueOf( type, val.asEnum() ); - } - - /** - * Expects a method or field annotation target and returns the property name for this target - * - * @param target the annotation target - * - * @return the property name of the target. For a field it is the field name and for a method name it is - * the method name stripped of 'is', 'has' or 'get' - */ - public static String getPropertyName(AnnotationTarget target) { - if ( !( target instanceof MethodInfo || target instanceof FieldInfo ) ) { - throw new AssertionFailure( "Unexpected annotation target " + target.toString() ); - } - - if ( target instanceof FieldInfo ) { - return ( (FieldInfo) target ).name(); - } - else { - final String methodName = ( (MethodInfo) target ).name(); - String propertyName; - if ( methodName.startsWith( "is" ) ) { - propertyName = Introspector.decapitalize( methodName.substring( 2 ) ); - } - else if ( methodName.startsWith( "has" ) ) { - propertyName = Introspector.decapitalize( methodName.substring( 3 ) ); - } - else if ( methodName.startsWith( "get" ) ) { - propertyName = Introspector.decapitalize( methodName.substring( 3 ) ); - } - else { - throw new AssertionFailure( "Expected a method following the Java Bean notation" ); - } - return propertyName; - } - } - - /** - * @param classInfo the class info from which to retrieve the annotation instance - * @param annotationName the annotation to retrieve from the class info - * - * @return the single annotation defined on the class or {@code null} in case the annotation is not specified at all - * - * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. - */ - public static AnnotationInstance getSingleAnnotation(ClassInfo classInfo, DotName annotationName) - throws AssertionFailure { - return getSingleAnnotation( classInfo.annotations(), annotationName ); - } - - /** - * @param annotations List of annotation instances keyed against their dot name. - * @param annotationName the annotation to retrieve from map - * - * @return the single annotation of the specified dot name or {@code null} in case the annotation is not specified at all - * - * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. - */ - public static AnnotationInstance getSingleAnnotation(Map> annotations, DotName annotationName) - throws AssertionFailure { - List annotationList = annotations.get( annotationName ); - if ( annotationList == null ) { - return null; - } - else if ( annotationList.size() == 1 ) { - return annotationList.get( 0 ); - } - else { - throw new AssertionFailure( - "Found more than one instance of the annotation " - + annotationList.get( 0 ).name().toString() - + ". Expected was one." - ); - } - } - - /** - * @param annotations List of annotation instances keyed against their dot name. - * @param annotationName the annotation to check - * - * @return returns {@code true} if the map contains only a single instance of specified annotation or {@code false} otherwise. - * - * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. - */ - public static boolean containsSingleAnnotations(Map> annotations, DotName annotationName) - throws AssertionFailure { - return getSingleAnnotation( annotations, annotationName ) != null; - } - - /** - * Creates a jandex index for the specified classes - * - * @param classLoaderService class loader service - * @param classes the classes to index - * - * @return an annotation repository w/ all the annotation discovered in the specified classes - */ - public static Index indexForClass(ClassLoaderService classLoaderService, Class... classes) { - Indexer indexer = new Indexer(); - for ( Class clazz : classes ) { - InputStream stream = classLoaderService.locateResourceStream( - clazz.getName().replace( '.', '/' ) + ".class" - ); - try { - indexer.index( stream ); - } - catch ( IOException e ) { - StringBuilder builder = new StringBuilder(); - builder.append( "[" ); - int count = 0; - for ( Class c : classes ) { - builder.append( c.getName() ); - if ( count < classes.length - 1 ) { - builder.append( "," ); - } - count++; - } - builder.append( "]" ); - throw new HibernateException( "Unable to create annotation index for " + builder.toString() ); - } - } - return indexer.complete(); - } - - public static Map> getMemberAnnotations(ClassInfo classInfo, String name) { - if ( classInfo == null ) { - throw new IllegalArgumentException( "classInfo cannot be null" ); - } - - if ( name == null ) { - throw new IllegalArgumentException( "name cannot be null" ); - } - - Map> annotations = new HashMap>(); - for ( List annotationList : classInfo.annotations().values() ) { - for ( AnnotationInstance instance : annotationList ) { - String targetName = null; - if ( instance.target() instanceof FieldInfo ) { - targetName = ( (FieldInfo) instance.target() ).name(); - } - else if ( instance.target() instanceof MethodInfo ) { - targetName = ( (MethodInfo) instance.target() ).name(); - } - if ( targetName != null && name.equals( targetName ) ) { - addAnnotationToMap( instance, annotations ); - } - } - } - return annotations; - } - - private static void addAnnotationToMap(AnnotationInstance instance, Map> annotations) { - DotName dotName = instance.name(); - List list; - if ( annotations.containsKey( dotName ) ) { - list = annotations.get( dotName ); - } - else { - list = new ArrayList(); - annotations.put( dotName, list ); - } - list.add( instance ); - } - - private static Object getDefaultValue(AnnotationInstance annotation, String element) { - String name = annotation.name().toString(); - String fqElement = name + '.' + element; - Object val = DEFAULT_VALUES_BY_ELEMENT.get( fqElement ); - if ( val != null ) { - return val; - } - try { - val = Index.class.getClassLoader().loadClass( name ).getMethod( element ).getDefaultValue(); - DEFAULT_VALUES_BY_ELEMENT.put( fqElement, val ); - return val == null ? null : val; - } - catch ( RuntimeException error ) { - throw error; - } - catch ( Exception error ) { - throw new AssertionFailure( - String.format( "The annotation %s does not define a parameter '%s'", name, element ), - error - ); - } - } - - // THIS IS FOR 4.3.x AND SHOULD BE CONSIDERED TEMPORARY. HHH-8118 corrected CL use in JandexHelper by adding - // CLS as method arguments. But that was done in the metamodel branch only before I knew that master added a few - // uses. HHH-8316 needs it for 4.3. DO NOT LET THIS GET MERGED INTO METAMODEL! - private static Object getDefaultValue(AnnotationInstance annotation, String element, - ClassLoaderService classLoaderService) { - String name = annotation.name().toString(); - String fqElement = name + '.' + element; - Object val = DEFAULT_VALUES_BY_ELEMENT.get( fqElement ); - if ( val != null ) { - return val; - } - try { - val = classLoaderService.classForName( name ).getMethod( element ).getDefaultValue(); - if ( val != null ) { - // Annotation parameters of type Class are handled using Strings - if ( val instanceof Class ) { - val = ( ( Class ) val ).getName(); - } - } - DEFAULT_VALUES_BY_ELEMENT.put( fqElement, val ); - return val; - } - catch ( RuntimeException error ) { - throw error; - } - catch ( Exception error ) { - throw new AssertionFailure( - String.format( "The annotation %s does not define a parameter '%s'", name, element ), - error - ); - } - } - - private static T defaultAnnotationParameter(Object defaultValue, Class type) { - Object returnValue = defaultValue; - - // resolve some mismatches between what's stored in jandex and what the defaults are for annotations - // in case of nested annotation arrays, jandex returns arrays of AnnotationInstances, hence we return - // an empty array of this type here - if ( defaultValue.getClass().isArray() && defaultValue.getClass().getComponentType().isAnnotation() ) { - returnValue = new AnnotationInstance[0]; - } - return type.cast( returnValue ); - } - - private static T explicitAnnotationParameter(AnnotationValue annotationValue, Class type) { - Object returnValue = annotationValue.value(); - - // if the jandex return type is Type we actually try to retrieve a class parameter - // for our purposes we just return the fqcn of the class - if ( returnValue instanceof Type ) { - returnValue = ( (Type) returnValue ).name().toString(); - } - - // arrays we have to handle explicitly - if ( type.isArray() ) { - AnnotationValue[] values = (AnnotationValue[]) returnValue; - Class componentType = type.getComponentType(); - Object[] arr = (Object[]) Array.newInstance( componentType, values.length ); - for ( int i = 0; i < values.length; i++ ) { - arr[i] = componentType.cast( values[i].value() ); - } - returnValue = arr; - } - - return type.cast( returnValue ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java deleted file mode 100644 index 8b1f1a49dc16..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ReflectionHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import java.beans.Introspector; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -/** - * Some helper methods for reflection tasks - * - * @author Hardy Ferentschik - */ -public class ReflectionHelper { - - private ReflectionHelper() { - } - - /** - * Process bean properties getter by applying the JavaBean naming conventions. - * - * @param member the member for which to get the property name. - * - * @return The bean method name with the "is" or "get" prefix stripped off, {@code null} - * the method name id not according to the JavaBeans standard. - */ - public static String getPropertyName(Member member) { - String name = null; - - if ( member instanceof Field ) { - name = member.getName(); - } - - if ( member instanceof Method ) { - String methodName = member.getName(); - if ( methodName.startsWith( "is" ) ) { - name = Introspector.decapitalize( methodName.substring( 2 ) ); - } - else if ( methodName.startsWith( "has" ) ) { - name = Introspector.decapitalize( methodName.substring( 3 ) ); - } - else if ( methodName.startsWith( "get" ) ) { - name = Introspector.decapitalize( methodName.substring( 3 ) ); - } - } - return name; - } - - public static boolean isProperty(Member m) { - if ( m instanceof Method ) { - Method method = (Method) m; - return !method.isSynthetic() - && !method.isBridge() - && !Modifier.isStatic( method.getModifiers() ) - && method.getParameterTypes().length == 0 - && ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) ); - } - else { - return !Modifier.isTransient( m.getModifiers() ) && !m.isSynthetic(); - } - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/UnknownInheritanceTypeException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/UnknownInheritanceTypeException.java deleted file mode 100644 index 1f492d5d6cbb..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/UnknownInheritanceTypeException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations; - -import org.hibernate.HibernateException; - -/** - * @author Steve Ebersole - */ -public class UnknownInheritanceTypeException extends HibernateException { - public UnknownInheritanceTypeException(String message) { - super( message ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java deleted file mode 100644 index 8c81080eace7..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.CascadeType; -import javax.persistence.FetchType; - -import org.hibernate.FetchMode; -import org.hibernate.annotations.NotFoundAction; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl; -import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; - -/** - * Represents an association attribute. - * - * @author Hardy Ferentschik - * @todo Check whether we need further subclasses for different association types. Needs to evolve during development (HF) - */ -public class AssociationAttribute extends MappedAttribute { - private final AttributeNature associationNature; - private final boolean ignoreNotFound; - private final String referencedEntityType; - private final String mappedBy; - private final Set cascadeTypes; - private final boolean isOptional; - private final boolean isLazy; - private final boolean isOrphanRemoval; - private final FetchMode fetchMode; - private final boolean mapsId; - private final String referencedIdAttributeName; - - private boolean isInsertable = true; - private boolean isUpdatable = true; - private AttributeTypeResolver resolver; - - public static AssociationAttribute createAssociationAttribute(String name, - Class attributeType, - AttributeNature attributeNature, - String accessType, - Map> annotations, - EntityBindingContext context) { - return new AssociationAttribute( - name, - attributeType, - attributeNature, - accessType, - annotations, - context - ); - } - - private AssociationAttribute(String name, - Class javaType, - AttributeNature associationType, - String accessType, - Map> annotations, - EntityBindingContext context) { - super( name, javaType, accessType, annotations, context ); - this.associationNature = associationType; - this.ignoreNotFound = ignoreNotFound(); - - AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation( - annotations, - associationType.getAnnotationDotName() - ); - - // using jandex we don't really care which exact type of annotation we are dealing with - this.referencedEntityType = determineReferencedEntityType( associationAnnotation ); - this.mappedBy = determineMappedByAttributeName( associationAnnotation ); - this.isOptional = determineOptionality( associationAnnotation ); - this.isLazy = determineFetchType( associationAnnotation ); - this.isOrphanRemoval = determineOrphanRemoval( associationAnnotation ); - this.cascadeTypes = determineCascadeTypes( associationAnnotation ); - - this.fetchMode = determineFetchMode(); - this.referencedIdAttributeName = determineMapsId(); - this.mapsId = referencedIdAttributeName != null; - } - - public boolean isIgnoreNotFound() { - return ignoreNotFound; - } - - public String getReferencedEntityType() { - return referencedEntityType; - } - - public String getMappedBy() { - return mappedBy; - } - - public AttributeNature getAssociationNature() { - return associationNature; - } - - public Set getCascadeTypes() { - return cascadeTypes; - } - - public boolean isOrphanRemoval() { - return isOrphanRemoval; - } - - public FetchMode getFetchMode() { - return fetchMode; - } - - public String getReferencedIdAttributeName() { - return referencedIdAttributeName; - } - - public boolean mapsId() { - return mapsId; - } - - @Override - public AttributeTypeResolver getHibernateTypeResolver() { - if ( resolver == null ) { - resolver = getDefaultHibernateTypeResolver(); - } - return resolver; - } - - @Override - public boolean isLazy() { - return isLazy; - } - - @Override - public boolean isOptional() { - return isOptional; - } - - @Override - public boolean isInsertable() { - return isInsertable; - } - - @Override - public boolean isUpdatable() { - return isUpdatable; - } - - @Override - public PropertyGeneration getPropertyGeneration() { - return PropertyGeneration.NEVER; - } - - private AttributeTypeResolver getDefaultHibernateTypeResolver() { - return new CompositeAttributeTypeResolver( new AttributeTypeResolverImpl( this ) ); - } - - private boolean ignoreNotFound() { - NotFoundAction action = NotFoundAction.EXCEPTION; - AnnotationInstance notFoundAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.NOT_FOUND - ); - if ( notFoundAnnotation != null ) { - AnnotationValue actionValue = notFoundAnnotation.value( "action" ); - if ( actionValue != null ) { - action = Enum.valueOf( NotFoundAction.class, actionValue.asEnum() ); - } - } - - return NotFoundAction.IGNORE.equals( action ); - } - - private boolean determineOptionality(AnnotationInstance associationAnnotation) { - boolean optional = true; - - AnnotationValue optionalValue = associationAnnotation.value( "optional" ); - if ( optionalValue != null ) { - optional = optionalValue.asBoolean(); - } - - return optional; - } - - private boolean determineOrphanRemoval(AnnotationInstance associationAnnotation) { - boolean orphanRemoval = false; - AnnotationValue orphanRemovalValue = associationAnnotation.value( "orphanRemoval" ); - if ( orphanRemovalValue != null ) { - orphanRemoval = orphanRemovalValue.asBoolean(); - } - return orphanRemoval; - } - - private boolean determineFetchType(AnnotationInstance associationAnnotation) { - boolean lazy = false; - AnnotationValue fetchValue = associationAnnotation.value( "fetch" ); - if ( fetchValue != null ) { - FetchType fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() ); - if ( FetchType.LAZY.equals( fetchType ) ) { - lazy = true; - } - } - return lazy; - } - - private String determineReferencedEntityType(AnnotationInstance associationAnnotation) { - String targetTypeName = getAttributeType().getName(); - - AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.TARGET - ); - if ( targetAnnotation != null ) { - targetTypeName = targetAnnotation.value().asClass().name().toString(); - } - - AnnotationValue targetEntityValue = associationAnnotation.value( "targetEntity" ); - if ( targetEntityValue != null ) { - targetTypeName = targetEntityValue.asClass().name().toString(); - } - - return targetTypeName; - } - - private String determineMappedByAttributeName(AnnotationInstance associationAnnotation) { - String mappedBy = null; - AnnotationValue mappedByAnnotationValue = associationAnnotation.value( "mappedBy" ); - if ( mappedByAnnotationValue != null ) { - mappedBy = mappedByAnnotationValue.asString(); - } - - return mappedBy; - } - - private Set determineCascadeTypes(AnnotationInstance associationAnnotation) { - Set cascadeTypes = new HashSet(); - AnnotationValue cascadeValue = associationAnnotation.value( "cascade" ); - if ( cascadeValue != null ) { - String[] cascades = cascadeValue.asEnumArray(); - for ( String s : cascades ) { - cascadeTypes.add( Enum.valueOf( CascadeType.class, s ) ); - } - } - return cascadeTypes; - } - - private FetchMode determineFetchMode() { - FetchMode mode = FetchMode.DEFAULT; - - AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.FETCH ); - if ( fetchAnnotation != null ) { - org.hibernate.annotations.FetchMode annotationFetchMode = JandexHelper.getEnumValue( - fetchAnnotation, - "value", - org.hibernate.annotations.FetchMode.class - ); - mode = EnumConversionHelper.annotationFetchModeToHibernateFetchMode( annotationFetchMode ); - } - - return mode; - } - - private String determineMapsId() { - String referencedIdAttributeName; - AnnotationInstance mapsIdAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.MAPS_ID ); - if ( mapsIdAnnotation == null ) { - return null; - } - - if ( !( AttributeNature.MANY_TO_ONE.equals( getAssociationNature() ) || AttributeNature.MANY_TO_ONE - .equals( getAssociationNature() ) ) ) { - throw new MappingException( - "@MapsId can only be specified on a many-to-one or one-to-one associations", - getContext().getOrigin() - ); - } - - referencedIdAttributeName = JandexHelper.getValue( mapsIdAnnotation, "value", String.class ); - - return referencedIdAttributeName; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java deleted file mode 100644 index 8cf92281983d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.source.annotations.JPADotNames; - -import org.jboss.jandex.DotName; - -/** - * An enum defining the type of a mapped attribute. - * - * @author Hardy Ferentschik - */ -public enum AttributeNature { - BASIC( JPADotNames.BASIC ), - ONE_TO_ONE( JPADotNames.ONE_TO_ONE ), - ONE_TO_MANY( JPADotNames.ONE_TO_MANY ), - MANY_TO_ONE( JPADotNames.MANY_TO_ONE ), - MANY_TO_MANY( JPADotNames.MANY_TO_MANY ), - ELEMENT_COLLECTION( JPADotNames.ELEMENT_COLLECTION ), - EMBEDDED_ID( JPADotNames.EMBEDDED_ID ), - EMBEDDED( JPADotNames.EMBEDDED ); - - private final DotName annotationDotName; - - AttributeNature(DotName annotationDotName) { - this.annotationDotName = annotationDotName; - } - - public DotName getAnnotationDotName() { - return annotationDotName; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java deleted file mode 100644 index 1f36ab1f5877..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.AssertionFailure; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; - -/** - * Contains the information about a single {@link javax.persistence.AttributeOverride}. Instances of this class - * are creating during annotation processing and then applied onto the persistence attributes. - * - * @author Hardy Ferentschik - * @todo Take care of prefixes of the form 'element', 'key' and 'value'. Add another type enum to handle this. (HF) - */ -public class AttributeOverride { - private static final String PROPERTY_PATH_SEPARATOR = "."; - private final ColumnValues columnValues; - private final String attributePath; - - public AttributeOverride(AnnotationInstance attributeOverrideAnnotation) { - this( null, attributeOverrideAnnotation ); - } - - public AttributeOverride(String prefix, AnnotationInstance attributeOverrideAnnotation) { - if ( attributeOverrideAnnotation == null ) { - throw new IllegalArgumentException( "An AnnotationInstance needs to be passed" ); - } - - if ( !JPADotNames.ATTRIBUTE_OVERRIDE.equals( attributeOverrideAnnotation.name() ) ) { - throw new AssertionFailure( "A @AttributeOverride annotation needs to be passed to the constructor" ); - } - - columnValues = new ColumnValues( - JandexHelper.getValue( - attributeOverrideAnnotation, - "column", - AnnotationInstance.class - ) - ); - attributePath = createAttributePath( - prefix, - JandexHelper.getValue( attributeOverrideAnnotation, "name", String.class ) - ); - } - - public ColumnValues getColumnValues() { - return columnValues; - } - - public String getAttributePath() { - return attributePath; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "AttributeOverride" ); - sb.append( "{columnValues=" ).append( columnValues ); - sb.append( ", attributePath='" ).append( attributePath ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - AttributeOverride that = (AttributeOverride) o; - - if ( attributePath != null ? !attributePath.equals( that.attributePath ) : that.attributePath != null ) { - return false; - } - if ( columnValues != null ? !columnValues.equals( that.columnValues ) : that.columnValues != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = columnValues != null ? columnValues.hashCode() : 0; - result = 31 * result + ( attributePath != null ? attributePath.hashCode() : 0 ); - return result; - } - - private String createAttributePath(String prefix, String name) { - String path = ""; - if ( StringHelper.isNotEmpty( prefix ) ) { - path += prefix; - } - if ( StringHelper.isNotEmpty( path ) && !path.endsWith( PROPERTY_PATH_SEPARATOR ) ) { - path += PROPERTY_PATH_SEPARATOR; - } - path += name; - return path; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java deleted file mode 100644 index 280edcf9bfdb..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import javax.persistence.FetchType; -import javax.persistence.GenerationType; - -import org.hibernate.AnnotationException; -import org.hibernate.annotations.GenerationTime; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl; -import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.EnumeratedTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.LobTypeResolver; -import org.hibernate.metamodel.source.annotations.attribute.type.TemporalTypeResolver; -import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; - -/** - * Represent a basic attribute (explicitly or implicitly mapped). - * - * @author Hardy Ferentschik - */ -public class BasicAttribute extends MappedAttribute { - - /** - * The id generator in case this basic attribute represents an simple id. Will be {@code null} in case there - * is no explicit id generator or the containing entity does not have a simple id - */ - private final IdGenerator idGenerator; - - /** - * Is this a versioned property (annotated w/ {@code @Version}. - */ - private final boolean isVersioned; - - /** - * Is this property lazy loaded (see {@link javax.persistence.Basic}). - */ - private boolean isLazy = false; - - /** - * Is this property optional (see {@link javax.persistence.Basic}). - */ - private boolean isOptional = true; - - /** - * Are this properties generated and when - */ - private PropertyGeneration propertyGeneration; - private boolean isInsertable = true; - private boolean isUpdatable = true; - - private final String customWriteFragment; - private final String customReadFragment; - private final String checkCondition; - private AttributeTypeResolver resolver; - - public static BasicAttribute createSimpleAttribute(String name, - Class attributeType, - Map> annotations, - String accessType, - EntityBindingContext context) { - return new BasicAttribute( name, attributeType, accessType, annotations, context ); - } - - BasicAttribute(String name, - Class attributeType, - String accessType, - Map> annotations, - EntityBindingContext context) { - super( name, attributeType, accessType, annotations, context ); - - AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION ); - isVersioned = versionAnnotation != null; - - if ( isId() ) { - // an id must be unique and cannot be nullable - getColumnValues().setUnique( true ); - getColumnValues().setNullable( false ); - idGenerator = checkGeneratedValueAnnotation(); - } - else { - idGenerator = null; - } - - checkBasicAnnotation(); - checkGeneratedAnnotation(); - - List columnTransformerAnnotations = getAllColumnTransformerAnnotations(); - String[] readWrite = createCustomReadWrite( columnTransformerAnnotations ); - this.customReadFragment = readWrite[0]; - this.customWriteFragment = readWrite[1]; - this.checkCondition = parseCheckAnnotation(); - } - - public boolean isVersioned() { - return isVersioned; - } - - public boolean isLazy() { - return isLazy; - } - - public boolean isOptional() { - return isOptional; - } - - public boolean isInsertable() { - return isInsertable; - } - - public boolean isUpdatable() { - return isUpdatable; - } - - public PropertyGeneration getPropertyGeneration() { - return propertyGeneration; - } - - public String getCustomWriteFragment() { - return customWriteFragment; - } - - public String getCustomReadFragment() { - return customReadFragment; - } - - public String getCheckCondition() { - return checkCondition; - } - - public IdGenerator getIdGenerator() { - return idGenerator; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "SimpleAttribute" ); - sb.append( "{name=" ).append( getName() ); - return sb.toString(); - } - - private void checkBasicAnnotation() { - AnnotationInstance basicAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.BASIC ); - if ( basicAnnotation != null ) { - FetchType fetchType = FetchType.LAZY; - AnnotationValue fetchValue = basicAnnotation.value( "fetch" ); - if ( fetchValue != null ) { - fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() ); - } - this.isLazy = fetchType == FetchType.LAZY; - - AnnotationValue optionalValue = basicAnnotation.value( "optional" ); - if ( optionalValue != null ) { - this.isOptional = optionalValue.asBoolean(); - } - } - } - - // TODO - there is more todo for updatable and insertable. Checking the @Generated annotation is only one part (HF) - private void checkGeneratedAnnotation() { - AnnotationInstance generatedAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.GENERATED - ); - if ( generatedAnnotation != null ) { - this.isInsertable = false; - - AnnotationValue generationTimeValue = generatedAnnotation.value(); - if ( generationTimeValue != null ) { - GenerationTime genTime = Enum.valueOf( GenerationTime.class, generationTimeValue.asEnum() ); - if ( GenerationTime.ALWAYS.equals( genTime ) ) { - this.isUpdatable = false; - this.propertyGeneration = PropertyGeneration.parse( genTime.toString().toLowerCase() ); - } - } - } - } - - private List getAllColumnTransformerAnnotations() { - List allColumnTransformerAnnotations = new ArrayList(); - - // not quite sure about the usefulness of @ColumnTransformers (HF) - AnnotationInstance columnTransformersAnnotations = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.COLUMN_TRANSFORMERS - ); - if ( columnTransformersAnnotations != null ) { - AnnotationInstance[] annotationInstances = allColumnTransformerAnnotations.get( 0 ).value().asNestedArray(); - allColumnTransformerAnnotations.addAll( Arrays.asList( annotationInstances ) ); - } - - AnnotationInstance columnTransformerAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.COLUMN_TRANSFORMER - ); - if ( columnTransformerAnnotation != null ) { - allColumnTransformerAnnotations.add( columnTransformerAnnotation ); - } - return allColumnTransformerAnnotations; - } - - private String[] createCustomReadWrite(List columnTransformerAnnotations) { - String[] readWrite = new String[2]; - - boolean alreadyProcessedForColumn = false; - for ( AnnotationInstance annotationInstance : columnTransformerAnnotations ) { - String forColumn = annotationInstance.value( "forColumn" ) == null ? - null : annotationInstance.value( "forColumn" ).asString(); - - if ( forColumn != null && !forColumn.equals( getName() ) ) { - continue; - } - - if ( alreadyProcessedForColumn ) { - throw new AnnotationException( "Multiple definition of read/write conditions for column " + getName() ); - } - - readWrite[0] = annotationInstance.value( "read" ) == null ? - null : annotationInstance.value( "read" ).asString(); - readWrite[1] = annotationInstance.value( "write" ) == null ? - null : annotationInstance.value( "write" ).asString(); - - alreadyProcessedForColumn = true; - } - return readWrite; - } - - private String parseCheckAnnotation() { - String checkCondition = null; - AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK ); - if ( checkAnnotation != null ) { - checkCondition = checkAnnotation.value( "constraints" ).toString(); - } - return checkCondition; - } - - private IdGenerator checkGeneratedValueAnnotation() { - IdGenerator generator = null; - AnnotationInstance generatedValueAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - JPADotNames.GENERATED_VALUE - ); - if ( generatedValueAnnotation != null ) { - String name = JandexHelper.getValue( generatedValueAnnotation, "generator", String.class ); - if ( StringHelper.isNotEmpty( name ) ) { - generator = getContext().getMetadataImplementor().getIdGenerator( name ); - if ( generator == null ) { - throw new MappingException( String.format( "Unable to find named generator %s", name ), null ); - } - } - else { - GenerationType genType = JandexHelper.getEnumValue( - generatedValueAnnotation, - "strategy", - GenerationType.class - ); - String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( - genType, - getContext().getMetadataImplementor().getOptions().useNewIdentifierGenerators() - ); - generator = new IdGenerator( null, strategy, null ); - } - } - return generator; - } - - @Override - public AttributeTypeResolver getHibernateTypeResolver() { - if ( resolver == null ) { - resolver = getDefaultHibernateTypeResolver(); - } - return resolver; - } - - private AttributeTypeResolver getDefaultHibernateTypeResolver() { - CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( - new AttributeTypeResolverImpl( - this - ) - ); - resolver.addHibernateTypeResolver( new TemporalTypeResolver( this ) ); - resolver.addHibernateTypeResolver( new LobTypeResolver( this ) ); - resolver.addHibernateTypeResolver( new EnumeratedTypeResolver( this ) ); - return resolver; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java deleted file mode 100644 index 232318662efc..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.internal.util.StringHelper; - -/** - * @author Hardy Ferentschik - */ -public class ColumnSourceImpl extends ColumnValuesSourceImpl { - private final MappedAttribute attribute; - private final String name; - - ColumnSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { - super( attribute.getColumnValues() ); - if ( attributeOverride != null ) { - setOverrideColumnValues( attributeOverride.getColumnValues() ); - } - this.attribute = attribute; - this.name = resolveColumnName(); - } - - protected String resolveColumnName() { - if ( StringHelper.isEmpty( super.getName() ) ) { - //no @Column defined. - return attribute.getContext().getNamingStrategy().propertyToColumnName( attribute.getName() ); - } - else { - return super.getName(); - } - } - - @Override - public String getName() { - return name; - } - - @Override - public String getReadFragment() { - if ( attribute instanceof BasicAttribute ) { - return ( (BasicAttribute) attribute ).getCustomReadFragment(); - } - else { - return null; - } - } - - @Override - public String getWriteFragment() { - if ( attribute instanceof BasicAttribute ) { - return ( (BasicAttribute) attribute ).getCustomWriteFragment(); - } - else { - return null; - } - } - - @Override - public String getCheckCondition() { - if ( attribute instanceof BasicAttribute ) { - return ( (BasicAttribute) attribute ).getCheckCondition(); - } - else { - return null; - } - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValues.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValues.java deleted file mode 100644 index 03b751aa9007..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValues.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.JPADotNames; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -/** - * Container for the properties defined by {@link javax.persistence.Column}. - * - * @author Hardy Ferentschik - */ -public class ColumnValues { - private String name = ""; - private boolean unique = false; - private boolean nullable = true; - private boolean insertable = true; - private boolean updatable = true; - private String columnDefinition = ""; - private String table = null; - private int length = 255; - private int precision = 0; - private int scale = 0; - - ColumnValues() { - this( null ); - } - - public ColumnValues(AnnotationInstance columnAnnotation) { - if ( columnAnnotation != null && !JPADotNames.COLUMN.equals( columnAnnotation.name() ) ) { - throw new AssertionFailure( "A @Column annotation needs to be passed to the constructor" ); - } - applyColumnValues( columnAnnotation ); - } - - private void applyColumnValues(AnnotationInstance columnAnnotation) { - // if the column annotation is null we don't have to do anything. Everything is already defaulted. - if ( columnAnnotation == null ) { - return; - } - - AnnotationValue nameValue = columnAnnotation.value( "name" ); - if ( nameValue != null ) { - this.name = nameValue.asString(); - } - - AnnotationValue uniqueValue = columnAnnotation.value( "unique" ); - if ( uniqueValue != null ) { - this.unique = nameValue.asBoolean(); - } - - AnnotationValue nullableValue = columnAnnotation.value( "nullable" ); - if ( nullableValue != null ) { - this.nullable = nullableValue.asBoolean(); - } - - AnnotationValue insertableValue = columnAnnotation.value( "insertable" ); - if ( insertableValue != null ) { - this.insertable = insertableValue.asBoolean(); - } - - AnnotationValue updatableValue = columnAnnotation.value( "updatable" ); - if ( updatableValue != null ) { - this.updatable = updatableValue.asBoolean(); - } - - AnnotationValue columnDefinition = columnAnnotation.value( "columnDefinition" ); - if ( columnDefinition != null ) { - this.columnDefinition = columnDefinition.asString(); - } - - AnnotationValue tableValue = columnAnnotation.value( "table" ); - if ( tableValue != null ) { - this.table = tableValue.asString(); - } - - AnnotationValue lengthValue = columnAnnotation.value( "length" ); - if ( lengthValue != null ) { - this.length = lengthValue.asInt(); - } - - AnnotationValue precisionValue = columnAnnotation.value( "precision" ); - if ( precisionValue != null ) { - this.precision = precisionValue.asInt(); - } - - AnnotationValue scaleValue = columnAnnotation.value( "scale" ); - if ( scaleValue != null ) { - this.scale = scaleValue.asInt(); - } - } - - public final String getName() { - return name; - } - - public final boolean isUnique() { - return unique; - } - - public final boolean isNullable() { - return nullable; - } - - public final boolean isInsertable() { - return insertable; - } - - public final boolean isUpdatable() { - return updatable; - } - - public final String getColumnDefinition() { - return columnDefinition; - } - - public final String getTable() { - return table; - } - - public final int getLength() { - return length; - } - - public final int getPrecision() { - return precision; - } - - public final int getScale() { - return scale; - } - - public void setName(String name) { - this.name = name; - } - - public void setUnique(boolean unique) { - this.unique = unique; - } - - public void setNullable(boolean nullable) { - this.nullable = nullable; - } - - public void setInsertable(boolean insertable) { - this.insertable = insertable; - } - - public void setUpdatable(boolean updatable) { - this.updatable = updatable; - } - - public void setColumnDefinition(String columnDefinition) { - this.columnDefinition = columnDefinition; - } - - public void setTable(String table) { - this.table = table; - } - - public void setLength(int length) { - this.length = length; - } - - public void setPrecision(int precision) { - this.precision = precision; - } - - public void setScale(int scale) { - this.scale = scale; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ColumnValues" ); - sb.append( "{name='" ).append( name ).append( '\'' ); - sb.append( ", unique=" ).append( unique ); - sb.append( ", nullable=" ).append( nullable ); - sb.append( ", insertable=" ).append( insertable ); - sb.append( ", updatable=" ).append( updatable ); - sb.append( ", columnDefinition='" ).append( columnDefinition ).append( '\'' ); - sb.append( ", table='" ).append( table ).append( '\'' ); - sb.append( ", length=" ).append( length ); - sb.append( ", precision=" ).append( precision ); - sb.append( ", scale=" ).append( scale ); - sb.append( '}' ); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - ColumnValues that = (ColumnValues) o; - - if ( insertable != that.insertable ) { - return false; - } - if ( length != that.length ) { - return false; - } - if ( nullable != that.nullable ) { - return false; - } - if ( precision != that.precision ) { - return false; - } - if ( scale != that.scale ) { - return false; - } - if ( unique != that.unique ) { - return false; - } - if ( updatable != that.updatable ) { - return false; - } - if ( columnDefinition != null ? !columnDefinition.equals( that.columnDefinition ) : that.columnDefinition != null ) { - return false; - } - if ( name != null ? !name.equals( that.name ) : that.name != null ) { - return false; - } - if ( table != null ? !table.equals( that.table ) : that.table != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = name != null ? name.hashCode() : 0; - result = 31 * result + ( unique ? 1 : 0 ); - result = 31 * result + ( nullable ? 1 : 0 ); - result = 31 * result + ( insertable ? 1 : 0 ); - result = 31 * result + ( updatable ? 1 : 0 ); - result = 31 * result + ( columnDefinition != null ? columnDefinition.hashCode() : 0 ); - result = 31 * result + ( table != null ? table.hashCode() : 0 ); - result = 31 * result + length; - result = 31 * result + precision; - result = 31 * result + scale; - return result; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java deleted file mode 100644 index 16480cf0c00f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnValuesSourceImpl.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; - -/** - * @author Steve Ebersole - */ -public class ColumnValuesSourceImpl implements ColumnSource { - private ColumnValues columnValues; - - public ColumnValuesSourceImpl(ColumnValues columnValues) { - this.columnValues = columnValues; - } - - void setOverrideColumnValues(ColumnValues columnValues) { - this.columnValues = columnValues; - } - - @Override - public String getName() { - return columnValues.getName(); - } - - @Override - public boolean isNullable() { - return columnValues.isNullable(); - } - - @Override - public String getDefaultValue() { - return null; - } - - @Override - public String getSqlType() { - // todo - return null; - } - - @Override - public Datatype getDatatype() { - // todo - return null; - } - - @Override - public Size getSize() { - return new Size( - columnValues.getPrecision(), - columnValues.getScale(), - columnValues.getLength(), - Size.LobMultiplier.NONE - ); - } - - @Override - public boolean isUnique() { - return columnValues.isUnique(); - } - - @Override - public String getComment() { - // todo - return null; - } - - @Override - public boolean isIncludedInInsert() { - return columnValues.isInsertable(); - } - - @Override - public boolean isIncludedInUpdate() { - return columnValues.isUpdatable(); - } - - @Override - public String getContainingTableName() { - return columnValues.getTable(); - } - - - // these come from attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public String getReadFragment() { - return null; - } - - @Override - public String getWriteFragment() { - return null; - } - - @Override - public String getCheckCondition() { - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DerivedValueSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DerivedValueSourceImpl.java deleted file mode 100644 index c53002db9616..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DerivedValueSourceImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.source.binder.DerivedValueSource; - -/** - * @author Strong Liu - */ -public class DerivedValueSourceImpl implements DerivedValueSource { - private final FormulaValue formulaValue; - - DerivedValueSourceImpl(FormulaValue formulaValue) { - this.formulaValue = formulaValue; - } - - @Override - public String getExpression() { - return formulaValue.getExpression(); - } - - @Override - public String getContainingTableName() { - return formulaValue.getContainingTableName(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java deleted file mode 100644 index a2a3e50fe921..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import org.hibernate.metamodel.source.annotations.entity.EntityClass; -import org.hibernate.metamodel.source.binder.DiscriminatorSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; - -/** - * @author Hardy Ferentschik - */ -public class DiscriminatorSourceImpl implements DiscriminatorSource { - private final EntityClass entityClass; - - public DiscriminatorSourceImpl(EntityClass entityClass) { - this.entityClass = entityClass; - } - - @Override - public boolean isForced() { - return entityClass.isDiscriminatorForced(); - } - - @Override - public boolean isInserted() { - return entityClass.isDiscriminatorIncludedInSql(); - } - - @Override - public RelationalValueSource getDiscriminatorRelationalValueSource() { - return entityClass.getDiscriminatorFormula() != null ? - new DerivedValueSourceImpl( entityClass.getDiscriminatorFormula() ) - : new ColumnValuesSourceImpl( entityClass.getDiscriminatorColumnValues() ); - } - - @Override - public String getExplicitHibernateTypeName() { - return entityClass.getDiscriminatorType().getName(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java deleted file mode 100644 index 6c4b1d7ce5d2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ExplicitHibernateTypeSourceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.Map; - -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; - -/** - * @author Strong Liu - */ -public class ExplicitHibernateTypeSourceImpl implements ExplicitHibernateTypeSource { - private final AttributeTypeResolver typeResolver; - - public ExplicitHibernateTypeSourceImpl(AttributeTypeResolver typeResolver) { - this.typeResolver = typeResolver; - } - - @Override - public String getName() { - return typeResolver.getExplicitHibernateTypeName(); - } - - @Override - public Map getParameters() { - return typeResolver.getExplicitHibernateTypeParameters(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java deleted file mode 100644 index 8daaee904895..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/FormulaValue.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.hibernate.metamodel.source.annotations.attribute; - -/** - * @author Strong Liu - */ -public class FormulaValue { - private String tableName; - private final String expression; - - public FormulaValue(String tableName, String expression) { - this.tableName = tableName; - this.expression = expression; - } - - public String getExpression() { - return expression; - } - - public String getContainingTableName() { - return tableName; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java deleted file mode 100644 index 758e2c6e0400..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.List; -import java.util.Map; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; -import org.hibernate.metamodel.source.annotations.entity.EntityBindingContext; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.DotName; - -/** - * Base class for the different types of mapped attributes - * - * @author Hardy Ferentschik - */ -public abstract class MappedAttribute implements Comparable { - /** - * Annotations defined on the attribute, keyed against the annotation dot name. - */ - private final Map> annotations; - - /** - * The property name. - */ - private final String name; - - /** - * The java type of the attribute - */ - private final Class attributeType; - - /** - * The access type for this property. At the moment this is either 'field' or 'property', but Hibernate - * also allows custom named accessors (see {@link org.hibernate.property.PropertyAccessorFactory}). - */ - private final String accessType; - - /** - * Defines the column values (relational values) for this property. - */ - private ColumnValues columnValues; - - /** - * Is this property an id property (or part thereof). - */ - private final boolean isId; - - /** - * Whether a change of the property's value triggers a version increment of the entity (in case of optimistic - * locking). - */ - private final boolean isOptimisticLockable; - - /** - * The binding context - */ - private final EntityBindingContext context; - - MappedAttribute(String name, Class attributeType, String accessType, Map> annotations, EntityBindingContext context) { - this.context = context; - this.annotations = annotations; - this.name = name; - this.attributeType = attributeType; - this.accessType = accessType; - - //if this attribute has either @Id or @EmbeddedId, then it is an id attribute - AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); - AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.EMBEDDED_ID - ); - isId = ( idAnnotation != null || embeddedIdAnnotation != null ); - - AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.COLUMN - ); - columnValues = new ColumnValues( columnAnnotation ); - - this.isOptimisticLockable = checkOptimisticLockAnnotation(); - } - - public String getName() { - return name; - } - - public final Class getAttributeType() { - return attributeType; - } - - public String getAccessType() { - return accessType; - } - - public EntityBindingContext getContext() { - return context; - } - - public Map> annotations() { - return annotations; - } - - public ColumnValues getColumnValues() { - return columnValues; - } - - public boolean isId() { - return isId; - } - - public boolean isOptimisticLockable() { - return isOptimisticLockable; - } - - @Override - public int compareTo(MappedAttribute mappedProperty) { - return name.compareTo( mappedProperty.getName() ); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "MappedAttribute" ); - sb.append( "{name='" ).append( name ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } - - public abstract AttributeTypeResolver getHibernateTypeResolver(); - - public abstract boolean isLazy(); - - public abstract boolean isOptional(); - - public abstract boolean isInsertable(); - - public abstract boolean isUpdatable(); - - public abstract PropertyGeneration getPropertyGeneration(); - - private boolean checkOptimisticLockAnnotation() { - boolean triggersVersionIncrement = true; - AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.OPTIMISTIC_LOCK - ); - if ( optimisticLockAnnotation != null ) { - boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean(); - triggersVersionIncrement = !exclude; - } - return triggersVersionIncrement; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java deleted file mode 100644 index e6ae635ea9e5..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleIdentifierSourceImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.binder.SimpleIdentifierSource; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { - private final BasicAttribute attribute; - private final Map attributeOverrideMap; - - public SimpleIdentifierSourceImpl(BasicAttribute attribute, Map attributeOverrideMap) { - if ( !attribute.isId() ) { - throw new AssertionFailure( - String.format( - "A non id attribute was passed to SimpleIdentifierSourceImpl: %s", - attribute.toString() - ) - ); - } - this.attribute = attribute; - this.attributeOverrideMap = attributeOverrideMap; - } - - @Override - public Nature getNature() { - return Nature.SIMPLE; - } - - @Override - public SingularAttributeSource getIdentifierAttributeSource() { - return new SingularAttributeSourceImpl( attribute ); - } - - @Override - public IdGenerator getIdentifierGeneratorDescriptor() { - return attribute.getIdGenerator(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java deleted file mode 100644 index 3b97d0b62c2e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class SingularAttributeSourceImpl implements SingularAttributeSource { - private final MappedAttribute attribute; - private final AttributeOverride attributeOverride; - - public SingularAttributeSourceImpl(MappedAttribute attribute) { - this(attribute, null); - } - - public SingularAttributeSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { - this.attribute = attribute; - this.attributeOverride = attributeOverride; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return new ExplicitHibernateTypeSourceImpl( attribute.getHibernateTypeResolver() ); - } - - @Override - public String getPropertyAccessorName() { - return attribute.getAccessType(); - } - - @Override - public boolean isInsertable() { - return attribute.isInsertable(); - } - - @Override - public boolean isUpdatable() { - return attribute.isUpdatable(); - } - - @Override - public PropertyGeneration getGeneration() { - return attribute.getPropertyGeneration(); - } - - @Override - public boolean isLazy() { - return attribute.isLazy(); - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return attribute.isOptimisticLockable(); - } - - @Override - public String getName() { - return attribute.getName(); - } - - @Override - public List relationalValueSources() { - List valueSources = new ArrayList(); - valueSources.add( new ColumnSourceImpl( attribute, attributeOverride ) ); - return valueSources; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; - } - - @Override - public Iterable metaAttributes() { - return Collections.emptySet(); - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java deleted file mode 100644 index 3eae19acdcfb..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -import java.util.Set; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.ToOneAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource { - private final AssociationAttribute associationAttribute; - private final Set cascadeStyles; - - public ToOneAttributeSourceImpl(AssociationAttribute associationAttribute) { - super( associationAttribute ); - this.associationAttribute = associationAttribute; - this.cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( associationAttribute.getCascadeTypes() ); - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.MANY_TO_ONE; - } - - @Override - public String getReferencedEntityName() { - return associationAttribute.getReferencedEntityType(); - } - - @Override - public String getReferencedEntityAttributeName() { - return associationAttribute.getMappedBy(); - } - - @Override - public Iterable getCascadeStyles() { - return cascadeStyles; - } - - @Override - public FetchMode getFetchMode() { - return associationAttribute.getFetchMode(); - } - - @Override - public FetchTiming getFetchTiming() { - // todo : implement - return FetchTiming.IMMEDIATE; - } - - @Override - public FetchStyle getFetchStyle() { - // todo : implement - return FetchStyle.JOIN; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/package-info.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/package-info.java deleted file mode 100644 index 7a0ab7ea6a7e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/package-info.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute; - -/** - * This package contains binding code for attributes. - */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AbstractAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AbstractAttributeTypeResolver.java deleted file mode 100644 index 47916da9ed1f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AbstractAttributeTypeResolver.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.Collections; -import java.util.Map; - -import org.hibernate.internal.util.StringHelper; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public abstract class AbstractAttributeTypeResolver implements AttributeTypeResolver { - protected abstract AnnotationInstance getTypeDeterminingAnnotationInstance(); - - protected abstract String resolveHibernateTypeName(AnnotationInstance annotationInstance); - - protected Map resolveHibernateTypeParameters(AnnotationInstance annotationInstance) { - return Collections.emptyMap(); - } - - @Override - final public String getExplicitHibernateTypeName() { - return resolveHibernateTypeName( getTypeDeterminingAnnotationInstance() ); - } - - @Override - final public Map getExplicitHibernateTypeParameters() { - if ( StringHelper.isNotEmpty( getExplicitHibernateTypeName() ) ) { - return resolveHibernateTypeParameters( getTypeDeterminingAnnotationInstance() ); - } - else { - return Collections.emptyMap(); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolver.java deleted file mode 100644 index 7333c641098d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolver.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.Map; - -/** - * Determines explicit Hibernate type information for JPA mapped attributes when additional type information is - * provided via annotations like {@link javax.persistence.Lob}, {@link javax.persistence.Enumerated} and - * {@link javax.persistence.Temporal}. - * - * @author Strong Liu - */ -public interface AttributeTypeResolver { - /** - * @return returns an explicit hibernate type name in case the mapped attribute has an additional - * {@link org.hibernate.annotations.Type} annotation or an implicit type is given via the use of annotations like - * {@link javax.persistence.Lob}, {@link javax.persistence.Enumerated} and - * {@link javax.persistence.Temporal}. - */ - String getExplicitHibernateTypeName(); - - /** - * @return Returns a map of optional type parameters. See {@link #getExplicitHibernateTypeName()}. - */ - Map getExplicitHibernateTypeParameters(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java deleted file mode 100644 index f163fe520c46..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/AttributeTypeResolverImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -/** - * @author Strong Liu - */ -public class AttributeTypeResolverImpl extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - - public AttributeTypeResolverImpl(MappedAttribute mappedAttribute) { - this.mappedAttribute = mappedAttribute; - } - - @Override - protected String resolveHibernateTypeName(AnnotationInstance typeAnnotation) { - String typeName = null; - if ( typeAnnotation != null ) { - typeName = JandexHelper.getValue( typeAnnotation, "type", String.class ); - } - return typeName; - } - - @Override - protected Map resolveHibernateTypeParameters(AnnotationInstance typeAnnotation) { - HashMap typeParameters = new HashMap(); - AnnotationValue parameterAnnotationValue = typeAnnotation.value( "parameters" ); - if ( parameterAnnotationValue != null ) { - AnnotationInstance[] parameterAnnotations = parameterAnnotationValue.asNestedArray(); - for ( AnnotationInstance parameterAnnotationInstance : parameterAnnotations ) { - typeParameters.put( - JandexHelper.getValue( parameterAnnotationInstance, "name", String.class ), - JandexHelper.getValue( parameterAnnotationInstance, "value", String.class ) - ); - } - } - return typeParameters; - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( - mappedAttribute.annotations(), - HibernateDotNames.TYPE - ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/CompositeAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/CompositeAttributeTypeResolver.java deleted file mode 100644 index 26c36ff4ba74..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/CompositeAttributeTypeResolver.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.CollectionHelper; - -/** - * @author Strong Liu - */ -public class CompositeAttributeTypeResolver implements AttributeTypeResolver { - private List resolvers = new ArrayList(); - private final AttributeTypeResolverImpl explicitHibernateTypeResolver; - - public CompositeAttributeTypeResolver(AttributeTypeResolverImpl explicitHibernateTypeResolver) { - if ( explicitHibernateTypeResolver == null ) { - throw new AssertionFailure( "The Given AttributeTypeResolver is null." ); - } - this.explicitHibernateTypeResolver = explicitHibernateTypeResolver; - } - - public void addHibernateTypeResolver(AttributeTypeResolver resolver) { - if ( resolver == null ) { - throw new AssertionFailure( "The Given AttributeTypeResolver is null." ); - } - resolvers.add( resolver ); - } - - @Override - public String getExplicitHibernateTypeName() { - String type = explicitHibernateTypeResolver.getExplicitHibernateTypeName(); - if ( StringHelper.isEmpty( type ) ) { - for ( AttributeTypeResolver resolver : resolvers ) { - type = resolver.getExplicitHibernateTypeName(); - if ( StringHelper.isNotEmpty( type ) ) { - break; - } - } - } - return type; - } - - @Override - public Map getExplicitHibernateTypeParameters() { - Map parameters = explicitHibernateTypeResolver.getExplicitHibernateTypeParameters(); - if ( CollectionHelper.isEmpty( parameters ) ) { - for ( AttributeTypeResolver resolver : resolvers ) { - parameters = resolver.getExplicitHibernateTypeParameters(); - if ( CollectionHelper.isNotEmpty( parameters ) ) { - break; - } - } - } - return parameters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java deleted file mode 100644 index 79c80e9157ad..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/EnumeratedTypeResolver.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.sql.Types; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; -import org.hibernate.type.EnumType; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public class EnumeratedTypeResolver extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - private final boolean isMapKey; - - public EnumeratedTypeResolver(MappedAttribute mappedAttribute) { - if ( mappedAttribute == null ) { - throw new AssertionFailure( "MappedAttribute is null" ); - } - this.mappedAttribute = mappedAttribute; - this.isMapKey = false;//todo - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( - mappedAttribute.annotations(), - JPADotNames.ENUMERATED - ); - } - - @Override - public String resolveHibernateTypeName(AnnotationInstance enumeratedAnnotation) { - boolean isEnum = mappedAttribute.getAttributeType().isEnum(); - if ( !isEnum ) { - if ( enumeratedAnnotation != null ) { - throw new AnnotationException( "Attribute " + mappedAttribute.getName() + " is not a Enumerated type, but has a @Enumerated annotation." ); - } - else { - return null; - } - } - return EnumType.class.getName(); - } - - @Override - protected Map resolveHibernateTypeParameters(AnnotationInstance annotationInstance) { - HashMap typeParameters = new HashMap(); - typeParameters.put( EnumType.ENUM, mappedAttribute.getAttributeType().getName() ); - if ( annotationInstance != null ) { - javax.persistence.EnumType enumType = JandexHelper.getEnumValue( - annotationInstance, - "value", - javax.persistence.EnumType.class - ); - if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) { - typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) ); - } - else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) { - typeParameters.put( EnumType.TYPE, String.valueOf( Types.VARCHAR ) ); - } - else { - throw new AssertionFailure( "Unknown EnumType: " + enumType ); - } - } - else { - typeParameters.put( EnumType.TYPE, String.valueOf( Types.INTEGER ) ); - } - return typeParameters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java deleted file mode 100644 index f0d405e90334..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/LobTypeResolver.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.io.Serializable; -import java.sql.Blob; -import java.sql.Clob; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; -import org.hibernate.type.CharacterArrayClobType; -import org.hibernate.type.PrimitiveCharacterArrayClobType; -import org.hibernate.type.SerializableToBlobType; -import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.WrappedMaterializedBlobType; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public class LobTypeResolver extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - - public LobTypeResolver(MappedAttribute mappedAttribute) { - if ( mappedAttribute == null ) { - throw new AssertionFailure( "MappedAttribute is null" ); - } - this.mappedAttribute = mappedAttribute; - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( mappedAttribute.annotations(), JPADotNames.LOB ); - } - - @Override - public String resolveHibernateTypeName(AnnotationInstance annotationInstance) { - if ( annotationInstance == null ) { - return null; - } - String type = null; - if ( Clob.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.CLOB.getName(); - } - else if ( Blob.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.BLOB.getName(); - } - else if ( String.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.MATERIALIZED_CLOB.getName(); - } - else if ( Character[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = CharacterArrayClobType.class.getName(); - } - else if ( char[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = PrimitiveCharacterArrayClobType.class.getName(); - } - else if ( Byte[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = WrappedMaterializedBlobType.class.getName(); - } - else if ( byte[].class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = StandardBasicTypes.MATERIALIZED_BLOB.getName(); - } - else if ( Serializable.class.isAssignableFrom( mappedAttribute.getAttributeType() ) ) { - type = SerializableToBlobType.class.getName(); - } - else { - type = "blob"; - } - return type; - } - - @Override - protected Map resolveHibernateTypeParameters(AnnotationInstance annotationInstance) { - if ( getExplicitHibernateTypeName().equals( SerializableToBlobType.class.getName() ) ) { - HashMap typeParameters = new HashMap(); - typeParameters.put( - SerializableToBlobType.CLASS_NAME, - mappedAttribute.getAttributeType().getName() - ); - return typeParameters; - } - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java deleted file mode 100644 index 41414aa63e3c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/TemporalTypeResolver.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.attribute.type; - -import java.util.Calendar; -import java.util.Date; -import javax.persistence.TemporalType; - -import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; -import org.hibernate.type.StandardBasicTypes; - -import org.jboss.jandex.AnnotationInstance; - -/** - * @author Strong Liu - */ -public class TemporalTypeResolver extends AbstractAttributeTypeResolver { - private final MappedAttribute mappedAttribute; - private final boolean isMapKey; - - public TemporalTypeResolver(MappedAttribute mappedAttribute) { - if ( mappedAttribute == null ) { - throw new AssertionFailure( "MappedAttribute is null" ); - } - this.mappedAttribute = mappedAttribute; - this.isMapKey = false;//todo - } - - @Override - public String resolveHibernateTypeName(AnnotationInstance temporalAnnotation) { - - if ( isTemporalType( mappedAttribute.getAttributeType() ) ) { - if ( temporalAnnotation == null ) { - //SPEC 11.1.47 The Temporal annotation must be specified for persistent fields or properties of type java.util.Date and java.util.Calendar. - throw new AnnotationException( "Attribute " + mappedAttribute.getName() + " is a Temporal type, but no @Temporal annotation found." ); - } - TemporalType temporalType = JandexHelper.getEnumValue( temporalAnnotation, "value", TemporalType.class ); - boolean isDate = Date.class.isAssignableFrom( mappedAttribute.getAttributeType() ); - String type; - switch ( temporalType ) { - case DATE: - type = isDate ? StandardBasicTypes.DATE.getName() : StandardBasicTypes.CALENDAR_DATE.getName(); - break; - case TIME: - type = StandardBasicTypes.TIME.getName(); - if ( !isDate ) { - throw new NotYetImplementedException( "Calendar cannot persist TIME only" ); - } - break; - case TIMESTAMP: - type = isDate ? StandardBasicTypes.TIMESTAMP.getName() : StandardBasicTypes.CALENDAR.getName(); - break; - default: - throw new AssertionFailure( "Unknown temporal type: " + temporalType ); - } - return type; - } - else { - if ( temporalAnnotation != null ) { - throw new AnnotationException( - "@Temporal should only be set on a java.util.Date or java.util.Calendar property: " + mappedAttribute - .getName() - ); - } - } - return null; - } - - @Override - protected AnnotationInstance getTypeDeterminingAnnotationInstance() { - return JandexHelper.getSingleAnnotation( - mappedAttribute.annotations(), - JPADotNames.TEMPORAL - ); - } - - private static boolean isTemporalType(Class type) { - return Date.class.isAssignableFrom( type ) || Calendar.class.isAssignableFrom( type ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java deleted file mode 100644 index b7331a26aa73..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/type/package-info.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.attribute.type; - -/** - * This package contains type binding code for basic attributes. - */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java deleted file mode 100644 index 3ab8e3d2c17c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ComponentAttributeSourceImpl.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; -import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; -import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.ToOneAttributeSourceImpl; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.ComponentAttributeSource; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; - -/** - * Annotation backed implementation of {@code ComponentAttributeSource}. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class ComponentAttributeSourceImpl implements ComponentAttributeSource { - private static final String PATH_SEPERATOR = "."; - private final EmbeddableClass embeddableClass; - private final ValueHolder> classReference; - private final Map attributeOverrides; - private final String path; - - public ComponentAttributeSourceImpl(EmbeddableClass embeddableClass, String parentPath, Map attributeOverrides) { - this.embeddableClass = embeddableClass; - this.classReference = new ValueHolder>( embeddableClass.getConfiguredClass() ); - this.attributeOverrides = attributeOverrides; - if ( StringHelper.isEmpty( parentPath ) ) { - path = embeddableClass.getEmbeddedAttributeName(); - } - else { - path = parentPath + "." + embeddableClass.getEmbeddedAttributeName(); - } - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.COMPONENT; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public String getClassName() { - return embeddableClass.getConfiguredClass().getName(); - } - - @Override - public ValueHolder> getClassReference() { - return classReference; - } - - @Override - public String getName() { - return embeddableClass.getEmbeddedAttributeName(); - } - - @Override - public String getExplicitTuplizerClassName() { - return embeddableClass.getCustomTuplizer(); - } - - @Override - public String getPropertyAccessorName() { - return embeddableClass.getClassAccessType().toString().toLowerCase(); - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return embeddableClass.getLocalBindingContext(); - } - - @Override - public Iterable attributeSources() { - List attributeList = new ArrayList(); - for ( BasicAttribute attribute : embeddableClass.getSimpleAttributes() ) { - AttributeOverride attributeOverride = null; - String tmp = getPath() + PATH_SEPERATOR + attribute.getName(); - if ( attributeOverrides.containsKey( tmp ) ) { - attributeOverride = attributeOverrides.get( tmp ); - } - attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) ); - } - for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) { - attributeList.add( - new ComponentAttributeSourceImpl( - embeddable, - getPath(), - createAggregatedOverrideMap() - ) - ); - } - for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes() ) { - attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) ); - } - return attributeList; - } - - @Override - public String getPath() { - return path; - } - - @Override - public String getParentReferenceAttributeName() { - return embeddableClass.getParentReferencingAttributeName(); - } - - @Override - public Iterable metaAttributes() { - // not relevant for annotations - return Collections.emptySet(); - } - - @Override - public List relationalValueSources() { - // none, they are defined on the simple sub-attributes - return null; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - // probably need to check for @Target in EmbeddableClass (HF) - return null; - } - - @Override - public boolean isInsertable() { - return true; - } - - @Override - public boolean isUpdatable() { - return true; - } - - @Override - public PropertyGeneration getGeneration() { - return null; - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return true; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ComponentAttributeSourceImpl" ); - sb.append( "{embeddableClass=" ).append( embeddableClass.getConfiguredClass().getSimpleName() ); - sb.append( '}' ); - return sb.toString(); - } - - private Map createAggregatedOverrideMap() { - // add all overrides passed down to this instance - they override overrides ;-) which are defined further down - // the embeddable chain - Map aggregatedOverrideMap = new HashMap( - attributeOverrides - ); - - for ( Map.Entry entry : embeddableClass.getAttributeOverrideMap().entrySet() ) { - String fullPath = getPath() + PATH_SEPERATOR + entry.getKey(); - if ( !aggregatedOverrideMap.containsKey( fullPath ) ) { - aggregatedOverrideMap.put( fullPath, entry.getValue() ); - } - } - return aggregatedOverrideMap; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java deleted file mode 100644 index a2e8a60fed5d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import javax.persistence.AccessType; - -import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.ReflectionHelper; -import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; -import org.hibernate.metamodel.source.annotations.attribute.AttributeNature; -import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.MethodInfo; -import org.jboss.logging.Logger; - -import com.fasterxml.classmate.ResolvedTypeWithMembers; -import com.fasterxml.classmate.members.HierarchicType; -import com.fasterxml.classmate.members.ResolvedMember; - -/** - * Base class for a configured entity, mapped super class or embeddable - * - * @author Hardy Ferentschik - */ -public class ConfiguredClass { - public static final Logger LOG = Logger.getLogger( ConfiguredClass.class.getName() ); - - /** - * The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy. - */ - private final ConfiguredClass parent; - - /** - * The Jandex class info for this configured class. Provides access to the annotation defined on this configured class. - */ - private final ClassInfo classInfo; - - /** - * The actual java type. - */ - private final Class clazz; - - /** - * The default access type for this entity - */ - private final AccessType classAccessType; - - /** - * The type of configured class, entity, mapped super class, embeddable, ... - */ - private final ConfiguredClassType configuredClassType; - - /** - * The id attributes - */ - private final Map idAttributeMap; - - /** - * The mapped association attributes for this entity - */ - private final Map associationAttributeMap; - - /** - * The mapped simple attributes for this entity - */ - private final Map simpleAttributeMap; - - /** - * The version attribute or {@code null} in case none exists. - */ - private BasicAttribute versionAttribute; - - /** - * The embedded classes for this entity - */ - private final Map embeddedClasses = new HashMap(); - - /** - * A map of all attribute overrides defined in this class. The override name is "normalised", meaning as if specified - * on class level. If the override is specified on attribute level the attribute name is used as prefix. - */ - private final Map attributeOverrideMap; - - private final Set transientFieldNames = new HashSet(); - private final Set transientMethodNames = new HashSet(); - - /** - * Fully qualified name of a custom tuplizer - */ - private final String customTuplizer; - - private final EntityBindingContext localBindingContext; - - public ConfiguredClass( - ClassInfo classInfo, - AccessType defaultAccessType, - ConfiguredClass parent, - AnnotationBindingContext context) { - this.parent = parent; - this.classInfo = classInfo; - this.clazz = context.locateClassByName( classInfo.toString() ); - this.configuredClassType = determineType(); - this.classAccessType = determineClassAccessType( defaultAccessType ); - this.customTuplizer = determineCustomTuplizer(); - - this.simpleAttributeMap = new TreeMap(); - this.idAttributeMap = new TreeMap(); - this.associationAttributeMap = new TreeMap(); - - this.localBindingContext = new EntityBindingContext( context, this ); - - collectAttributes(); - attributeOverrideMap = Collections.unmodifiableMap( findAttributeOverrides() ); - } - - public String getName() { - return clazz.getName(); - } - - public Class getConfiguredClass() { - return clazz; - } - - public ClassInfo getClassInfo() { - return classInfo; - } - - public ConfiguredClass getParent() { - return parent; - } - - public EntityBindingContext getLocalBindingContext() { - return localBindingContext; - } - - public Iterable getSimpleAttributes() { - return simpleAttributeMap.values(); - } - - public Iterable getIdAttributes() { - return idAttributeMap.values(); - } - - public BasicAttribute getVersionAttribute() { - return versionAttribute; - } - - public Iterable getAssociationAttributes() { - return associationAttributeMap.values(); - } - - public Map getEmbeddedClasses() { - return embeddedClasses; - } - - public Map getAttributeOverrideMap() { - return attributeOverrideMap; - } - - public AccessType getClassAccessType() { - return classAccessType; - } - - public String getCustomTuplizer() { - return customTuplizer; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ConfiguredClass" ); - sb.append( "{clazz=" ).append( clazz.getSimpleName() ); - sb.append( '}' ); - return sb.toString(); - } - - private ConfiguredClassType determineType() { - if ( classInfo.annotations().containsKey( JPADotNames.ENTITY ) ) { - return ConfiguredClassType.ENTITY; - } - else if ( classInfo.annotations().containsKey( JPADotNames.MAPPED_SUPERCLASS ) ) { - return ConfiguredClassType.MAPPED_SUPERCLASS; - } - else if ( classInfo.annotations().containsKey( JPADotNames.EMBEDDABLE ) ) { - return ConfiguredClassType.EMBEDDABLE; - } - else { - return ConfiguredClassType.NON_ENTITY; - } - } - - private AccessType determineClassAccessType(AccessType defaultAccessType) { - // default to the hierarchy access type to start with - AccessType accessType = defaultAccessType; - - AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ACCESS ); - if ( accessAnnotation != null && accessAnnotation.target().getClass().equals( ClassInfo.class ) ) { - accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); - } - - return accessType; - } - - /** - * Find all attributes for this configured class and add them to the corresponding map - */ - private void collectAttributes() { - // find transient field and method names - findTransientFieldAndMethodNames(); - - // use the class mate library to generic types - ResolvedTypeWithMembers resolvedType = localBindingContext.resolveMemberTypes( - localBindingContext.getResolvedType( - clazz - ) - ); - for ( HierarchicType hierarchicType : resolvedType.allTypesAndOverrides() ) { - if ( hierarchicType.getType().getErasedType().equals( clazz ) ) { - resolvedType = localBindingContext.resolveMemberTypes( hierarchicType.getType() ); - break; - } - } - - if ( resolvedType == null ) { - throw new AssertionFailure( "Unable to resolve types for " + clazz.getName() ); - } - - Set explicitlyConfiguredMemberNames = createExplicitlyConfiguredAccessProperties( resolvedType ); - - if ( AccessType.FIELD.equals( classAccessType ) ) { - Field fields[] = clazz.getDeclaredFields(); - Field.setAccessible( fields, true ); - for ( Field field : fields ) { - if ( isPersistentMember( transientFieldNames, explicitlyConfiguredMemberNames, field ) ) { - createMappedAttribute( field, resolvedType, AccessType.FIELD ); - } - } - } - else { - Method[] methods = clazz.getDeclaredMethods(); - Method.setAccessible( methods, true ); - for ( Method method : methods ) { - if ( isPersistentMember( transientMethodNames, explicitlyConfiguredMemberNames, method ) ) { - createMappedAttribute( method, resolvedType, AccessType.PROPERTY ); - } - } - } - } - - private boolean isPersistentMember(Set transientNames, Set explicitlyConfiguredMemberNames, Member member) { - if ( !ReflectionHelper.isProperty( member ) ) { - return false; - } - - if ( transientNames.contains( member.getName() ) ) { - return false; - } - - if ( explicitlyConfiguredMemberNames.contains( ReflectionHelper.getPropertyName( member ) ) ) { - return false; - } - - return true; - } - - /** - * Creates {@code MappedProperty} instances for the explicitly configured persistent properties - * - * @param resolvedMembers the resolved type parameters for this class - * - * @return the property names of the explicitly configured attribute names in a set - */ - private Set createExplicitlyConfiguredAccessProperties(ResolvedTypeWithMembers resolvedMembers) { - Set explicitAccessPropertyNames = new HashSet(); - - List accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS ); - if ( accessAnnotations == null ) { - return explicitAccessPropertyNames; - } - - // iterate over all @Access annotations defined on the current class - for ( AnnotationInstance accessAnnotation : accessAnnotations ) { - // we are only interested at annotations defined on fields and methods - AnnotationTarget annotationTarget = accessAnnotation.target(); - if ( !( annotationTarget.getClass().equals( MethodInfo.class ) || annotationTarget.getClass() - .equals( FieldInfo.class ) ) ) { - continue; - } - - AccessType accessType = JandexHelper.getEnumValue( accessAnnotation, "value", AccessType.class ); - - if ( !isExplicitAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ) ) { - continue; - } - - // the placement is correct, get the member - Member member; - if ( annotationTarget instanceof MethodInfo ) { - Method m; - try { - m = clazz.getMethod( ( (MethodInfo) annotationTarget ).name() ); - } - catch ( NoSuchMethodException e ) { - throw new HibernateException( - "Unable to load method " - + ( (MethodInfo) annotationTarget ).name() - + " of class " + clazz.getName() - ); - } - member = m; - accessType = AccessType.PROPERTY; - } - else { - Field f; - try { - f = clazz.getField( ( (FieldInfo) annotationTarget ).name() ); - } - catch ( NoSuchFieldException e ) { - throw new HibernateException( - "Unable to load field " - + ( (FieldInfo) annotationTarget ).name() - + " of class " + clazz.getName() - ); - } - member = f; - accessType = AccessType.FIELD; - } - if ( ReflectionHelper.isProperty( member ) ) { - createMappedAttribute( member, resolvedMembers, accessType ); - explicitAccessPropertyNames.add( ReflectionHelper.getPropertyName( member ) ); - } - } - return explicitAccessPropertyNames; - } - - private boolean isExplicitAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) { - // when the access type of the class is FIELD - // overriding access annotations must be placed on properties AND have the access type PROPERTY - if ( AccessType.FIELD.equals( classAccessType ) ) { - if ( !( annotationTarget instanceof MethodInfo ) ) { - LOG.tracef( - "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + - "@Access has to be placed on the property (getter)", classInfo.name().toString() - ); - return false; - } - - if ( !AccessType.PROPERTY.equals( accessType ) ) { - LOG.tracef( - "The access type of class %s is AccessType.FIELD. To override the access for an attribute " + - "@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " + - "Using AccessType.FIELD on the property has no effect", - classInfo.name().toString() - ); - return false; - } - } - - // when the access type of the class is PROPERTY - // overriding access annotations must be placed on fields and have the access type FIELD - if ( AccessType.PROPERTY.equals( classAccessType ) ) { - if ( !( annotationTarget instanceof FieldInfo ) ) { - LOG.tracef( - "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + - "@Access has to be placed on the field ", classInfo.name().toString() - ); - return false; - } - - if ( !AccessType.FIELD.equals( accessType ) ) { - LOG.tracef( - "The access type of class %s is AccessType.PROPERTY. To override the access for a field " + - "@Access has to be placed on the field with an access type of AccessType.FIELD. " + - "Using AccessType.PROPERTY on the field has no effect", - classInfo.name().toString() - ); - return false; - } - } - return true; - } - - private void createMappedAttribute(Member member, ResolvedTypeWithMembers resolvedType, AccessType accessType) { - final String attributeName = ReflectionHelper.getPropertyName( member ); - ResolvedMember[] resolvedMembers; - if ( member instanceof Field ) { - resolvedMembers = resolvedType.getMemberFields(); - } - else { - resolvedMembers = resolvedType.getMemberMethods(); - } - Class attributeType = (Class) findResolvedType( member.getName(), resolvedMembers ); - final Map> annotations = JandexHelper.getMemberAnnotations( - classInfo, member.getName() - ); - - AttributeNature attributeNature = determineAttributeNature( annotations ); - String accessTypeString = accessType.toString().toLowerCase(); - switch ( attributeNature ) { - case BASIC: { - BasicAttribute attribute = BasicAttribute.createSimpleAttribute( - attributeName, attributeType, annotations, accessTypeString, getLocalBindingContext() - ); - if ( attribute.isId() ) { - idAttributeMap.put( attributeName, attribute ); - } - else if ( attribute.isVersioned() ) { - if ( versionAttribute == null ) { - versionAttribute = attribute; - } - else { - throw new MappingException( "Multiple version attributes", localBindingContext.getOrigin() ); - } - } - else { - simpleAttributeMap.put( attributeName, attribute ); - } - break; - } - case ELEMENT_COLLECTION: { - throw new NotYetImplementedException( "Element collections must still be implemented." ); - } - case EMBEDDED_ID: { - throw new NotYetImplementedException( "Embedded ids must still be implemented." ); - } - case EMBEDDED: { - AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - HibernateDotNames.TARGET - ); - if ( targetAnnotation != null ) { - attributeType = localBindingContext.locateClassByName( - JandexHelper.getValue( targetAnnotation, "value", String.class ) - ); - } - resolveEmbeddable( attributeName, attributeType ); - break; - } - // OneToOne, OneToMany, ManyToOne, ManyToMany - default: { - AssociationAttribute attribute = AssociationAttribute.createAssociationAttribute( - attributeName, - attributeType, - attributeNature, - accessTypeString, - annotations, - getLocalBindingContext() - ); - associationAttributeMap.put( attributeName, attribute ); - } - } - } - - private void resolveEmbeddable(String attributeName, Class type) { - ClassInfo embeddableClassInfo = localBindingContext.getClassInfo( type.getName() ); - if ( embeddableClassInfo == null ) { - String msg = String.format( - "Attribute '%s#%s' is annotated with @Embedded, but '%s' does not seem to be annotated " + - "with @Embeddable. Are all annotated classes added to the configuration?", - getConfiguredClass().getSimpleName(), - attributeName, - type.getSimpleName() - ); - throw new AnnotationException( msg ); - } - - localBindingContext.resolveAllTypes( type.getName() ); - EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy( - localBindingContext.locateClassByName( embeddableClassInfo.toString() ), - attributeName, - classAccessType, - localBindingContext - ); - embeddedClasses.put( attributeName, hierarchy.getLeaf() ); - } - - /** - * Given the annotations defined on a persistent attribute this methods determines the attribute type. - * - * @param annotations the annotations defined on the persistent attribute - * - * @return an instance of the {@code AttributeType} enum - */ - private AttributeNature determineAttributeNature(Map> annotations) { - EnumMap discoveredAttributeTypes = - new EnumMap( AttributeNature.class ); - - AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ); - if ( oneToOne != null ) { - discoveredAttributeTypes.put( AttributeNature.ONE_TO_ONE, oneToOne ); - } - - AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ); - if ( oneToMany != null ) { - discoveredAttributeTypes.put( AttributeNature.ONE_TO_MANY, oneToMany ); - } - - AnnotationInstance manyToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ); - if ( manyToOne != null ) { - discoveredAttributeTypes.put( AttributeNature.MANY_TO_ONE, manyToOne ); - } - - AnnotationInstance manyToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ); - if ( manyToMany != null ) { - discoveredAttributeTypes.put( AttributeNature.MANY_TO_MANY, manyToMany ); - } - - AnnotationInstance embedded = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED ); - if ( embedded != null ) { - discoveredAttributeTypes.put( AttributeNature.EMBEDDED, embedded ); - } - - AnnotationInstance embeddedId = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID ); - if ( embeddedId != null ) { - discoveredAttributeTypes.put( AttributeNature.EMBEDDED_ID, embeddedId ); - } - - AnnotationInstance elementCollection = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.ELEMENT_COLLECTION - ); - if ( elementCollection != null ) { - discoveredAttributeTypes.put( AttributeNature.ELEMENT_COLLECTION, elementCollection ); - } - - if ( discoveredAttributeTypes.size() == 0 ) { - return AttributeNature.BASIC; - } - else if ( discoveredAttributeTypes.size() == 1 ) { - return discoveredAttributeTypes.keySet().iterator().next(); - } - else { - throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() ); - } - } - - private Type findResolvedType(String name, ResolvedMember[] resolvedMembers) { - for ( ResolvedMember resolvedMember : resolvedMembers ) { - if ( resolvedMember.getName().equals( name ) ) { - return resolvedMember.getType().getErasedType(); - } - } - throw new AssertionFailure( - String.format( - "Unable to resolve type of attribute %s of class %s", - name, - classInfo.name().toString() - ) - ); - } - - /** - * Populates the sets of transient field and method names. - */ - private void findTransientFieldAndMethodNames() { - List transientMembers = classInfo.annotations().get( JPADotNames.TRANSIENT ); - if ( transientMembers == null ) { - return; - } - - for ( AnnotationInstance transientMember : transientMembers ) { - AnnotationTarget target = transientMember.target(); - if ( target instanceof FieldInfo ) { - transientFieldNames.add( ( (FieldInfo) target ).name() ); - } - else { - transientMethodNames.add( ( (MethodInfo) target ).name() ); - } - } - } - - private Map findAttributeOverrides() { - Map attributeOverrideList = new HashMap(); - - AnnotationInstance attributeOverrideAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ATTRIBUTE_OVERRIDE - ); - if ( attributeOverrideAnnotation != null ) { - String prefix = createPathPrefix( attributeOverrideAnnotation.target() ); - AttributeOverride override = new AttributeOverride( prefix, attributeOverrideAnnotation ); - attributeOverrideList.put( override.getAttributePath(), override ); - } - - AnnotationInstance attributeOverridesAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ATTRIBUTE_OVERRIDES - ); - if ( attributeOverridesAnnotation != null ) { - AnnotationInstance[] annotationInstances = attributeOverridesAnnotation.value().asNestedArray(); - for ( AnnotationInstance annotationInstance : annotationInstances ) { - String prefix = createPathPrefix( attributeOverridesAnnotation.target() ); - AttributeOverride override = new AttributeOverride( prefix, annotationInstance ); - attributeOverrideList.put( override.getAttributePath(), override ); - } - } - return attributeOverrideList; - } - - private String createPathPrefix(AnnotationTarget target) { - String prefix = null; - if ( target instanceof FieldInfo || target instanceof MethodInfo ) { - prefix = JandexHelper.getPropertyName( target ); - } - return prefix; - } - - private List findAssociationOverrides() { - List associationOverrideList = new ArrayList(); - - AnnotationInstance associationOverrideAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ASSOCIATION_OVERRIDE - ); - if ( associationOverrideAnnotation != null ) { - associationOverrideList.add( associationOverrideAnnotation ); - } - - AnnotationInstance associationOverridesAnnotation = JandexHelper.getSingleAnnotation( - classInfo, - JPADotNames.ASSOCIATION_OVERRIDES - ); - if ( associationOverrideAnnotation != null ) { - AnnotationInstance[] attributeOverride = associationOverridesAnnotation.value().asNestedArray(); - Collections.addAll( associationOverrideList, attributeOverride ); - } - - return associationOverrideList; - } - - private String determineCustomTuplizer() { - final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation( - classInfo, HibernateDotNames.TUPLIZERS - ); - if ( tuplizersAnnotation == null ) { - return null; - } - - AnnotationInstance[] annotations = JandexHelper.getValue( - tuplizersAnnotation, - "value", - AnnotationInstance[].class - ); - - AnnotationInstance pojoTuplizerAnnotation = null; - for ( AnnotationInstance tuplizerAnnotation : annotations ) { - if ( EntityMode.valueOf( tuplizerAnnotation.value( "entityModeType" ).asEnum() ) == EntityMode.POJO ) { - pojoTuplizerAnnotation = tuplizerAnnotation; - break; - } - } - - String customTuplizer = null; - if ( pojoTuplizerAnnotation != null ) { - customTuplizer = pojoTuplizerAnnotation.value( "impl" ).asString(); - } - return customTuplizer; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClassType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClassType.java deleted file mode 100644 index cf7d0207ade0..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClassType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -/** - * @author Hardy Ferentschik - */ -public enum ConfiguredClassType { - ENTITY, - MAPPED_SUPERCLASS, - EMBEDDABLE, - NON_ENTITY -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java deleted file mode 100644 index ce162b0fef12..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableClass.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.AccessType; - -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; - -/** - * Represents the information about an entity annotated with {@code @Embeddable}. - * - * @author Hardy Ferentschik - */ -public class EmbeddableClass extends ConfiguredClass { - private final String embeddedAttributeName; - private final String parentReferencingAttributeName; - - public EmbeddableClass( - ClassInfo classInfo, - String embeddedAttributeName, - ConfiguredClass parent, - AccessType defaultAccessType, - AnnotationBindingContext context) { - super( classInfo, defaultAccessType, parent, context ); - this.embeddedAttributeName = embeddedAttributeName; - this.parentReferencingAttributeName = checkParentAnnotation(); - } - - private String checkParentAnnotation() { - AnnotationInstance parentAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - HibernateDotNames.PARENT - ); - if ( parentAnnotation == null ) { - return null; - } - else { - return JandexHelper.getPropertyName( parentAnnotation.target() ); - } - } - - public String getEmbeddedAttributeName() { - return embeddedAttributeName; - } - - public String getParentReferencingAttributeName() { - return parentReferencingAttributeName; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableHierarchy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableHierarchy.java deleted file mode 100644 index 41f46f489c92..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableHierarchy.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import javax.persistence.AccessType; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; - -/** - * Contains information about the access and inheritance type for all classes within a class hierarchy. - * - * @author Hardy Ferentschik - */ -public class EmbeddableHierarchy implements Iterable { - private final AccessType defaultAccessType; - private final List embeddables; - - /** - * Builds the configured class hierarchy for a an embeddable class. - * - * @param embeddableClass the top level embedded class - * @param propertyName the name of the property in the entity class embedding this embeddable - * @param accessType the access type inherited from the class in which the embeddable gets embedded - * @param context the annotation binding context with access to the service registry and the annotation index - * - * @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity. - */ - public static EmbeddableHierarchy createEmbeddableHierarchy(Class embeddableClass, String propertyName, AccessType accessType, AnnotationBindingContext context) { - - ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() ); - if ( embeddableClassInfo == null ) { - throw new AssertionFailure( - String.format( - "The specified class %s cannot be found in the annotation index", - embeddableClass.getName() - ) - ); - } - - if ( JandexHelper.getSingleAnnotation( embeddableClassInfo, JPADotNames.EMBEDDABLE ) == null ) { - throw new AssertionFailure( - String.format( - "The specified class %s is not annotated with @Embeddable even though it is as embeddable", - embeddableClass.getName() - ) - ); - } - - List classInfoList = new ArrayList(); - ClassInfo tmpClassInfo; - Class clazz = embeddableClass; - while ( clazz != null && !clazz.equals( Object.class ) ) { - tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) ); - clazz = clazz.getSuperclass(); - if ( tmpClassInfo == null ) { - continue; - } - - classInfoList.add( 0, tmpClassInfo ); - } - - return new EmbeddableHierarchy( - classInfoList, - propertyName, - context, - accessType - ); - } - - @SuppressWarnings("unchecked") - private EmbeddableHierarchy( - List classInfoList, - String propertyName, - AnnotationBindingContext context, - AccessType defaultAccessType) { - this.defaultAccessType = defaultAccessType; - - // the resolved type for the top level class in the hierarchy - context.resolveAllTypes( classInfoList.get( classInfoList.size() - 1 ).name().toString() ); - - embeddables = new ArrayList(); - ConfiguredClass parent = null; - EmbeddableClass embeddable; - for ( ClassInfo info : classInfoList ) { - embeddable = new EmbeddableClass( - info, propertyName, parent, defaultAccessType, context - ); - embeddables.add( embeddable ); - parent = embeddable; - } - } - - - public AccessType getDefaultAccessType() { - return defaultAccessType; - } - - /** - * @return An iterator iterating in top down manner over the configured classes in this hierarchy. - */ - public Iterator iterator() { - return embeddables.iterator(); - } - - /** - * @return Returns the leaf configured class - */ - public EmbeddableClass getLeaf() { - return embeddables.get( embeddables.size() - 1 ); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "EmbeddableHierarchy" ); - sb.append( "{defaultAccessType=" ).append( defaultAccessType ); - sb.append( ", embeddables=" ).append( embeddables ); - sb.append( '}' ); - return sb.toString(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBindingContext.java deleted file mode 100644 index 70c0b2f07e87..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBindingContext.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.SourceType; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.service.ServiceRegistry; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.Index; - -import com.fasterxml.classmate.ResolvedType; -import com.fasterxml.classmate.ResolvedTypeWithMembers; - -/** - * Annotation version of a local binding context. - * - * @author Steve Ebersole - */ -public class EntityBindingContext implements LocalBindingContext, AnnotationBindingContext { - private final AnnotationBindingContext contextDelegate; - private final Origin origin; - - public EntityBindingContext(AnnotationBindingContext contextDelegate, ConfiguredClass source) { - this.contextDelegate = contextDelegate; - this.origin = new Origin( SourceType.ANNOTATION, source.getName() ); - } - - @Override - public Origin getOrigin() { - return origin; - } - - @Override - public ServiceRegistry getServiceRegistry() { - return contextDelegate.getServiceRegistry(); - } - - @Override - public NamingStrategy getNamingStrategy() { - return contextDelegate.getNamingStrategy(); - } - - @Override - public MappingDefaults getMappingDefaults() { - return contextDelegate.getMappingDefaults(); - } - - @Override - public MetadataImplementor getMetadataImplementor() { - return contextDelegate.getMetadataImplementor(); - } - - @Override - public Class locateClassByName(String name) { - return contextDelegate.locateClassByName( name ); - } - - @Override - public Type makeJavaType(String className) { - return contextDelegate.makeJavaType( className ); - } - - @Override - public boolean isGloballyQuotedIdentifiers() { - return contextDelegate.isGloballyQuotedIdentifiers(); - } - - @Override - public ValueHolder> makeClassReference(String className) { - return contextDelegate.makeClassReference( className ); - } - - @Override - public String qualifyClassName(String name) { - return contextDelegate.qualifyClassName( name ); - } - - @Override - public Index getIndex() { - return contextDelegate.getIndex(); - } - - @Override - public ClassInfo getClassInfo(String name) { - return contextDelegate.getClassInfo( name ); - } - - @Override - public void resolveAllTypes(String className) { - contextDelegate.resolveAllTypes( className ); - } - - @Override - public ResolvedType getResolvedType(Class clazz) { - return contextDelegate.getResolvedType( clazz ); - } - - @Override - public ResolvedTypeWithMembers resolveMemberTypes(ResolvedType type) { - return contextDelegate.resolveMemberTypes( type ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java deleted file mode 100644 index d873e89a1756..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java +++ /dev/null @@ -1,986 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.AccessType; -import javax.persistence.DiscriminatorType; -import javax.persistence.PersistenceException; -import javax.persistence.PostLoad; -import javax.persistence.PostPersist; -import javax.persistence.PostRemove; -import javax.persistence.PostUpdate; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; -import javax.persistence.PreUpdate; - -import org.hibernate.AnnotationException; -import org.hibernate.MappingException; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.annotations.OptimisticLockType; -import org.hibernate.annotations.PolymorphismType; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.attribute.ColumnValues; -import org.hibernate.metamodel.source.annotations.attribute.FormulaValue; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; -import org.hibernate.metamodel.source.binder.ConstraintSource; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.metamodel.source.binder.TableSource; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.Type; -import org.jboss.jandex.Type.Kind; - -/** - * Represents an entity or mapped superclass configured via annotations/orm-xml. - * - * @author Hardy Ferentschik - */ -public class EntityClass extends ConfiguredClass { - private final IdType idType; - private final InheritanceType inheritanceType; - - private final String explicitEntityName; - private final String customLoaderQueryName; - private final List synchronizedTableNames; - private final int batchSize; - - private final TableSource primaryTableSource; - private final Set secondaryTableSources; - private final Set constraintSources; - - private boolean isMutable; - private boolean isExplicitPolymorphism; - private OptimisticLockStyle optimisticLockStyle; - private String whereClause; - private String rowId; - private Caching caching; - private boolean isDynamicInsert; - private boolean isDynamicUpdate; - private boolean isSelectBeforeUpdate; - private String customPersister; - - private CustomSQL customInsert; - private CustomSQL customUpdate; - private CustomSQL customDelete; - - private boolean isLazy; - private String proxy; - - private ColumnValues discriminatorColumnValues; - private FormulaValue discriminatorFormula; - private Class discriminatorType; - private String discriminatorMatchValue; - private boolean isDiscriminatorForced = true; - private boolean isDiscriminatorIncludedInSql = true; - - private final List jpaCallbacks; - - public EntityClass( - ClassInfo classInfo, - EntityClass parent, - AccessType hierarchyAccessType, - InheritanceType inheritanceType, - AnnotationBindingContext context) { - super( classInfo, hierarchyAccessType, parent, context ); - this.inheritanceType = inheritanceType; - this.idType = determineIdType(); - boolean hasOwnTable = definesItsOwnTable(); - this.explicitEntityName = determineExplicitEntityName(); - this.constraintSources = new HashSet(); - - if ( hasOwnTable ) { - AnnotationInstance tableAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - JPADotNames.TABLE - ); - this.primaryTableSource = createTableSource( tableAnnotation ); - } - else { - this.primaryTableSource = null; - } - - this.secondaryTableSources = createSecondaryTableSources(); - this.customLoaderQueryName = determineCustomLoader(); - this.synchronizedTableNames = determineSynchronizedTableNames(); - this.batchSize = determineBatchSize(); - this.jpaCallbacks = determineEntityListeners(); - - processHibernateEntitySpecificAnnotations(); - processCustomSqlAnnotations(); - processProxyGeneration(); - processDiscriminator(); - } - - public ColumnValues getDiscriminatorColumnValues() { - return discriminatorColumnValues; - } - - public FormulaValue getDiscriminatorFormula() { - return discriminatorFormula; - } - - public Class getDiscriminatorType() { - return discriminatorType; - } - - public IdType getIdType() { - return idType; - } - - public boolean isExplicitPolymorphism() { - return isExplicitPolymorphism; - } - - public boolean isMutable() { - return isMutable; - } - - public OptimisticLockStyle getOptimisticLockStyle() { - return optimisticLockStyle; - } - - public String getWhereClause() { - return whereClause; - } - - public String getRowId() { - return rowId; - } - - public Caching getCaching() { - return caching; - } - - public TableSource getPrimaryTableSource() { - if ( definesItsOwnTable() ) { - return primaryTableSource; - } - else { - return ( (EntityClass) getParent() ).getPrimaryTableSource(); - } - } - - public Set getSecondaryTableSources() { - return secondaryTableSources; - } - - public Set getConstraintSources() { - return constraintSources; - } - - public String getExplicitEntityName() { - return explicitEntityName; - } - - public String getEntityName() { - return getConfiguredClass().getSimpleName(); - } - - public boolean isDynamicInsert() { - return isDynamicInsert; - } - - public boolean isDynamicUpdate() { - return isDynamicUpdate; - } - - public boolean isSelectBeforeUpdate() { - return isSelectBeforeUpdate; - } - - public String getCustomLoaderQueryName() { - return customLoaderQueryName; - } - - public CustomSQL getCustomInsert() { - return customInsert; - } - - public CustomSQL getCustomUpdate() { - return customUpdate; - } - - public CustomSQL getCustomDelete() { - return customDelete; - } - - public List getSynchronizedTableNames() { - return synchronizedTableNames; - } - - public String getCustomPersister() { - return customPersister; - } - - public boolean isLazy() { - return isLazy; - } - - public String getProxy() { - return proxy; - } - - public int getBatchSize() { - return batchSize; - } - - public boolean isEntityRoot() { - return getParent() == null; - } - - public boolean isDiscriminatorForced() { - return isDiscriminatorForced; - } - - public boolean isDiscriminatorIncludedInSql() { - return isDiscriminatorIncludedInSql; - } - - public String getDiscriminatorMatchValue() { - return discriminatorMatchValue; - } - - public List getJpaCallbacks() { - return jpaCallbacks; - } - - private String determineExplicitEntityName() { - final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.ENTITY - ); - return JandexHelper.getValue( jpaEntityAnnotation, "name", String.class ); - } - - - private boolean definesItsOwnTable() { - return !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) || isEntityRoot(); - } - - private IdType determineIdType() { - List idAnnotations = findIdAnnotations( JPADotNames.ID ); - List embeddedIdAnnotations = findIdAnnotations( JPADotNames.EMBEDDED_ID ); - - if ( !idAnnotations.isEmpty() && !embeddedIdAnnotations.isEmpty() ) { - throw new MappingException( - "@EmbeddedId and @Id cannot be used together. Check the configuration for " + getName() + "." - ); - } - - if ( !embeddedIdAnnotations.isEmpty() ) { - if ( embeddedIdAnnotations.size() == 1 ) { - return IdType.EMBEDDED; - } - else { - throw new AnnotationException( "Multiple @EmbeddedId annotations are not allowed" ); - } - } - - if ( !idAnnotations.isEmpty() ) { - return idAnnotations.size() == 1 ? IdType.SIMPLE : IdType.COMPOSED; - } - return IdType.NONE; - } - - private List findIdAnnotations(DotName idAnnotationType) { - List idAnnotationList = new ArrayList(); - if ( getClassInfo().annotations().containsKey( idAnnotationType ) ) { - idAnnotationList.addAll( getClassInfo().annotations().get( idAnnotationType ) ); - } - ConfiguredClass parent = getParent(); - while ( parent != null ) { - if ( parent.getClassInfo().annotations().containsKey( idAnnotationType ) ) { - idAnnotationList.addAll( parent.getClassInfo().annotations().get( idAnnotationType ) ); - } - parent = parent.getParent(); - } - return idAnnotationList; - } - - private void processDiscriminator() { - if ( !InheritanceType.SINGLE_TABLE.equals( inheritanceType ) ) { - return; - } - - final AnnotationInstance discriminatorValueAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.DISCRIMINATOR_VALUE - ); - if ( discriminatorValueAnnotation != null ) { - this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString(); - } - - final AnnotationInstance discriminatorColumnAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.DISCRIMINATOR_COLUMN - ); - - final AnnotationInstance discriminatorFormulaAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), - HibernateDotNames.DISCRIMINATOR_FORMULA - ); - - - Class type = String.class; // string is the discriminator default - if ( discriminatorFormulaAnnotation != null ) { - String expression = JandexHelper.getValue( discriminatorFormulaAnnotation, "value", String.class ); - discriminatorFormula = new FormulaValue( getPrimaryTableSource().getExplicitTableName(), expression ); - } - discriminatorColumnValues = new ColumnValues( null ); //(stliu) give null here, will populate values below - discriminatorColumnValues.setNullable( false ); // discriminator column cannot be null - if ( discriminatorColumnAnnotation != null ) { - - DiscriminatorType discriminatorType = Enum.valueOf( - DiscriminatorType.class, discriminatorColumnAnnotation.value( "discriminatorType" ).asEnum() - ); - switch ( discriminatorType ) { - case STRING: { - type = String.class; - break; - } - case CHAR: { - type = Character.class; - break; - } - case INTEGER: { - type = Integer.class; - break; - } - default: { - throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType ); - } - } - - discriminatorColumnValues.setName( - JandexHelper.getValue( - discriminatorColumnAnnotation, - "name", - String.class - ) - ); - discriminatorColumnValues.setLength( - JandexHelper.getValue( - discriminatorColumnAnnotation, - "length", - Integer.class - ) - ); - discriminatorColumnValues.setColumnDefinition( - JandexHelper.getValue( - discriminatorColumnAnnotation, - "columnDefinition", - String.class - ) - ); - } - discriminatorType = type; - - AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.DISCRIMINATOR_OPTIONS - ); - if ( discriminatorOptionsAnnotation != null ) { - isDiscriminatorForced = discriminatorOptionsAnnotation.value( "force" ).asBoolean(); - isDiscriminatorIncludedInSql = discriminatorOptionsAnnotation.value( "insert" ).asBoolean(); - } - else { - isDiscriminatorForced = false; - isDiscriminatorIncludedInSql = true; - } - } - - private void processHibernateEntitySpecificAnnotations() { - final AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.ENTITY - ); - - // see HHH-6400 - PolymorphismType polymorphism = PolymorphismType.IMPLICIT; - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "polymorphism" ) != null ) { - polymorphism = PolymorphismType.valueOf( hibernateEntityAnnotation.value( "polymorphism" ).asEnum() ); - } - isExplicitPolymorphism = polymorphism == PolymorphismType.EXPLICIT; - - // see HHH-6401 - OptimisticLockType optimisticLockType = OptimisticLockType.VERSION; - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "optimisticLock" ) != null ) { - optimisticLockType = OptimisticLockType.valueOf( - hibernateEntityAnnotation.value( "optimisticLock" ) - .asEnum() - ); - } - optimisticLockStyle = OptimisticLockStyle.valueOf( optimisticLockType.name() ); - - final AnnotationInstance hibernateImmutableAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.IMMUTABLE - ); - isMutable = hibernateImmutableAnnotation == null - && hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "mutable" ) != null - && hibernateEntityAnnotation.value( "mutable" ).asBoolean(); - - - final AnnotationInstance whereAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.WHERE - ); - whereClause = whereAnnotation != null && whereAnnotation.value( "clause" ) != null ? - whereAnnotation.value( "clause" ).asString() : null; - - final AnnotationInstance rowIdAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.ROW_ID - ); - rowId = rowIdAnnotation != null && rowIdAnnotation.value() != null - ? rowIdAnnotation.value().asString() : null; - - caching = determineCachingSettings(); - - // see HHH-6397 - isDynamicInsert = - hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "dynamicInsert" ) != null - && hibernateEntityAnnotation.value( "dynamicInsert" ).asBoolean(); - - // see HHH-6398 - isDynamicUpdate = - hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "dynamicUpdate" ) != null - && hibernateEntityAnnotation.value( "dynamicUpdate" ).asBoolean(); - - - // see HHH-6399 - isSelectBeforeUpdate = - hibernateEntityAnnotation != null - && hibernateEntityAnnotation.value( "selectBeforeUpdate" ) != null - && hibernateEntityAnnotation.value( "selectBeforeUpdate" ).asBoolean(); - - // Custom persister - final String entityPersisterClass; - final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.PERSISTER - ); - if ( persisterAnnotation == null || persisterAnnotation.value( "impl" ) == null ) { - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "persister" ) != null ) { - entityPersisterClass = hibernateEntityAnnotation.value( "persister" ).asString(); - } - else { - entityPersisterClass = null; - } - } - else { - if ( hibernateEntityAnnotation != null && hibernateEntityAnnotation.value( "persister" ) != null ) { - // todo : error? - } - entityPersisterClass = persisterAnnotation.value( "impl" ).asString(); - } - this.customPersister = entityPersisterClass; - } - - private Caching determineCachingSettings() { - final AnnotationInstance hibernateCacheAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.CACHE - ); - if ( hibernateCacheAnnotation != null ) { - final org.hibernate.cache.spi.access.AccessType accessType = hibernateCacheAnnotation.value( "usage" ) == null - ? getLocalBindingContext().getMappingDefaults().getCacheAccessType() - : CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() ) - .toAccessType(); - return new Caching( - hibernateCacheAnnotation.value( "region" ) == null - ? getName() - : hibernateCacheAnnotation.value( "region" ).asString(), - accessType, - hibernateCacheAnnotation.value( "include" ) != null - && "all".equals( hibernateCacheAnnotation.value( "include" ).asString() ) - ); - } - - final AnnotationInstance jpaCacheableAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), JPADotNames.CACHEABLE - ); - - boolean cacheable = true; // true is the default - if ( jpaCacheableAnnotation != null && jpaCacheableAnnotation.value() != null ) { - cacheable = jpaCacheableAnnotation.value().asBoolean(); - } - - final boolean doCaching; - switch ( getLocalBindingContext().getMetadataImplementor().getOptions().getSharedCacheMode() ) { - case ALL: { - doCaching = true; - break; - } - case ENABLE_SELECTIVE: { - doCaching = cacheable; - break; - } - case DISABLE_SELECTIVE: { - doCaching = jpaCacheableAnnotation == null || cacheable; - break; - } - default: { - // treat both NONE and UNSPECIFIED the same - doCaching = false; - break; - } - } - - if ( !doCaching ) { - return null; - } - - return new Caching( - getName(), - getLocalBindingContext().getMappingDefaults().getCacheAccessType(), - true - ); - } - - /** - * todo see {@code Binder#createTable} - * - * @param tableAnnotation a annotation instance, either {@link javax.persistence.Table} or {@link javax.persistence.SecondaryTable} - * - * @return A table source for the specified annotation instance - */ - private TableSource createTableSource(AnnotationInstance tableAnnotation) { - String schema = null; - String catalog = null; - if ( tableAnnotation != null ) { - schema = JandexHelper.getValue( tableAnnotation, "schema", String.class ); - catalog = JandexHelper.getValue( tableAnnotation, "catalog", String.class ); - } - // process the table name - String tableName = null; - String logicalTableName = null; - - if ( tableAnnotation != null ) { - logicalTableName = JandexHelper.getValue( tableAnnotation, "name", String.class ); - if ( StringHelper.isNotEmpty( logicalTableName ) ) { - tableName = logicalTableName; - } - createUniqueConstraints( tableAnnotation, tableName ); - } - - TableSourceImpl tableSourceImpl; - if ( tableAnnotation == null || JPADotNames.TABLE.equals( tableAnnotation.name() ) ) { - // for the main table @Table we use 'null' as logical name - tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, null ); - } - else { - // for secondary tables a name must be specified which is used as logical table name - tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, logicalTableName ); - } - return tableSourceImpl; - } - - private Set createSecondaryTableSources() { - Set secondaryTableSources = new HashSet(); - AnnotationInstance secondaryTables = JandexHelper.getSingleAnnotation( - getClassInfo(), - JPADotNames.SECONDARY_TABLES - ); - AnnotationInstance secondaryTable = JandexHelper.getSingleAnnotation( - getClassInfo(), - JPADotNames.SECONDARY_TABLE - ); - // collect all @secondaryTable annotations - List secondaryTableAnnotations = new ArrayList(); - if ( secondaryTable != null ) { - secondaryTableAnnotations.add( - secondaryTable - ); - } - - if ( secondaryTables != null ) { - secondaryTableAnnotations.addAll( - Arrays.asList( - JandexHelper.getValue( secondaryTables, "value", AnnotationInstance[].class ) - ) - ); - } - - // create table sources - for ( AnnotationInstance annotationInstance : secondaryTableAnnotations ) { - secondaryTableSources.add( createTableSource( annotationInstance ) ); - } - - return secondaryTableSources; - } - - - private void createUniqueConstraints(AnnotationInstance tableAnnotation, String tableName) { - AnnotationValue value = tableAnnotation.value( "uniqueConstraints" ); - if ( value == null ) { - return; - } - - AnnotationInstance[] uniqueConstraints = value.asNestedArray(); - for ( AnnotationInstance unique : uniqueConstraints ) { - String name = unique.value( "name" ) == null ? null : unique.value( "name" ).asString(); - String[] columnNames = unique.value( "columnNames" ).asStringArray(); - UniqueConstraintSourceImpl uniqueConstraintSource = - new UniqueConstraintSourceImpl( - name, tableName, Arrays.asList( columnNames ) - ); - constraintSources.add( uniqueConstraintSource ); - } - } - - private String determineCustomLoader() { - String customLoader = null; - // Custom sql loader - final AnnotationInstance sqlLoaderAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.LOADER - ); - if ( sqlLoaderAnnotation != null ) { - customLoader = sqlLoaderAnnotation.value( "namedQuery" ).asString(); - } - return customLoader; - } - - private CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation) { - if ( customSqlAnnotation == null ) { - return null; - } - - final String sql = customSqlAnnotation.value( "sql" ).asString(); - final boolean isCallable = customSqlAnnotation.value( "callable" ) != null - && customSqlAnnotation.value( "callable" ).asBoolean(); - - final ExecuteUpdateResultCheckStyle checkStyle = customSqlAnnotation.value( "check" ) == null - ? isCallable - ? ExecuteUpdateResultCheckStyle.NONE - : ExecuteUpdateResultCheckStyle.COUNT - : ExecuteUpdateResultCheckStyle.valueOf( customSqlAnnotation.value( "check" ).asEnum() ); - - return new CustomSQL( sql, isCallable, checkStyle ); - } - - private void processCustomSqlAnnotations() { - // Custom sql insert - final AnnotationInstance sqlInsertAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SQL_INSERT - ); - customInsert = createCustomSQL( sqlInsertAnnotation ); - - // Custom sql update - final AnnotationInstance sqlUpdateAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SQL_UPDATE - ); - customUpdate = createCustomSQL( sqlUpdateAnnotation ); - - // Custom sql delete - final AnnotationInstance sqlDeleteAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SQL_DELETE - ); - customDelete = createCustomSQL( sqlDeleteAnnotation ); - } - - private List determineSynchronizedTableNames() { - final AnnotationInstance synchronizeAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.SYNCHRONIZE - ); - if ( synchronizeAnnotation != null ) { - final String[] tableNames = synchronizeAnnotation.value().asStringArray(); - return Arrays.asList( tableNames ); - } - else { - return Collections.emptyList(); - } - } - - private void processProxyGeneration() { - // Proxy generation - final AnnotationInstance hibernateProxyAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.PROXY - ); - if ( hibernateProxyAnnotation != null ) { - isLazy = hibernateProxyAnnotation.value( "lazy" ) == null - || hibernateProxyAnnotation.value( "lazy" ).asBoolean(); - if ( isLazy ) { - final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" ); - if ( proxyClassValue == null ) { - proxy = getName(); - } - else { - proxy = proxyClassValue.asString(); - } - } - else { - proxy = null; - } - } - else { - isLazy = true; - proxy = getName(); - } - } - - private int determineBatchSize() { - final AnnotationInstance batchSizeAnnotation = JandexHelper.getSingleAnnotation( - getClassInfo(), HibernateDotNames.BATCH_SIZE - ); - return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt(); - } - - private List determineEntityListeners() { - List callbackClassList = new ArrayList(); - - // Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded) - if ( JandexHelper.getSingleAnnotation( getClassInfo(), JPADotNames.EXCLUDE_DEFAULT_LISTENERS ) == null ) { - List defaultEntityListenerAnnotations = getLocalBindingContext().getIndex() - .getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); - for ( AnnotationInstance annotation : defaultEntityListenerAnnotations ) { - for ( Type callbackClass : annotation.value().asClassArray() ) { - String callbackClassName = callbackClass.name().toString(); - try { - processDefaultJpaCallbacks( callbackClassName, callbackClassList ); - } - catch ( PersistenceException error ) { - throw new PersistenceException( error.getMessage() + "default entity listener " + callbackClassName ); - } - } - } - } - - // Bind JPA entity listener callbacks, using superclasses first (unless excluded) - List annotationList = getClassInfo().annotations().get( JPADotNames.ENTITY_LISTENERS ); - if ( annotationList != null ) { - for ( AnnotationInstance annotation : annotationList ) { - for ( Type callbackClass : annotation.value().asClassArray() ) { - String callbackClassName = callbackClass.name().toString(); - try { - processJpaCallbacks( callbackClassName, true, callbackClassList ); - } - catch ( PersistenceException error ) { - throw new PersistenceException( error.getMessage() + "entity listener " + callbackClassName ); - } - } - } - } - - // Bind JPA entity.mapped superclass callbacks, using superclasses first (unless excluded) - try { - processJpaCallbacks( getName(), false, callbackClassList ); - } - catch ( PersistenceException error ) { - throw new PersistenceException( - error.getMessage() + "entity/mapped superclass " + getClassInfo().name().toString() - ); - } - - return callbackClassList; - } - - private void processDefaultJpaCallbacks(String instanceCallbackClassName, List jpaCallbackClassList) { - ClassInfo callbackClassInfo = getLocalBindingContext().getClassInfo( instanceCallbackClassName ); - - // Process superclass first if available and not excluded - if ( JandexHelper.getSingleAnnotation( callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ) != null ) { - DotName superName = callbackClassInfo.superName(); - if ( superName != null ) { - processDefaultJpaCallbacks( instanceCallbackClassName, jpaCallbackClassList ); - } - } - - String callbackClassName = callbackClassInfo.name().toString(); - Map, String> callbacksByType = new HashMap, String>(); - createDefaultCallback( - PrePersist.class, PseudoJpaDotNames.DEFAULT_PRE_PERSIST, callbackClassName, callbacksByType - ); - createDefaultCallback( - PreRemove.class, PseudoJpaDotNames.DEFAULT_PRE_REMOVE, callbackClassName, callbacksByType - ); - createDefaultCallback( - PreUpdate.class, PseudoJpaDotNames.DEFAULT_PRE_UPDATE, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostLoad.class, PseudoJpaDotNames.DEFAULT_POST_LOAD, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostPersist.class, PseudoJpaDotNames.DEFAULT_POST_PERSIST, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostRemove.class, PseudoJpaDotNames.DEFAULT_POST_REMOVE, callbackClassName, callbacksByType - ); - createDefaultCallback( - PostUpdate.class, PseudoJpaDotNames.DEFAULT_POST_UPDATE, callbackClassName, callbacksByType - ); - if ( !callbacksByType.isEmpty() ) { - jpaCallbackClassList.add( new JpaCallbackClassImpl( instanceCallbackClassName, callbacksByType, true ) ); - } - } - - private void processJpaCallbacks(String instanceCallbackClassName, boolean isListener, List callbackClassList) { - - ClassInfo callbackClassInfo = getLocalBindingContext().getClassInfo( instanceCallbackClassName ); - - // Process superclass first if available and not excluded - if ( JandexHelper.getSingleAnnotation( callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ) != null ) { - DotName superName = callbackClassInfo.superName(); - if ( superName != null ) { - processJpaCallbacks( - instanceCallbackClassName, - isListener, - callbackClassList - ); - } - } - - Map, String> callbacksByType = new HashMap, String>(); - createCallback( PrePersist.class, JPADotNames.PRE_PERSIST, callbacksByType, callbackClassInfo, isListener ); - createCallback( PreRemove.class, JPADotNames.PRE_REMOVE, callbacksByType, callbackClassInfo, isListener ); - createCallback( PreUpdate.class, JPADotNames.PRE_UPDATE, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostLoad.class, JPADotNames.POST_LOAD, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostPersist.class, JPADotNames.POST_PERSIST, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostRemove.class, JPADotNames.POST_REMOVE, callbacksByType, callbackClassInfo, isListener ); - createCallback( PostUpdate.class, JPADotNames.POST_UPDATE, callbacksByType, callbackClassInfo, isListener ); - if ( !callbacksByType.isEmpty() ) { - callbackClassList.add( new JpaCallbackClassImpl( instanceCallbackClassName, callbacksByType, isListener ) ); - } - } - - private void createDefaultCallback(Class callbackTypeClass, - DotName callbackTypeName, - String callbackClassName, - Map, String> callbacksByClass) { - for ( AnnotationInstance callback : getLocalBindingContext().getIndex().getAnnotations( callbackTypeName ) ) { - MethodInfo methodInfo = (MethodInfo) callback.target(); - validateMethod( methodInfo, callbackTypeClass, callbacksByClass, true ); - if ( methodInfo.declaringClass().name().toString().equals( callbackClassName ) ) { - if ( methodInfo.args().length != 1 ) { - throw new PersistenceException( - String.format( - "Callback method %s must have exactly one argument defined as either Object or %s in ", - methodInfo.name(), - getEntityName() - ) - ); - } - callbacksByClass.put( callbackTypeClass, methodInfo.name() ); - } - } - } - - private void createCallback(Class callbackTypeClass, - DotName callbackTypeName, - Map, String> callbacksByClass, - ClassInfo callbackClassInfo, - boolean isListener) { - Map> annotations = callbackClassInfo.annotations(); - List annotationInstances = annotations.get( callbackTypeName ); - if ( annotationInstances == null ) { - return; - } - for ( AnnotationInstance callbackAnnotation : annotationInstances ) { - MethodInfo methodInfo = (MethodInfo) callbackAnnotation.target(); - validateMethod( methodInfo, callbackTypeClass, callbacksByClass, isListener ); - callbacksByClass.put( callbackTypeClass, methodInfo.name() ); - } - } - - private void validateMethod(MethodInfo methodInfo, - Class callbackTypeClass, - Map, String> callbacksByClass, - boolean isListener) { - if ( methodInfo.returnType().kind() != Kind.VOID ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must have a void return type in " ); - } - if ( Modifier.isStatic( methodInfo.flags() ) || Modifier.isFinal( methodInfo.flags() ) ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must not be static or final in " ); - } - Type[] argTypes = methodInfo.args(); - if ( isListener ) { - if ( argTypes.length != 1 ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must have exactly one argument in " ); - } - String argTypeName = argTypes[0].name().toString(); - if ( !argTypeName.equals( Object.class.getName() ) && !argTypeName.equals( getName() ) ) { - throw new PersistenceException( - "The argument for callback method " + methodInfo.name() + - " must be defined as either Object or " + getEntityName() + " in " - ); - } - } - else if ( argTypes.length != 0 ) { - throw new PersistenceException( "Callback method " + methodInfo.name() + " must have no arguments in " ); - } - if ( callbacksByClass.containsKey( callbackTypeClass ) ) { - throw new PersistenceException( - "Only one method may be annotated as a " + callbackTypeClass.getSimpleName() + - " callback method in " - ); - } - } - - // Process JPA callbacks, in superclass-first order (unless superclasses are excluded), using default listeners first - // (unless default listeners are excluded), then entity listeners, and finally the entity/mapped superclass itself - private class JpaCallbackClassImpl implements JpaCallbackClass { - - private final Map, String> callbacksByType; - private final String name; - private final boolean isListener; - - private JpaCallbackClassImpl(String name, - Map, String> callbacksByType, - boolean isListener) { - this.name = name; - this.callbacksByType = callbacksByType; - this.isListener = isListener; - } - - @Override - public String getCallbackMethod(Class callbackType) { - return callbacksByType.get( callbackType ); - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean isListener() { - return isListener; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java deleted file mode 100644 index 4c6c677e4e3f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntitySourceImpl.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; -import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.ToOneAttributeSourceImpl; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.ConstraintSource; -import org.hibernate.metamodel.source.binder.EntitySource; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Hardy Ferentschik - */ -public class EntitySourceImpl implements EntitySource { - private final EntityClass entityClass; - private final Set subclassEntitySources; - - public EntitySourceImpl(EntityClass entityClass) { - this.entityClass = entityClass; - this.subclassEntitySources = new HashSet(); - } - - public EntityClass getEntityClass() { - return entityClass; - } - - @Override - public Origin getOrigin() { - return entityClass.getLocalBindingContext().getOrigin(); - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return entityClass.getLocalBindingContext(); - } - - @Override - public String getEntityName() { - return entityClass.getName(); - } - - @Override - public String getClassName() { - return entityClass.getName(); - } - - @Override - public String getJpaEntityName() { - return entityClass.getExplicitEntityName(); - } - - @Override - public TableSource getPrimaryTable() { - return entityClass.getPrimaryTableSource(); - } - - @Override - public boolean isAbstract() { - return false; - } - - @Override - public boolean isLazy() { - return entityClass.isLazy(); - } - - @Override - public String getProxy() { - return entityClass.getProxy(); - } - - @Override - public int getBatchSize() { - return entityClass.getBatchSize(); - } - - @Override - public boolean isDynamicInsert() { - return entityClass.isDynamicInsert(); - } - - @Override - public boolean isDynamicUpdate() { - return entityClass.isDynamicUpdate(); - } - - @Override - public boolean isSelectBeforeUpdate() { - return entityClass.isSelectBeforeUpdate(); - } - - @Override - public String getCustomTuplizerClassName() { - return entityClass.getCustomTuplizer(); - } - - @Override - public String getCustomPersisterClassName() { - return entityClass.getCustomPersister(); - } - - @Override - public String getCustomLoaderName() { - return entityClass.getCustomLoaderQueryName(); - } - - @Override - public CustomSQL getCustomSqlInsert() { - return entityClass.getCustomInsert(); - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return entityClass.getCustomUpdate(); - } - - @Override - public CustomSQL getCustomSqlDelete() { - return entityClass.getCustomDelete(); - } - - @Override - public List getSynchronizedTableNames() { - return entityClass.getSynchronizedTableNames(); - } - - @Override - public Iterable metaAttributes() { - return Collections.emptySet(); - } - - @Override - public String getPath() { - return entityClass.getName(); - } - - @Override - public Iterable attributeSources() { - List attributeList = new ArrayList(); - for ( BasicAttribute attribute : entityClass.getSimpleAttributes() ) { - attributeList.add( new SingularAttributeSourceImpl( attribute ) ); - } - for ( EmbeddableClass component : entityClass.getEmbeddedClasses().values() ) { - attributeList.add( - new ComponentAttributeSourceImpl( - component, - "", - entityClass.getAttributeOverrideMap() - ) - ); - } - for ( AssociationAttribute associationAttribute : entityClass.getAssociationAttributes() ) { - attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) ); - } - return attributeList; - } - - @Override - public void add(SubclassEntitySource subclassEntitySource) { - subclassEntitySources.add( subclassEntitySource ); - } - - @Override - public Iterable subclassEntitySources() { - return subclassEntitySources; - } - - @Override - public String getDiscriminatorMatchValue() { - return entityClass.getDiscriminatorMatchValue(); - } - - @Override - public Iterable getConstraints() { - return entityClass.getConstraintSources(); - } - - @Override - public List getJpaCallbackClasses() { - return entityClass.getJpaCallbacks(); - } - - @Override - public Iterable getSecondaryTables() { - return entityClass.getSecondaryTableSources(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java deleted file mode 100644 index 164e756af79d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/IdType.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -/** - * An emum for the type of id configuration for an entity. - * - * @author Hardy Ferentschik - */ -public enum IdType { - // single @Id annotation - SIMPLE, - // multiple @Id annotations - COMPOSED, - // @EmbeddedId annotation - EMBEDDED, - // does not contain any identifier mappings - NONE -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java deleted file mode 100644 index 808c0b0cd92d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/RootEntitySourceImpl.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; -import org.hibernate.metamodel.source.annotations.attribute.DiscriminatorSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.SimpleIdentifierSourceImpl; -import org.hibernate.metamodel.source.annotations.attribute.SingularAttributeSourceImpl; -import org.hibernate.metamodel.source.binder.DiscriminatorSource; -import org.hibernate.metamodel.source.binder.IdentifierSource; -import org.hibernate.metamodel.source.binder.RootEntitySource; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * @author Hardy Ferentschik - */ -public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntitySource { - public RootEntitySourceImpl(EntityClass entityClass) { - super( entityClass ); - } - - @Override - public IdentifierSource getIdentifierSource() { - IdType idType = getEntityClass().getIdType(); - switch ( idType ) { - case SIMPLE: { - BasicAttribute attribute = getEntityClass().getIdAttributes().iterator().next(); - return new SimpleIdentifierSourceImpl( attribute, getEntityClass().getAttributeOverrideMap() ); - } - case COMPOSED: { - throw new NotYetImplementedException( "Composed ids must still be implemented." ); - } - case EMBEDDED: { - throw new NotYetImplementedException( "Embedded ids must still be implemented." ); - } - default: { - throw new AssertionFailure( "The root entity needs to specify an identifier" ); - } - } - } - - @Override - public SingularAttributeSource getVersioningAttributeSource() { - SingularAttributeSource attributeSource = null; - EntityClass entityClass = getEntityClass(); - if ( entityClass.getVersionAttribute() != null ) { - attributeSource = new SingularAttributeSourceImpl( entityClass.getVersionAttribute() ); - } - return attributeSource; - } - - @Override - public DiscriminatorSource getDiscriminatorSource() { - DiscriminatorSource discriminatorSource = null; - if ( getEntityClass().getDiscriminatorColumnValues() != null ) { - discriminatorSource = new DiscriminatorSourceImpl( getEntityClass() ); - } - return discriminatorSource; - } - - @Override - public EntityMode getEntityMode() { - return EntityMode.POJO; - } - - @Override - public boolean isMutable() { - return getEntityClass().isMutable(); - } - - @Override - public boolean isExplicitPolymorphism() { - return getEntityClass().isExplicitPolymorphism(); - } - - @Override - public String getWhere() { - return getEntityClass().getWhereClause(); - } - - @Override - public String getRowId() { - return getEntityClass().getRowId(); - } - - @Override - public OptimisticLockStyle getOptimisticLockStyle() { - return getEntityClass().getOptimisticLockStyle(); - } - - @Override - public Caching getCaching() { - return getEntityClass().getCaching(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java deleted file mode 100644 index 8fa01ef480bb..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/SubclassEntitySourceImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import org.hibernate.metamodel.source.binder.SubclassEntitySource; - -/** - * @author Hardy Ferentschik - */ -public class SubclassEntitySourceImpl extends EntitySourceImpl implements SubclassEntitySource { - public SubclassEntitySourceImpl(EntityClass entityClass) { - super( entityClass ); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/TableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/TableSourceImpl.java deleted file mode 100644 index 716a483e3cc7..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/TableSourceImpl.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import org.hibernate.metamodel.source.binder.TableSource; - -class TableSourceImpl implements TableSource { - private final String schema; - private final String catalog; - private final String tableName; - private final String logicalName; - - TableSourceImpl(String schema, String catalog, String tableName, String logicalName) { - this.schema = schema; - this.catalog = catalog; - this.tableName = tableName; - this.logicalName = logicalName; - } - - @Override - public String getExplicitSchemaName() { - return schema; - } - - @Override - public String getExplicitCatalogName() { - return catalog; - } - - @Override - public String getExplicitTableName() { - return tableName; - } - - @Override - public String getLogicalName() { - return logicalName; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - TableSourceImpl that = (TableSourceImpl) o; - - if ( catalog != null ? !catalog.equals( that.catalog ) : that.catalog != null ) { - return false; - } - if ( logicalName != null ? !logicalName.equals( that.logicalName ) : that.logicalName != null ) { - return false; - } - if ( schema != null ? !schema.equals( that.schema ) : that.schema != null ) { - return false; - } - if ( tableName != null ? !tableName.equals( that.tableName ) : that.tableName != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = schema != null ? schema.hashCode() : 0; - result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 ); - result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); - result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 ); - return result; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "TableSourceImpl" ); - sb.append( "{schema='" ).append( schema ).append( '\'' ); - sb.append( ", catalog='" ).append( catalog ).append( '\'' ); - sb.append( ", tableName='" ).append( tableName ).append( '\'' ); - sb.append( ", logicalName='" ).append( logicalName ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintSourceImpl.java deleted file mode 100644 index 3e26ca40b7ae..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintSourceImpl.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.List; - -import org.hibernate.metamodel.source.binder.UniqueConstraintSource; - -/** - * @author Hardy Ferentschik - */ -class UniqueConstraintSourceImpl implements UniqueConstraintSource { - private final String name; - private final String tableName; - private final List columnNames; - - UniqueConstraintSourceImpl(String name, String tableName, List columnNames) { - this.name = name; - this.tableName = tableName; - this.columnNames = columnNames; - } - - @Override - public String name() { - return name; - } - - @Override - public String getTableName() { - return tableName; - } - - @Override - public Iterable columnNames() { - return columnNames; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - - UniqueConstraintSourceImpl that = (UniqueConstraintSourceImpl) o; - - if ( columnNames != null ? !columnNames.equals( that.columnNames ) : that.columnNames != null ) { - return false; - } - if ( name != null ? !name.equals( that.name ) : that.name != null ) { - return false; - } - if ( tableName != null ? !tableName.equals( that.tableName ) : that.tableName != null ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = name != null ? name.hashCode() : 0; - result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); - result = 31 * result + ( columnNames != null ? columnNames.hashCode() : 0 ); - return result; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "UniqueConstraintSourceImpl" ); - sb.append( "{name='" ).append( name ).append( '\'' ); - sb.append( ", tableName='" ).append( tableName ).append( '\'' ); - sb.append( ", columnNames=" ).append( columnNames ); - sb.append( '}' ); - return sb.toString(); - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java deleted file mode 100644 index 712d52c3f196..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinder.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.hibernate.MappingException; -import org.hibernate.annotations.FetchMode; -import org.hibernate.annotations.FetchProfiles; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.FetchProfile.Fetch; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; - -/** - * Binds fetch profiles found in annotations. - * - * @author Hardy Ferentschik - */ -public class FetchProfileBinder { - - private FetchProfileBinder() { - } - - /** - * Binds all {@link FetchProfiles} and {@link org.hibernate.annotations.FetchProfile} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - // TODO verify that association exists. See former VerifyFetchProfileReferenceSecondPass - public static void bind(AnnotationBindingContext bindingContext) { - - List annotations = bindingContext.getIndex() - .getAnnotations( HibernateDotNames.FETCH_PROFILE ); - for ( AnnotationInstance fetchProfile : annotations ) { - bind( bindingContext.getMetadataImplementor(), fetchProfile ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FETCH_PROFILES ); - for ( AnnotationInstance fetchProfiles : annotations ) { - AnnotationInstance[] fetchProfileAnnotations = JandexHelper.getValue( - fetchProfiles, - "value", - AnnotationInstance[].class - ); - for ( AnnotationInstance fetchProfile : fetchProfileAnnotations ) { - bind( bindingContext.getMetadataImplementor(), fetchProfile ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance fetchProfile) { - String name = JandexHelper.getValue( fetchProfile, "name", String.class ); - Set fetches = new HashSet(); - AnnotationInstance[] overrideAnnotations = JandexHelper.getValue( - fetchProfile, - "fetchOverrides", - AnnotationInstance[].class - ); - for ( AnnotationInstance override : overrideAnnotations ) { - FetchMode fetchMode = JandexHelper.getEnumValue( override, "mode", FetchMode.class ); - if ( !fetchMode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) { - throw new MappingException( "Only FetchMode.JOIN is currently supported" ); - } - final String entityName = JandexHelper.getValue( override, "entity", String.class ); - final String associationName = JandexHelper.getValue( override, "association", String.class ); - fetches.add( new Fetch( entityName, associationName, fetchMode.toString().toLowerCase() ) ); - } - metadata.addFetchProfile( new FetchProfile( name, fetches ) ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java deleted file mode 100644 index 9c5c5c26fd86..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/FilterDefBinder.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.annotations.FilterDef; -import org.hibernate.annotations.FilterDefs; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.type.Type; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds {@link FilterDefs} and {@link FilterDef} annotations. - * - * @author Hardy Ferentschik - */ -public class FilterDefBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - FilterDefBinder.class.getName() - ); - - /** - * Binds all {@link FilterDefs} and {@link FilterDef} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FILTER_DEF ); - for ( AnnotationInstance filterDef : annotations ) { - bind( bindingContext.getMetadataImplementor(), filterDef ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.FILTER_DEFS ); - for ( AnnotationInstance filterDefs : annotations ) { - AnnotationInstance[] filterDefAnnotations = JandexHelper.getValue( - filterDefs, - "value", - AnnotationInstance[].class - ); - for ( AnnotationInstance filterDef : filterDefAnnotations ) { - bind( bindingContext.getMetadataImplementor(), filterDef ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance filterDef) { - String name = JandexHelper.getValue( filterDef, "name", String.class ); - Map prms = new HashMap(); - for ( AnnotationInstance prm : JandexHelper.getValue( filterDef, "parameters", AnnotationInstance[].class ) ) { - prms.put( - JandexHelper.getValue( prm, "name", String.class ), - metadata.getTypeResolver().heuristicType( JandexHelper.getValue( prm, "type", String.class ) ) - ); - } - metadata.addFilterDefinition( - new FilterDefinition( - name, - JandexHelper.getValue( filterDef, "defaultCondition", String.class ), - prms - ) - ); - LOG.debugf( "Binding filter definition: %s", name ); - } - - private FilterDefBinder() { - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java deleted file mode 100644 index 8039fd7802da..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.persistence.GenerationType; -import javax.persistence.SequenceGenerator; - -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.GenericGenerators; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.id.MultipleHiLoPerTableGenerator; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.SequenceHiLoGenerator; -import org.hibernate.id.TableHiLoGenerator; -import org.hibernate.id.enhanced.SequenceStyleGenerator; -import org.hibernate.id.enhanced.TableGenerator; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.EnumConversionHelper; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and - * {@link GenericGenerators} annotations. - * - * @author Hardy Ferentschik - */ -public class IdGeneratorBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - IdGeneratorBinder.class.getName() - ); - - private IdGeneratorBinder() { - } - - /** - * Binds all {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and - * {@link GenericGenerators} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex() - .getAnnotations( JPADotNames.SEQUENCE_GENERATOR ); - for ( AnnotationInstance generator : annotations ) { - bindSequenceGenerator( bindingContext.getMetadataImplementor(), generator ); - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.TABLE_GENERATOR ); - for ( AnnotationInstance generator : annotations ) { - bindTableGenerator( bindingContext.getMetadataImplementor(), generator ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.GENERIC_GENERATOR ); - for ( AnnotationInstance generator : annotations ) { - bindGenericGenerator( bindingContext.getMetadataImplementor(), generator ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.GENERIC_GENERATORS ); - for ( AnnotationInstance generators : annotations ) { - for ( AnnotationInstance generator : JandexHelper.getValue( - generators, - "value", - AnnotationInstance[].class - ) ) { - bindGenericGenerator( bindingContext.getMetadataImplementor(), generator ); - } - } - } - - private static void addStringParameter(AnnotationInstance annotation, - String element, - Map parameters, - String parameter) { - String string = JandexHelper.getValue( annotation, element, String.class ); - if ( StringHelper.isNotEmpty( string ) ) { - parameters.put( parameter, string ); - } - } - - private static void bindGenericGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValue( generator, "name", String.class ); - Map parameterMap = new HashMap(); - AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( - generator, - "parameters", - AnnotationInstance[].class - ); - for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { - parameterMap.put( - JandexHelper.getValue( parameterAnnotation, "name", String.class ), - JandexHelper.getValue( parameterAnnotation, "value", String.class ) - ); - } - metadata.addIdGenerator( - new IdGenerator( - name, - JandexHelper.getValue( generator, "strategy", String.class ), - parameterMap - ) - ); - LOG.tracef( "Add generic generator with name: %s", name ); - } - - private static void bindSequenceGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValue( generator, "name", String.class ); - Map parameterMap = new HashMap(); - addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM ); - boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); - String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( - GenerationType.SEQUENCE, - useNewIdentifierGenerators - ); - if ( useNewIdentifierGenerators ) { - addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG ); - addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA ); - parameterMap.put( - SequenceStyleGenerator.INCREMENT_PARAM, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) ) - ); - parameterMap.put( - SequenceStyleGenerator.INITIAL_PARAM, - String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class ) ) - ); - } - else { - if ( JandexHelper.getValue( generator, "initialValue", Integer.class ) != 1 ) { - LOG.unsupportedInitialValue( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS ); - } - parameterMap.put( - SequenceHiLoGenerator.MAX_LO, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 ) - ); - } - metadata.addIdGenerator( new IdGenerator( name, strategy, parameterMap ) ); - LOG.tracef( "Add sequence generator with name: %s", name ); - } - - private static void bindTableGenerator(MetadataImplementor metadata, AnnotationInstance generator) { - String name = JandexHelper.getValue( generator, "name", String.class ); - Map parameterMap = new HashMap(); - addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG ); - addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA ); - boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); - String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( - GenerationType.TABLE, - useNewIdentifierGenerators - ); - if ( useNewIdentifierGenerators ) { - parameterMap.put( TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); - addStringParameter( generator, "table", parameterMap, TableGenerator.TABLE_PARAM ); - addStringParameter( generator, "pkColumnName", parameterMap, TableGenerator.SEGMENT_COLUMN_PARAM ); - addStringParameter( generator, "pkColumnValue", parameterMap, TableGenerator.SEGMENT_VALUE_PARAM ); - addStringParameter( generator, "valueColumnName", parameterMap, TableGenerator.VALUE_COLUMN_PARAM ); - parameterMap.put( - TableGenerator.INCREMENT_PARAM, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", String.class ) ) - ); - parameterMap.put( - TableGenerator.INITIAL_PARAM, - String.valueOf( JandexHelper.getValue( generator, "initialValue", String.class ) + 1 ) - ); - } - else { - addStringParameter( generator, "table", parameterMap, MultipleHiLoPerTableGenerator.ID_TABLE ); - addStringParameter( generator, "pkColumnName", parameterMap, MultipleHiLoPerTableGenerator.PK_COLUMN_NAME ); - addStringParameter( generator, "pkColumnValue", parameterMap, MultipleHiLoPerTableGenerator.PK_VALUE_NAME ); - addStringParameter( generator, "valueColumnName", parameterMap, MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME ); - parameterMap.put( - TableHiLoGenerator.MAX_LO, - String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class ) - 1 ) - ); - } - if ( JandexHelper.getValue( generator, "uniqueConstraints", AnnotationInstance[].class ).length > 0 ) { - LOG.ignoringTableGeneratorConstraints( name ); - } - metadata.addIdGenerator( new IdGenerator( name, strategy, parameterMap ) ); - LOG.tracef( "Add table generator with name: %s", name ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java deleted file mode 100644 index a7bbd8e1fc45..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/QueryBinder.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import javax.persistence.NamedNativeQueries; -import javax.persistence.NamedNativeQuery; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; - -import org.hibernate.AnnotationException; -import org.hibernate.CacheMode; -import org.hibernate.FlushMode; -import org.hibernate.LockMode; -import org.hibernate.annotations.QueryHints; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; -import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.logging.Logger; - -/** - * Binds {@link NamedQuery}, {@link NamedQueries}, {@link NamedNativeQuery}, {@link NamedNativeQueries}, - * {@link org.hibernate.annotations.NamedQuery}, {@link org.hibernate.annotations.NamedQueries}, - * {@link org.hibernate.annotations.NamedNativeQuery}, and {@link org.hibernate.annotations.NamedNativeQueries}. - * - * @author Hardy Ferentschik - */ -public class QueryBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - QueryBinder.class.getName() - ); - - private QueryBinder() { - } - - /** - * Binds all {@link NamedQuery}, {@link NamedQueries}, {@link NamedNativeQuery}, {@link NamedNativeQueries}, - * {@link org.hibernate.annotations.NamedQuery}, {@link org.hibernate.annotations.NamedQueries}, - * {@link org.hibernate.annotations.NamedNativeQuery}, and {@link org.hibernate.annotations.NamedNativeQueries} - * annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_NATIVE_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( JPADotNames.NAMED_NATIVE_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedQuery( bindingContext.getMetadataImplementor(), query ); - } - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); - for ( AnnotationInstance query : annotations ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERIES ); - for ( AnnotationInstance queries : annotations ) { - for ( AnnotationInstance query : JandexHelper.getValue( queries, "value", AnnotationInstance[].class ) ) { - bindNamedNativeQuery( bindingContext.getMetadataImplementor(), query ); - } - } - } - - /** - * Binds {@link javax.persistence.NamedQuery} as well as {@link org.hibernate.annotations.NamedQuery}. - * - * @param metadata the current metadata - * @param annotation the named query annotation - */ - private static void bindNamedQuery(MetadataImplementor metadata, AnnotationInstance annotation) { - String name = JandexHelper.getValue( annotation, "name", String.class ); - if ( StringHelper.isEmpty( name ) ) { - throw new AnnotationException( "A named query must have a name when used in class or package level" ); - } - - String query = JandexHelper.getValue( annotation, "query", String.class ); - - AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class ); - - String cacheRegion = getString( hints, QueryHints.CACHE_REGION ); - if ( StringHelper.isEmpty( cacheRegion ) ) { - cacheRegion = null; - } - - Integer timeout = getTimeout( hints, query ); - if ( timeout != null && timeout < 0 ) { - timeout = null; - } - - Integer fetchSize = getInteger( hints, QueryHints.FETCH_SIZE, name ); - if ( fetchSize != null && fetchSize < 0 ) { - fetchSize = null; - } - - String comment = getString( hints, QueryHints.COMMENT ); - if ( StringHelper.isEmpty( comment ) ) { - comment = null; - } - - metadata.addNamedQuery( - new NamedQueryDefinitionBuilder().setName( name ).setQuery( query ).setCacheable( - getBoolean( - hints, - QueryHints.CACHEABLE, - name - ) - ).setCacheRegion( cacheRegion ).setTimeout( timeout ).setFetchSize( fetchSize ).setFlushMode( - getFlushMode( hints, QueryHints.FLUSH_MODE, name ) - ).setCacheMode( getCacheMode( hints, QueryHints.CACHE_MODE, name ) ).setReadOnly( - getBoolean( - hints, - QueryHints.READ_ONLY, - name - ) - ).setComment( comment ).setParameterTypes( null ).createNamedQueryDefinition() - ); - LOG.debugf( "Binding named query: %s => %s", name, query ); - } - - private static void bindNamedNativeQuery(MetadataImplementor metadata, AnnotationInstance annotation) { - String name = JandexHelper.getValue( annotation, "name", String.class ); - if ( StringHelper.isEmpty( name ) ) { - throw new AnnotationException( "A named native query must have a name when used in class or package level" ); - } - - String query = JandexHelper.getValue( annotation, "query", String.class ); - - String resultSetMapping = JandexHelper.getValue( annotation, "resultSetMapping", String.class ); - - AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class ); - - boolean cacheable = getBoolean( hints, "org.hibernate.cacheable", name ); - String cacheRegion = getString( hints, QueryHints.CACHE_REGION ); - if ( StringHelper.isEmpty( cacheRegion ) ) { - cacheRegion = null; - } - - Integer timeout = getTimeout( hints, query ); - if ( timeout != null && timeout < 0 ) { - timeout = null; - } - - Integer fetchSize = getInteger( hints, QueryHints.FETCH_SIZE, name ); - if ( fetchSize != null && fetchSize < 0 ) { - fetchSize = null; - } - - FlushMode flushMode = getFlushMode( hints, QueryHints.FLUSH_MODE, name ); - CacheMode cacheMode = getCacheMode( hints, QueryHints.CACHE_MODE, name ); - - boolean readOnly = getBoolean( hints, QueryHints.READ_ONLY, name ); - - String comment = getString( hints, QueryHints.COMMENT ); - if ( StringHelper.isEmpty( comment ) ) { - comment = null; - } - - boolean callable = getBoolean( hints, QueryHints.CALLABLE, name ); - NamedSQLQueryDefinition def; - if ( StringHelper.isNotEmpty( resultSetMapping ) ) { - def = new NamedSQLQueryDefinitionBuilder().setName( name ) - .setQuery( query ) - .setResultSetRef( - resultSetMapping - ) - .setQuerySpaces( null ) - .setCacheable( cacheable ) - .setCacheRegion( cacheRegion ) - .setTimeout( timeout ) - .setFetchSize( fetchSize ) - .setFlushMode( flushMode ) - .setCacheMode( cacheMode ) - .setReadOnly( readOnly ) - .setComment( comment ) - .setParameterTypes( null ) - .setCallable( callable ) - .createNamedQueryDefinition(); - } - else { - AnnotationValue annotationValue = annotation.value( "resultClass" ); - if ( annotationValue == null ) { - throw new NotYetImplementedException( "Pure native scalar queries are not yet supported" ); - } - NativeSQLQueryRootReturn queryRoots[] = new NativeSQLQueryRootReturn[] { - new NativeSQLQueryRootReturn( - "alias1", - annotationValue.asString(), - new HashMap(), - LockMode.READ - ) - }; - def = new NamedSQLQueryDefinitionBuilder().setName( name ) - .setQuery( query ) - .setQueryReturns( queryRoots ) - .setQuerySpaces( null ) - .setCacheable( cacheable ) - .setCacheRegion( cacheRegion ) - .setTimeout( timeout ) - .setFetchSize( fetchSize ) - .setFlushMode( flushMode ) - .setCacheMode( cacheMode ) - .setReadOnly( readOnly ) - .setComment( comment ) - .setParameterTypes( null ) - .setCallable( callable ) - .createNamedQueryDefinition(); - } - metadata.addNamedNativeQuery( def ); - LOG.debugf( "Binding named native query: %s => %s", name, query ); - } - - private static boolean getBoolean(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null || val.equalsIgnoreCase( "false" ) ) { - return false; - } - if ( val.equalsIgnoreCase( "true" ) ) { - return true; - } - throw new AnnotationException( "Not a boolean in hint: " + query + ":" + element ); - } - - private static CacheMode getCacheMode(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null ) { - return null; - } - if ( val.equalsIgnoreCase( CacheMode.GET.toString() ) ) { - return CacheMode.GET; - } - if ( val.equalsIgnoreCase( CacheMode.IGNORE.toString() ) ) { - return CacheMode.IGNORE; - } - if ( val.equalsIgnoreCase( CacheMode.NORMAL.toString() ) ) { - return CacheMode.NORMAL; - } - if ( val.equalsIgnoreCase( CacheMode.PUT.toString() ) ) { - return CacheMode.PUT; - } - if ( val.equalsIgnoreCase( CacheMode.REFRESH.toString() ) ) { - return CacheMode.REFRESH; - } - throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + element ); - } - - private static FlushMode getFlushMode(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null ) { - return null; - } - if ( val.equalsIgnoreCase( FlushMode.ALWAYS.toString() ) ) { - return FlushMode.ALWAYS; - } - else if ( val.equalsIgnoreCase( FlushMode.AUTO.toString() ) ) { - return FlushMode.AUTO; - } - else if ( val.equalsIgnoreCase( FlushMode.COMMIT.toString() ) ) { - return FlushMode.COMMIT; - } - else if ( val.equalsIgnoreCase( FlushMode.NEVER.toString() ) ) { - return FlushMode.MANUAL; - } - else if ( val.equalsIgnoreCase( FlushMode.MANUAL.toString() ) ) { - return FlushMode.MANUAL; - } - else { - throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + element ); - } - } - - private static Integer getInteger(AnnotationInstance[] hints, String element, String query) { - String val = getString( hints, element ); - if ( val == null ) { - return null; - } - try { - return Integer.decode( val ); - } - catch ( NumberFormatException nfe ) { - throw new AnnotationException( "Not an integer in hint: " + query + ":" + element, nfe ); - } - } - - private static String getString(AnnotationInstance[] hints, String element) { - for ( AnnotationInstance hint : hints ) { - if ( element.equals( JandexHelper.getValue( hint, "name", String.class ) ) ) { - return JandexHelper.getValue( hint, "value", String.class ); - } - } - return null; - } - - private static Integer getTimeout(AnnotationInstance[] hints, String query) { - Integer timeout = getInteger( hints, QueryHints.TIMEOUT_JPA, query ); - if ( timeout == null ) { - return getInteger( hints, QueryHints.TIMEOUT_HIBERNATE, query ); // timeout is already in seconds - } - return ( ( timeout + 500 ) / 1000 ); // convert milliseconds to seconds (rounded) - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java deleted file mode 100644 index 72c0511e32bb..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TableBinder.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.List; - -import org.hibernate.AnnotationException; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.ObjectName; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds table related information. This binder is called after the entities are bound. - * - * @author Hardy Ferentschik - */ -public class TableBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - TableBinder.class.getName() - ); - - private TableBinder() { - } - - /** - * Binds {@link org.hibernate.annotations.Tables} and {@link org.hibernate.annotations.Table} annotations to the supplied - * metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TABLE ); - for ( AnnotationInstance tableAnnotation : annotations ) { - bind( bindingContext.getMetadataImplementor(), tableAnnotation ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TABLES ); - for ( AnnotationInstance tables : annotations ) { - for ( AnnotationInstance table : JandexHelper.getValue( tables, "value", AnnotationInstance[].class ) ) { - bind( bindingContext.getMetadataImplementor(), table ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance tableAnnotation) { - String tableName = JandexHelper.getValue( tableAnnotation, "appliesTo", String.class ); - ObjectName objectName = new ObjectName( tableName ); - Schema schema = metadata.getDatabase().getSchema( objectName.getSchema(), objectName.getCatalog() ); - Table table = schema.locateTable( objectName.getName() ); - if ( table != null ) { - bindHibernateTableAnnotation( table, tableAnnotation ); - } - } - - private static void bindHibernateTableAnnotation(Table table, AnnotationInstance tableAnnotation) { - for ( AnnotationInstance indexAnnotation : JandexHelper.getValue( - tableAnnotation, - "indexes", - AnnotationInstance[].class - ) ) { - bindIndexAnnotation( table, indexAnnotation ); - } - String comment = JandexHelper.getValue( tableAnnotation, "comment", String.class ); - if ( StringHelper.isNotEmpty( comment ) ) { - table.addComment( comment.trim() ); - } - } - - private static void bindIndexAnnotation(Table table, AnnotationInstance indexAnnotation) { - String indexName = JandexHelper.getValue( indexAnnotation, "appliesTo", String.class ); - String[] columnNames = JandexHelper.getValue( indexAnnotation, "columnNames", String[].class ); - if ( columnNames == null ) { - LOG.noColumnsSpecifiedForIndex( indexName, table.toLoggableString() ); - return; - } - org.hibernate.metamodel.relational.Index index = table.getOrCreateIndex( indexName ); - for ( String columnName : columnNames ) { - Column column = findColumn( table, columnName ); - if ( column == null ) { - throw new AnnotationException( "@Index references a unknown column: " + columnName ); - } - index.addColumn( column ); - } - } - - private static Column findColumn(Table table, String columnName) { - Column column = null; - for ( SimpleValue value : table.values() ) { - if ( value instanceof Column && ( (Column) value ).getColumnName().getName().equals( columnName ) ) { - column = (Column) value; - break; - } - } - return column; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java deleted file mode 100644 index 9031f036eaff..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/TypeDefBinder.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AnnotationException; -import org.hibernate.annotations.TypeDefs; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.logging.Logger; - -/** - * Binds {@link org.hibernate.annotations.TypeDef} and {@link TypeDefs}. - * - * @author Hardy Ferentschik - */ -public class TypeDefBinder { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - TypeDefBinder.class.getName() - ); - - /** - * Binds all {@link org.hibernate.annotations.TypeDef} and {@link TypeDefs} annotations to the supplied metadata. - * - * @param bindingContext the context for annotation binding - */ - public static void bind(AnnotationBindingContext bindingContext) { - List annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TYPE_DEF ); - for ( AnnotationInstance typeDef : annotations ) { - bind( bindingContext.getMetadataImplementor(), typeDef ); - } - - annotations = bindingContext.getIndex().getAnnotations( HibernateDotNames.TYPE_DEFS ); - for ( AnnotationInstance typeDefs : annotations ) { - AnnotationInstance[] typeDefAnnotations = JandexHelper.getValue( - typeDefs, - "value", - AnnotationInstance[].class - ); - for ( AnnotationInstance typeDef : typeDefAnnotations ) { - bind( bindingContext.getMetadataImplementor(), typeDef ); - } - } - } - - private static void bind(MetadataImplementor metadata, AnnotationInstance typeDefAnnotation) { - String name = JandexHelper.getValue( typeDefAnnotation, "name", String.class ); - String defaultForType = JandexHelper.getValue( typeDefAnnotation, "defaultForType", String.class ); - String typeClass = JandexHelper.getValue( typeDefAnnotation, "typeClass", String.class ); - - boolean noName = StringHelper.isEmpty( name ); - boolean noDefaultForType = defaultForType == null || defaultForType.equals( void.class.getName() ); - - if ( noName && noDefaultForType ) { - throw new AnnotationException( - "Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass " - + typeClass - ); - } - - Map parameterMaps = new HashMap(); - AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( - typeDefAnnotation, - "parameters", - AnnotationInstance[].class - ); - for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { - parameterMaps.put( - JandexHelper.getValue( parameterAnnotation, "name", String.class ), - JandexHelper.getValue( parameterAnnotation, "value", String.class ) - ); - } - - if ( !noName ) { - bind( name, typeClass, parameterMaps, metadata ); - } - if ( !noDefaultForType ) { - bind( defaultForType, typeClass, parameterMaps, metadata ); - } - } - - private static void bind( - String name, - String typeClass, - Map prms, - MetadataImplementor metadata) { - LOG.debugf( "Binding type definition: %s", name ); - metadata.addTypeDefinition( new TypeDef( name, typeClass, prms ) ); - } - - private TypeDefBinder() { - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameTargetAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameTargetAnnotationFilter.java deleted file mode 100644 index 4df19be708b3..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameTargetAnnotationFilter.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.filter; - -import java.util.Iterator; -import java.util.List; - -import org.hibernate.metamodel.source.annotations.xml.mocker.MockHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.DotName; - -/** - * @author Strong Liu - */ -class NameTargetAnnotationFilter extends AbstractAnnotationFilter { - @Override - protected void process(DotName annName, AnnotationInstance annotationInstance, List indexedAnnotationInstanceList) { - AnnotationTarget target = annotationInstance.target(); - - for ( Iterator iter = indexedAnnotationInstanceList.iterator(); iter.hasNext(); ) { - AnnotationInstance ann = iter.next(); - if ( MockHelper.targetEquals( target, ann.target() ) ) { - iter.remove(); - } - } - } - - public static NameTargetAnnotationFilter INSTANCE = new NameTargetAnnotationFilter(); - - @Override - protected DotName[] targetAnnotation() { - return new DotName[] { - LOB, - ID, - BASIC, - GENERATED_VALUE, - VERSION, - TRANSIENT, - ACCESS, - POST_LOAD, - POST_PERSIST, - POST_REMOVE, - POST_UPDATE, - PRE_PERSIST, - PRE_REMOVE, - PRE_UPDATE, - EMBEDDED_ID, - EMBEDDED, - MANY_TO_ONE, - MANY_TO_MANY, - ONE_TO_ONE, - ONE_TO_MANY, - ELEMENT_COLLECTION, - COLLECTION_TABLE, - COLUMN, - ENUMERATED, - JOIN_TABLE, - TEMPORAL, - ORDER_BY, - ORDER_COLUMN, - JOIN_COLUMN, - JOIN_COLUMNS, - MAPS_ID, - MAP_KEY_TEMPORAL, - MAP_KEY, - MAP_KEY_CLASS, - MAP_KEY_COLUMN, - MAP_KEY_ENUMERATED - }; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractAttributesBuilder.java deleted file mode 100644 index 425b308b01dc..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractAttributesBuilder.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - -import org.jboss.jandex.ClassInfo; - -/** - * Abstract Parser to handle {@link org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes JaxbAttributes} - * and {@link org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddableAttributes JaxbEmbeddableAttributes}. - * - * It would be really helpful if these two classes can implement an interface with those abstract methods in this class. - * - * @author Strong Liu - */ -abstract class AbstractAttributesBuilder { - - private ClassInfo classInfo; - private EntityMappingsMocker.Default defaults; - private IndexBuilder indexBuilder; - - AbstractAttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults) { - this.indexBuilder = indexBuilder; - this.classInfo = classInfo; - this.defaults = defaults; - } - - final void parser() { - for ( JaxbId id : getId() ) { - new IdMocker( indexBuilder, classInfo, defaults, id ).process(); - } - for ( JaxbTransient transientObj : getTransient() ) { - new TransientMocker( indexBuilder, classInfo, defaults, transientObj ).process(); - } - for ( JaxbVersion version : getVersion() ) { - new VersionMocker( indexBuilder, classInfo, defaults, version ).process(); - } - - for ( JaxbBasic basic : getBasic() ) { - new BasicMocker( indexBuilder, classInfo, defaults, basic ).process(); - } - for ( JaxbElementCollection elementCollection : getElementCollection() ) { - new ElementCollectionMocker( - indexBuilder, classInfo, defaults, elementCollection - ).process(); - } - for ( JaxbEmbedded embedded : getEmbedded() ) { - new EmbeddedMocker( indexBuilder, classInfo, defaults, embedded ).process(); - } - for ( JaxbManyToMany manyToMany : getManyToMany() ) { - new ManyToManyMocker( indexBuilder, classInfo, defaults, manyToMany ).process(); - } - - for ( JaxbManyToOne manyToOne : getManyToOne() ) { - new ManyToOneMocker( indexBuilder, classInfo, defaults, manyToOne ).process(); - } - for ( JaxbOneToMany oneToMany : getOneToMany() ) { - new OneToManyMocker( - indexBuilder, classInfo, defaults, oneToMany - ).process(); - } - for ( JaxbOneToOne oneToOne : getOneToOne() ) { - new OneToOneMocker( indexBuilder, classInfo, defaults, oneToOne ).process(); - } - if ( getEmbeddedId() != null ) { - new EmbeddedIdMocker( - indexBuilder, classInfo, defaults, getEmbeddedId() - ).process(); - } - } - - abstract List getId(); - - abstract List getTransient(); - - abstract List getVersion(); - - abstract List getBasic(); - - abstract List getElementCollection(); - - abstract List getEmbedded(); - - abstract List getManyToMany(); - - abstract List getManyToOne(); - - abstract List getOneToMany(); - - abstract List getOneToOne(); - - abstract JaxbEmbeddedId getEmbeddedId(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractEntityObjectMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractEntityObjectMocker.java deleted file mode 100644 index 8248e3e6a55a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractEntityObjectMocker.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.AssertionFailure; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; - -/** - * @author Strong Liu - */ -abstract class AbstractEntityObjectMocker extends AnnotationMocker { - private ListenerMocker listenerParser; - protected AbstractAttributesBuilder attributesBuilder; - protected ClassInfo classInfo; - - AbstractEntityObjectMocker(IndexBuilder indexBuilder, EntityMappingsMocker.Default defaults) { - super( indexBuilder, defaults ); - } - - private boolean isPreProcessCalled = false; - - /** - * Pre-process Entity Objects to find the default {@link javax.persistence.Access} for later attributes processing. - */ - final void preProcess() { - applyDefaults(); - classInfo = indexBuilder.createClassInfo( getClassName() ); - DotName classDotName = classInfo.name(); - if ( isMetadataComplete() ) { - indexBuilder.metadataComplete( classDotName ); - } - parserAccessType( getAccessType(), getTarget() ); - isPreProcessCalled = true; - } - - final void process() { - if ( !isPreProcessCalled ) { - throw new AssertionFailure( "preProcess should be called before process" ); - } - if ( getAccessType() == null ) { - JaxbAccessType accessType = AccessHelper.getEntityAccess( getTargetName(), indexBuilder ); - if ( accessType == null ) { - accessType = getDefaults().getAccess(); - } - parserAccessType( accessType, getTarget() ); - } - processExtra(); - if ( isExcludeDefaultListeners() ) { - create( EXCLUDE_DEFAULT_LISTENERS ); - } - if ( isExcludeSuperclassListeners() ) { - create( EXCLUDE_SUPERCLASS_LISTENERS ); - } - parserIdClass( getIdClass() ); - - if ( getAttributes() != null ) { - getAttributesBuilder().parser(); - - } - if ( getEntityListeners() != null ) { - getListenerParser().parser( getEntityListeners() ); - } - getListenerParser().parser( getPrePersist() ); - getListenerParser().parser( getPreRemove() ); - getListenerParser().parser( getPreUpdate() ); - getListenerParser().parser( getPostPersist() ); - getListenerParser().parser( getPostUpdate() ); - getListenerParser().parser( getPostRemove() ); - getListenerParser().parser( getPostLoad() ); - - indexBuilder.finishEntityObject( getTargetName(), getDefaults() ); - } - - - abstract protected void processExtra(); - - /** - * give a chance to the sub-classes to override defaults configuration - */ - abstract protected void applyDefaults(); - - abstract protected boolean isMetadataComplete(); - - abstract protected boolean isExcludeDefaultListeners(); - - abstract protected boolean isExcludeSuperclassListeners(); - - abstract protected JaxbIdClass getIdClass(); - - abstract protected JaxbEntityListeners getEntityListeners(); - - abstract protected JaxbAccessType getAccessType(); - - abstract protected String getClassName(); - - abstract protected JaxbPrePersist getPrePersist(); - - abstract protected JaxbPreRemove getPreRemove(); - - abstract protected JaxbPreUpdate getPreUpdate(); - - abstract protected JaxbPostPersist getPostPersist(); - - abstract protected JaxbPostUpdate getPostUpdate(); - - abstract protected JaxbPostRemove getPostRemove(); - - abstract protected JaxbPostLoad getPostLoad(); - - abstract protected JaxbAttributes getAttributes(); - - protected ListenerMocker getListenerParser() { - if ( listenerParser == null ) { - listenerParser = new ListenerMocker( indexBuilder, classInfo ); - } - return listenerParser; - } - - protected AbstractAttributesBuilder getAttributesBuilder() { - if ( attributesBuilder == null ) { - attributesBuilder = new AttributesBuilder( - indexBuilder, classInfo, getAccessType(), getDefaults(), getAttributes() - ); - } - return attributesBuilder; - } - - protected AnnotationInstance parserIdClass(JaxbIdClass idClass) { - if ( idClass == null ) { - return null; - } - String className = MockHelper.buildSafeClassName( idClass.getClazz(), getDefaults().getPackageName() ); - return create( - ID_CLASS, MockHelper.classValueArray( - "value", className, indexBuilder.getServiceRegistry() - ) - ); - } - - - @Override - protected DotName getTargetName() { - return classInfo.name(); - } - - @Override - protected AnnotationTarget getTarget() { - return classInfo; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMocker.java deleted file mode 100644 index d5cfb09c4f2f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMocker.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbUniqueConstraint; -import org.hibernate.metamodel.source.annotations.JPADotNames; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; - -/** - * Base class for the mock jandex annotations created from orm.xml. - * - * @author Strong Liu - */ -abstract class AbstractMocker implements JPADotNames { - final protected IndexBuilder indexBuilder; - - AbstractMocker(IndexBuilder indexBuilder) { - this.indexBuilder = indexBuilder; - } - - - abstract protected AnnotationInstance push(AnnotationInstance annotationInstance); - - - protected AnnotationInstance create(DotName name, AnnotationTarget target) { - return create( name, target, MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY ); - } - - - protected AnnotationInstance create(DotName name, AnnotationTarget target, List annotationValueList) { - return create( name, target, MockHelper.toArray( annotationValueList ) ); - } - - protected AnnotationInstance create(DotName name, AnnotationTarget target, AnnotationValue[] annotationValues) { - AnnotationInstance annotationInstance = MockHelper.create( name, target, annotationValues ); - push( annotationInstance ); - return annotationInstance; - - } - - - protected AnnotationInstance parserAccessType(JaxbAccessType accessType, AnnotationTarget target) { - if ( accessType == null ) { - return null; - } - return create( ACCESS, target, MockHelper.enumValueArray( "value", ACCESS_TYPE, accessType ) ); - } - - protected void nestedUniqueConstraintList(String name, List constraints, List annotationValueList) { - if ( MockHelper.isNotEmpty( constraints ) ) { - AnnotationValue[] values = new AnnotationValue[constraints.size()]; - for ( int i = 0; i < constraints.size(); i++ ) { - AnnotationInstance annotationInstance = parserUniqueConstraint( constraints.get( i ), null ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - } - - } - - //@UniqueConstraint - protected AnnotationInstance parserUniqueConstraint(JaxbUniqueConstraint uniqueConstraint, AnnotationTarget target) { - if ( uniqueConstraint == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", uniqueConstraint.getName(), annotationValueList ); - MockHelper.stringArrayValue( "columnNames", uniqueConstraint.getColumnName(), annotationValueList ); - return - create( UNIQUE_CONSTRAINT, target, - annotationValueList ); - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AccessHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AccessHelper.java deleted file mode 100644 index 1ba239c29685..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AccessHelper.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.MappingException; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.MethodInfo; -import org.jboss.logging.Logger; - -/** - * @author Strong Liu - */ -class AccessHelper implements JPADotNames { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - AccessHelper.class.getName() - ); - - static JaxbAccessType getAccessFromDefault(IndexBuilder indexBuilder) { - AnnotationInstance annotationInstance = JandexHelper.getSingleAnnotation( - indexBuilder.getAnnotations(), - PseudoJpaDotNames.DEFAULT_ACCESS - ); - if ( annotationInstance == null ) { - return null; - } - else { - return JandexHelper.getEnumValue( annotationInstance, "value", JaxbAccessType.class ); - } - - } - - static JaxbAccessType getAccessFromIdPosition(DotName className, IndexBuilder indexBuilder) { - Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); - Map> ormAnnotations = indexBuilder.getClassInfoAnnotationsMap( className ); - JaxbAccessType accessType = getAccessFromIdPosition( ormAnnotations ); - if ( accessType == null ) { - accessType = getAccessFromIdPosition( indexedAnnotations ); - } - if ( accessType == null ) { - ClassInfo parent = indexBuilder.getClassInfo( className ); - if ( parent == null ) { - parent = indexBuilder.getIndexedClassInfo( className ); - } - if ( parent != null ) { - DotName parentClassName = parent.superName(); - accessType = getAccessFromIdPosition( parentClassName, indexBuilder ); - } - - } - - return accessType; - } - - private static JaxbAccessType getAccessFromIdPosition(Map> annotations) { - if ( annotations == null || annotations.isEmpty() || !( annotations.containsKey( ID ) ) ) { - return null; - } - List idAnnotationInstances = annotations.get( ID ); - if ( MockHelper.isNotEmpty( idAnnotationInstances ) ) { - return processIdAnnotations( idAnnotationInstances ); - } - return null; - } - - private static JaxbAccessType processIdAnnotations(List idAnnotations) { - JaxbAccessType accessType = null; - for ( AnnotationInstance annotation : idAnnotations ) { - AnnotationTarget tmpTarget = annotation.target(); - if ( tmpTarget == null ) { - throw new AssertionFailure( "@Id has no AnnotationTarget, this is mostly a internal error." ); - } - if ( accessType == null ) { - accessType = annotationTargetToAccessType( tmpTarget ); - } - else { - if ( !accessType.equals( annotationTargetToAccessType( tmpTarget ) ) ) { - throw new MappingException( "Inconsistent placement of @Id annotation within hierarchy " ); - } - } - } - return accessType; - } - - static JaxbAccessType annotationTargetToAccessType(AnnotationTarget target) { - return ( target instanceof MethodInfo ) ? JaxbAccessType.PROPERTY : JaxbAccessType.FIELD; - } - - static JaxbAccessType getEntityAccess(DotName className, IndexBuilder indexBuilder) { - Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); - Map> ormAnnotations = indexBuilder.getClassInfoAnnotationsMap( className ); - JaxbAccessType accessType = getAccess( ormAnnotations ); - if ( accessType == null ) { - accessType = getAccess( indexedAnnotations ); - } - if ( accessType == null ) { - ClassInfo parent = indexBuilder.getClassInfo( className ); - if ( parent == null ) { - parent = indexBuilder.getIndexedClassInfo( className ); - } - if ( parent != null ) { - DotName parentClassName = parent.superName(); - accessType = getEntityAccess( parentClassName, indexBuilder ); - } - } - return accessType; - - } - - private static JaxbAccessType getAccess(Map> annotations) { - if ( annotations == null || annotations.isEmpty() || !isEntityObject( annotations ) ) { - return null; - } - List accessAnnotationInstances = annotations.get( JPADotNames.ACCESS ); - if ( MockHelper.isNotEmpty( accessAnnotationInstances ) ) { - for ( AnnotationInstance annotationInstance : accessAnnotationInstances ) { - if ( annotationInstance.target() != null && annotationInstance.target() instanceof ClassInfo ) { - return JandexHelper.getEnumValue( - annotationInstance, - "value", - JaxbAccessType.class - ); - } - } - } - return null; - } - - private static boolean isEntityObject(Map> annotations) { - return annotations.containsKey( ENTITY ) || annotations.containsKey( MAPPED_SUPERCLASS ) || annotations - .containsKey( EMBEDDABLE ); - } - - /** - * Get {@link javax.persistence.AccessType } from {@link javax.persistence.Access @Access} on the attribute of the given class - */ - static JaxbAccessType getAccessFromAttributeAnnotation(DotName className, String attributeName, IndexBuilder indexBuilder) { - Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); - if ( indexedAnnotations != null && indexedAnnotations.containsKey( ACCESS ) ) { - List annotationInstances = indexedAnnotations.get( ACCESS ); - if ( MockHelper.isNotEmpty( annotationInstances ) ) { - for ( AnnotationInstance annotationInstance : annotationInstances ) { - AnnotationTarget indexedPropertyTarget = annotationInstance.target(); - if ( indexedPropertyTarget == null ) { - continue; - } - if ( JandexHelper.getPropertyName( indexedPropertyTarget ).equals( attributeName ) ) { - JaxbAccessType accessType = JandexHelper.getEnumValue( - annotationInstance, - "value", - JaxbAccessType.class - ); - /** - * here we ignore @Access(FIELD) on property (getter) and @Access(PROPERTY) on field - */ - JaxbAccessType targetAccessType = annotationTargetToAccessType( indexedPropertyTarget ); - if ( accessType.equals( targetAccessType ) ) { - return targetAccessType; - } - else { - LOG.warn( - String.format( - "%s.%s has @Access on %s, but it tries to assign the access type to %s, this is not allowed by JPA spec, and will be ignored.", - className, - attributeName, - targetAccessType, - accessType - ) - ); - } - } - } - } - } - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AnnotationMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AnnotationMocker.java deleted file mode 100644 index 08f9ba63ea9d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AnnotationMocker.java +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.AssertionFailure; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAssociationOverride; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributeOverride; -import org.hibernate.internal.jaxb.mapping.orm.JaxbCollectionTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEnumType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbJoinColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbJoinTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbLob; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOrderColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrimaryKeyJoinColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTemporalType; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; - -/** - * @author Strong Liu - */ -abstract class AnnotationMocker extends AbstractMocker { - private EntityMappingsMocker.Default defaults; - - AnnotationMocker(IndexBuilder indexBuilder, EntityMappingsMocker.Default defaults) { - super( indexBuilder ); - this.defaults = defaults; - } - - abstract void process(); - - protected EntityMappingsMocker.Default getDefaults() { - return defaults; - } - - protected boolean isDefaultCascadePersist() { - return defaults.isCascadePersist()!=null && defaults.isCascadePersist(); - } - - //@JoinTable - protected AnnotationInstance parserJoinTable(JaxbJoinTable joinTable, AnnotationTarget target) { - if ( joinTable == null ) { - return null; - } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.JoinTableSchemaAware( joinTable ), - getDefaults() - ); - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", joinTable.getName(), annotationValueList ); - MockHelper.stringValue( "catalog", joinTable.getCatalog(), annotationValueList ); - MockHelper.stringValue( "schema", joinTable.getSchema(), annotationValueList ); - nestedJoinColumnList( "joinColumns", joinTable.getJoinColumn(), annotationValueList ); - nestedJoinColumnList( - "inverseJoinColumns", joinTable.getInverseJoinColumn(), annotationValueList - ); - nestedUniqueConstraintList( - "uniqueConstraints", joinTable.getUniqueConstraint(), annotationValueList - ); - return create( JOIN_TABLE, target, annotationValueList ); - } - - //@AssociationOverride - private AnnotationInstance parserAssociationOverride(JaxbAssociationOverride associationOverride, AnnotationTarget target) { - if ( associationOverride == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", associationOverride.getName(), annotationValueList ); - if ( associationOverride instanceof JaxbAssociationOverrideProxy ) { - JaxbAssociationOverrideProxy proxy = (JaxbAssociationOverrideProxy) associationOverride; - MockHelper.addToCollectionIfNotNull( annotationValueList, proxy.getJoinColumnsAnnotationValue() ); - MockHelper.addToCollectionIfNotNull( annotationValueList, proxy.getJoinTableAnnotationValue() ); - } - else { - nestedJoinColumnList( - "joinColumns", associationOverride.getJoinColumn(), annotationValueList - ); - MockHelper.nestedAnnotationValue( - "joinTable", parserJoinTable( associationOverride.getJoinTable(), null ), annotationValueList - ); - } - return create( ASSOCIATION_OVERRIDE, target, annotationValueList ); - } - - private AnnotationValue[] nestedJoinColumnList(String name, List columns, List annotationValueList) { - if ( MockHelper.isNotEmpty( columns ) ) { - AnnotationValue[] values = new AnnotationValue[columns.size()]; - for ( int i = 0; i < columns.size(); i++ ) { - AnnotationInstance annotationInstance = parserJoinColumn( columns.get( i ), null ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - return values; - } - return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; - } - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - //@Column - protected AnnotationInstance parserColumn(JaxbColumn column, AnnotationTarget target) { - if ( column == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", column.getName(), annotationValueList ); - MockHelper.stringValue( "columnDefinition", column.getColumnDefinition(), annotationValueList ); - MockHelper.stringValue( "table", column.getTable(), annotationValueList ); - MockHelper.booleanValue( "unique", column.isUnique(), annotationValueList ); - MockHelper.booleanValue( "nullable", column.isNullable(), annotationValueList ); - MockHelper.booleanValue( "insertable", column.isInsertable(), annotationValueList ); - MockHelper.booleanValue( "updatable", column.isUpdatable(), annotationValueList ); - MockHelper.integerValue( "length", column.getLength(), annotationValueList ); - MockHelper.integerValue( "precision", column.getPrecision(), annotationValueList ); - MockHelper.integerValue( "scale", column.getScale(), annotationValueList ); - return create( COLUMN, target, annotationValueList ); - } - - //@AttributeOverride - private AnnotationInstance parserAttributeOverride(JaxbAttributeOverride attributeOverride, AnnotationTarget target) { - if ( attributeOverride == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", attributeOverride.getName(), annotationValueList ); - if ( attributeOverride instanceof JaxbAttributeOverrideProxy ) { - JaxbAttributeOverrideProxy proxy = (JaxbAttributeOverrideProxy) attributeOverride; - MockHelper.addToCollectionIfNotNull( annotationValueList, proxy.getColumnAnnotationValue() ); - } - else { - MockHelper.nestedAnnotationValue( - "column", parserColumn( attributeOverride.getColumn(), null ), annotationValueList - ); - } - return - create( - ATTRIBUTE_OVERRIDE, target, annotationValueList - - ); - } - - - protected AnnotationInstance parserOrderColumn(JaxbOrderColumn orderColumn, AnnotationTarget target) { - if ( orderColumn == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", orderColumn.getName(), annotationValueList ); - MockHelper.stringValue( "columnDefinition", orderColumn.getColumnDefinition(), annotationValueList ); - MockHelper.booleanValue( "nullable", orderColumn.isNullable(), annotationValueList ); - MockHelper.booleanValue( "insertable", orderColumn.isInsertable(), annotationValueList ); - MockHelper.booleanValue( "updatable", orderColumn.isUpdatable(), annotationValueList ); - return create( ORDER_COLUMN, target, annotationValueList ); - } - - //@JoinColumn - protected AnnotationInstance parserJoinColumn(JaxbJoinColumn column, AnnotationTarget target) { - if ( column == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", column.getName(), annotationValueList ); - MockHelper.stringValue( "columnDefinition", column.getColumnDefinition(), annotationValueList ); - MockHelper.stringValue( "table", column.getTable(), annotationValueList ); - MockHelper.stringValue( - "referencedColumnName", column.getReferencedColumnName(), annotationValueList - ); - MockHelper.booleanValue( "unique", column.isUnique(), annotationValueList ); - MockHelper.booleanValue( "nullable", column.isNullable(), annotationValueList ); - MockHelper.booleanValue( "insertable", column.isInsertable(), annotationValueList ); - MockHelper.booleanValue( "updatable", column.isUpdatable(), annotationValueList ); - return create( JOIN_COLUMN, target, annotationValueList ); - } - - protected AnnotationInstance parserLob(JaxbLob lob, AnnotationTarget target) { - if ( lob == null ) { - return null; - } - return create( LOB, target ); - } - - protected AnnotationInstance parserTemporalType(JaxbTemporalType temporalType, AnnotationTarget target) { - if ( temporalType == null ) { - return null; - } - return create( TEMPORAL, target, MockHelper.enumValueArray( "value", TEMPORAL_TYPE, temporalType ) ); - } - - protected AnnotationInstance parserEnumType(JaxbEnumType enumerated, AnnotationTarget target) { - if ( enumerated == null ) { - return null; - } - return create( ENUMERATED, target, MockHelper.enumValueArray( "value", ENUM_TYPE, enumerated ) ); - } - - - protected AnnotationInstance parserPrimaryKeyJoinColumn(JaxbPrimaryKeyJoinColumn primaryKeyJoinColumn, AnnotationTarget target) { - if ( primaryKeyJoinColumn == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", primaryKeyJoinColumn.getName(), annotationValueList ); - MockHelper.stringValue( - "referencedColumnName", primaryKeyJoinColumn.getReferencedColumnName(), annotationValueList - ); - MockHelper.stringValue( - "columnDefinition", primaryKeyJoinColumn.getColumnDefinition(), annotationValueList - ); - return - create( - PRIMARY_KEY_JOIN_COLUMN, target, annotationValueList - - ); - } - - protected AnnotationInstance parserPrimaryKeyJoinColumnList(List primaryKeyJoinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { - if ( primaryKeyJoinColumnList.size() == 1 ) { - return parserPrimaryKeyJoinColumn( primaryKeyJoinColumnList.get( 0 ), target ); - } - else { - return create( - PRIMARY_KEY_JOIN_COLUMNS, - target, - nestedPrimaryKeyJoinColumnList( "value", primaryKeyJoinColumnList, null ) - ); - } - } - - return null; - - } - - protected AnnotationValue[] nestedPrimaryKeyJoinColumnList(String name, List constraints, List annotationValueList) { - if ( MockHelper.isNotEmpty( constraints ) ) { - AnnotationValue[] values = new AnnotationValue[constraints.size()]; - for ( int i = 0; i < constraints.size(); i++ ) { - AnnotationInstance annotationInstance = parserPrimaryKeyJoinColumn( constraints.get( i ), null ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - return values; - } - return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; - - } - - protected void getAnnotationInstanceByTarget(DotName annName, AnnotationTarget target, Operation operation) { - Map> annotatedMap = indexBuilder.getIndexedAnnotations( getTargetName() ); - if ( !annotatedMap.containsKey( annName ) ) { - return; - } - List annotationInstanceList = annotatedMap.get( annName ); - if ( MockHelper.isNotEmpty( annotationInstanceList ) ) { - for ( AnnotationInstance annotationInstance : annotationInstanceList ) { - AnnotationTarget annotationTarget = annotationInstance.target(); - if ( MockHelper.targetEquals( target, annotationTarget ) ) { - if ( operation.process( annotationInstance ) ) { - return; - } - } - } - } - } - - - protected AnnotationInstance parserAttributeOverrides(List attributeOverrides, AnnotationTarget target) { - if ( target == null ) { - throw new AssertionFailure( "target can not be null" ); - } - if ( attributeOverrides == null || attributeOverrides.isEmpty() ) { - return null; - } - Set names = new HashSet(); - for ( JaxbAttributeOverride attributeOverride : attributeOverrides ) { - names.add( attributeOverride.getName() ); - } - Operation operation = new AttributeOverrideOperation( names, attributeOverrides ); - getAnnotationInstanceByTarget( - ATTRIBUTE_OVERRIDES, target, new ContainerOperation( operation ) - ); - getAnnotationInstanceByTarget( - ATTRIBUTE_OVERRIDE, target, operation - ); - if ( attributeOverrides.size() == 1 ) { - return parserAttributeOverride( attributeOverrides.get( 0 ), target ); - } - else { - AnnotationValue[] values = new AnnotationValue[attributeOverrides.size()]; - for ( int i = 0; i < values.length; i++ ) { - values[i] = MockHelper.nestedAnnotationValue( - "", parserAttributeOverride( attributeOverrides.get( i ), null ) - ); - } - return create( - ATTRIBUTE_OVERRIDES, - target, - new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } - ); - } - } - - protected AnnotationInstance parserAssociationOverrides(List associationOverrides, AnnotationTarget target) { - if ( target == null ) { - throw new AssertionFailure( "target can not be null" ); - } - if ( associationOverrides == null || associationOverrides.isEmpty() ) { - return null; - } - - Set names = new HashSet(); - for ( JaxbAssociationOverride associationOverride : associationOverrides ) { - names.add( associationOverride.getName() ); - } - Operation operation = new AssociationOverrideOperation( names, associationOverrides ); - getAnnotationInstanceByTarget( - ASSOCIATION_OVERRIDES, target, new ContainerOperation( operation ) - ); - getAnnotationInstanceByTarget( - ASSOCIATION_OVERRIDE, target, operation - ); - - - if ( associationOverrides.size() == 1 ) { - return parserAssociationOverride( associationOverrides.get( 0 ), target ); - } - else { - AnnotationValue[] values = new AnnotationValue[associationOverrides.size()]; - for ( int i = 0; i < values.length; i++ ) { - values[i] = MockHelper.nestedAnnotationValue( - "", parserAssociationOverride( associationOverrides.get( i ), null ) - ); - } - return create( - ASSOCIATION_OVERRIDES, - target, - new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } - ); - } - - } - - protected AnnotationInstance parserCollectionTable(JaxbCollectionTable collectionTable, AnnotationTarget target) { - if ( collectionTable == null ) { - return null; - } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.CollectionTableSchemaAware( collectionTable ), - getDefaults() - ); - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", collectionTable.getName(), annotationValueList ); - MockHelper.stringValue( "catalog", collectionTable.getCatalog(), annotationValueList ); - MockHelper.stringValue( "schema", collectionTable.getSchema(), annotationValueList ); - nestedJoinColumnList( "joinColumns", collectionTable.getJoinColumn(), annotationValueList ); - nestedUniqueConstraintList( "uniqueConstraints", collectionTable.getUniqueConstraint(), annotationValueList ); - return create( COLLECTION_TABLE, target, annotationValueList ); - } - - - protected AnnotationInstance parserJoinColumnList(List joinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( joinColumnList ) ) { - if ( joinColumnList.size() == 1 ) { - return parserJoinColumn( joinColumnList.get( 0 ), target ); - } - else { - AnnotationValue[] values = nestedJoinColumnList( "value", joinColumnList, null ); - return create( - JOIN_COLUMNS, - target, - values - ); - } - } - return null; - - } - - protected interface Operation { - boolean process(AnnotationInstance annotationInstance); - } - - class ContainerOperation implements Operation { - private Operation child; - - ContainerOperation(Operation child) { - this.child = child; - } - - @Override - public boolean process(AnnotationInstance annotationInstance) { - AnnotationValue value = annotationInstance.value(); - AnnotationInstance[] indexedAttributeOverridesValues = value.asNestedArray(); - for ( AnnotationInstance ai : indexedAttributeOverridesValues ) { - child.process( ai ); - } - return true; - } - } - - class AttributeOverrideOperation implements Operation { - private Set names; - private List attributeOverrides; - - AttributeOverrideOperation(Set names, List attributeOverrides) { - this.names = names; - this.attributeOverrides = attributeOverrides; - } - - @Override - public boolean process(AnnotationInstance annotationInstance) { - String name = annotationInstance.value( "name" ).asString(); - if ( !names.contains( name ) ) { - JaxbAttributeOverrideProxy attributeOverride = new JaxbAttributeOverrideProxy(); - attributeOverride.setName( name ); - attributeOverride.setColumnAnnotationValue( annotationInstance.value( "column" ) ); - attributeOverrides.add( attributeOverride ); - } - return false; - } - } - - - class AssociationOverrideOperation implements Operation { - private Set names; - private List associationOverrides; - - AssociationOverrideOperation(Set names, List associationOverrides) { - this.names = names; - this.associationOverrides = associationOverrides; - } - - @Override - public boolean process(AnnotationInstance annotationInstance) { - String name = annotationInstance.value( "name" ).asString(); - if ( !names.contains( name ) ) { - JaxbAssociationOverrideProxy associationOverride = new JaxbAssociationOverrideProxy(); - associationOverride.setName( name ); - associationOverride.setJoinColumnsAnnotationValue( annotationInstance.value( "joinColumns" ) ); - associationOverride.setJoinTableAnnotationValue( annotationInstance.value( "joinTable" ) ); - associationOverrides.add( associationOverride ); - } - return false; - } - - } - - class JaxbAssociationOverrideProxy extends JaxbAssociationOverride { - private AnnotationValue joinTableAnnotationValue; - private AnnotationValue joinColumnsAnnotationValue; - - AnnotationValue getJoinColumnsAnnotationValue() { - return joinColumnsAnnotationValue; - } - - void setJoinColumnsAnnotationValue(AnnotationValue joinColumnsAnnotationValue) { - this.joinColumnsAnnotationValue = joinColumnsAnnotationValue; - } - - AnnotationValue getJoinTableAnnotationValue() { - return joinTableAnnotationValue; - } - - void setJoinTableAnnotationValue(AnnotationValue joinTableAnnotationValue) { - this.joinTableAnnotationValue = joinTableAnnotationValue; - } - } - - class JaxbAttributeOverrideProxy extends JaxbAttributeOverride { - private AnnotationValue columnAnnotationValue; - - AnnotationValue getColumnAnnotationValue() { - return columnAnnotationValue; - } - - void setColumnAnnotationValue(AnnotationValue columnAnnotationValue) { - this.columnAnnotationValue = columnAnnotationValue; - } - } - - /** - * Create simple AnnotationInstance with empty annotation value. - * AnnotationInstance's target is get from #{getTarget} - * - * @param name annotation name - * - * @return annotationInstance which name is , target is from #{getTarget}, and has no annotation values. - */ - protected AnnotationInstance create(DotName name) { - return create( name, MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY ); - } - - protected AnnotationInstance create(DotName name, AnnotationValue[] annotationValues) { - return create( name, getTarget(), annotationValues ); - - } - - protected AnnotationInstance create(DotName name, List annotationValueList) { - return create( name, getTarget(), annotationValueList ); - } - - /** - * @return DotName as the key for the ClassInfo object this mocker created that being push to. - */ - abstract protected DotName getTargetName(); - - /** - * @return Default Annotation Target for #{create} and #{mocker} methods. - */ - abstract protected AnnotationTarget getTarget(); - - protected AnnotationInstance push(AnnotationInstance annotationInstance) { - if ( annotationInstance != null && annotationInstance.target() != null ) { - indexBuilder.addAnnotationInstance( getTargetName(), annotationInstance ); - } - return annotationInstance; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java deleted file mode 100644 index d695b7ad82c2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/AttributesBuilder.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class AttributesBuilder extends AbstractAttributesBuilder { - private JaxbAttributes attributes; - - AttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, JaxbAccessType accessType, EntityMappingsMocker.Default defaults, JaxbAttributes attributes) { - super( indexBuilder, classInfo, defaults ); - this.attributes = attributes; - } - - @Override - List getBasic() { - return attributes.getBasic(); - } - - @Override - List getId() { - return attributes.getId(); - } - - @Override - List getTransient() { - return attributes.getTransient(); - } - - @Override - List getVersion() { - return attributes.getVersion(); - } - - @Override - List getElementCollection() { - return attributes.getElementCollection(); - } - - @Override - List getEmbedded() { - return attributes.getEmbedded(); - } - - @Override - List getManyToMany() { - return attributes.getManyToMany(); - } - - @Override - List getManyToOne() { - return attributes.getManyToOne(); - } - - @Override - List getOneToMany() { - return attributes.getOneToMany(); - } - - @Override - List getOneToOne() { - return attributes.getOneToOne(); - } - - @Override - JaxbEmbeddedId getEmbeddedId() { - return attributes.getEmbeddedId(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMocker.java deleted file mode 100644 index ff46073ede95..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMocker.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; - -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class BasicMocker extends PropertyMocker { - private JaxbBasic basic; - - BasicMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbBasic basic) { - super( indexBuilder, classInfo, defaults ); - this.basic = basic; - } - - @Override - protected String getFieldName() { - return basic.getName(); - } - - @Override - protected void processExtra() { - List annotationValueList = new ArrayList(); - MockHelper.booleanValue( "optional", basic.isOptional(), annotationValueList ); - MockHelper.enumValue( "fetch", FETCH_TYPE, basic.getFetch(), annotationValueList ); - create( BASIC, annotationValueList ); - parserColumn( basic.getColumn(), getTarget() ); - parserEnumType( basic.getEnumerated(), getTarget() ); - parserLob( basic.getLob(), getTarget() ); - parserTemporalType( basic.getTemporal(), getTarget() ); - - } - - - @Override - protected JaxbAccessType getAccessType() { - return basic.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - basic.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelper.java deleted file mode 100644 index 47eac0c95fb1..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelper.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMappedSuperclass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTable; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.xml.filter.IndexedAnnotationFilter; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; -import org.jboss.logging.Logger; - -/** - * @author Strong Liu - */ -class DefaultConfigurationHelper { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - DefaultConfigurationHelper.class.getName() - ); - static final DefaultConfigurationHelper INSTANCE = new DefaultConfigurationHelper(); - static final DotName[] GLOBAL_ANNOTATIONS = new DotName[] { - JPADotNames.SEQUENCE_GENERATOR, - JPADotNames.TABLE_GENERATOR, - JPADotNames.NAMED_QUERIES, - JPADotNames.NAMED_QUERY, - JPADotNames.NAMED_NATIVE_QUERIES, - JPADotNames.NAMED_NATIVE_QUERY, - JPADotNames.SQL_RESULT_SET_MAPPING, - JPADotNames.SQL_RESULT_SET_MAPPINGS - }; - static final DotName[] SCHEMA_AWARE_ANNOTATIONS = new DotName[] { - JPADotNames.TABLE, - JPADotNames.JOIN_TABLE, - JPADotNames.COLLECTION_TABLE, - JPADotNames.SECONDARY_TABLE, - JPADotNames.SECONDARY_TABLES, - JPADotNames.TABLE_GENERATOR, - JPADotNames.SEQUENCE_GENERATOR - }; - static final DotName[] ASSOCIATION_ANNOTATIONS = new DotName[] { - JPADotNames.ONE_TO_MANY, JPADotNames.ONE_TO_ONE, JPADotNames.MANY_TO_ONE, JPADotNames.MANY_TO_MANY - }; - - private DefaultConfigurationHelper() { - } - - void applyDefaults(SchemaAware schemaAware, EntityMappingsMocker.Default defaults) { - if ( hasSchemaOrCatalogDefined( defaults ) ) { - if ( StringHelper.isEmpty( schemaAware.getSchema() ) ) { - schemaAware.setSchema( defaults.getSchema() ); - } - if ( StringHelper.isEmpty( schemaAware.getCatalog() ) ) { - schemaAware.setCatalog( defaults.getCatalog() ); - } - } - } - - void applyDefaults(Map> annotationsMap, EntityMappingsMocker.Default defaults) { - if ( annotationsMap.isEmpty() || defaults == null ) { - return; - } - if ( hasSchemaOrCatalogDefined( defaults ) ) { - applyDefaultSchemaAndCatalog( annotationsMap, defaults ); - } - if ( defaults.isCascadePersist()!=null && defaults.isCascadePersist() ) { - applyDefaultCascadePersist( annotationsMap ); - } - } - - void applyDefaults(JaxbMappedSuperclass mappedSuperclass, EntityMappingsMocker.Default defaults) { - applyDefaultsToEntityObject( new MappedSuperClassEntityObject( mappedSuperclass ), defaults ); - } - - void applyDefaults(JaxbEmbeddable embeddable, EntityMappingsMocker.Default defaults) { - applyDefaultsToEntityObject( new EmbeddableEntityObject( embeddable ), defaults ); - } - - void applyDefaults(JaxbEntity entity, EntityMappingsMocker.Default defaults) { - mockTableIfNonExist( entity, defaults ); - applyDefaultsToEntityObject( new EntityEntityObject( entity ), defaults ); - } - - private void applyDefaultsToEntityObject(EntityObject entityObject, EntityMappingsMocker.Default defaults) { - if ( defaults == null ) { - return; - } - String className = MockHelper.buildSafeClassName( entityObject.getClazz(), defaults.getPackageName() ); - entityObject.setClazz( className ); - if ( entityObject.isMetadataComplete() == null ) { - entityObject.setMetadataComplete( defaults.isMetadataComplete() ); - } - LOG.debugf( "Adding XML overriding information for %s", className ); - } - - private boolean hasSchemaOrCatalogDefined(EntityMappingsMocker.Default defaults) { - return ( defaults != null ) && ( StringHelper.isNotEmpty( defaults.getSchema() ) || StringHelper.isNotEmpty( - defaults.getCatalog() - ) ); - } - - private void applyDefaultCascadePersist(Map> annotationsMap) { - for ( DotName annName : ASSOCIATION_ANNOTATIONS ) { - if ( annotationsMap.containsKey( annName ) ) { - addCascadePersistIfNotExist( annName, annotationsMap ); - } - } - } - - private void applyDefaultSchemaAndCatalog(Map> annotationsMap, EntityMappingsMocker.Default defaults) { - for ( DotName annName : SCHEMA_AWARE_ANNOTATIONS ) { - mockTableIfNonExist( annotationsMap, annName ); - if ( annotationsMap.containsKey( annName ) ) { - overrideSchemaCatalogByDefault( annName, annotationsMap, defaults ); - } - } - } - - private void mockTableIfNonExist(Map> annotationsMap, DotName annName) { - if ( annName == JPADotNames.TABLE && !annotationsMap.containsKey( JPADotNames.TABLE ) && annotationsMap - .containsKey( JPADotNames.ENTITY ) ) { - //if an entity doesn't have a @Table, we create one here - AnnotationInstance entity = JandexHelper.getSingleAnnotation( annotationsMap, JPADotNames.ENTITY ); - AnnotationInstance table = MockHelper.create( - JPADotNames.TABLE, entity.target(), MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY - ); - List annotationInstanceList = new ArrayList( 1 ); - annotationInstanceList.add( table ); - annotationsMap.put( JPADotNames.TABLE, annotationInstanceList ); - } - } - - private void mockTableIfNonExist(JaxbEntity entity, EntityMappingsMocker.Default defaults) { - if ( hasSchemaOrCatalogDefined( defaults ) ) { - JaxbTable table = entity.getTable(); - if ( table == null ) { - table = new JaxbTable(); - entity.setTable( table ); - } - } - } - - private void addCascadePersistIfNotExist(DotName annName, Map> indexedAnnotationMap) { - List annotationInstanceList = indexedAnnotationMap.get( annName ); - if ( annotationInstanceList == null || annotationInstanceList.isEmpty() ) { - return; - } - List newAnnotationInstanceList = new ArrayList( annotationInstanceList.size() ); - for ( AnnotationInstance annotationInstance : annotationInstanceList ) { - AnnotationValue cascadeValue = annotationInstance.value( "cascade" ); - List newAnnotationValueList = new ArrayList(); - newAnnotationValueList.addAll( annotationInstance.values() ); - if ( cascadeValue == null ) { - AnnotationValue temp = AnnotationValue.createEnumValue( "", JPADotNames.CASCADE_TYPE, "PERSIST" ); - cascadeValue = AnnotationValue.createArrayValue( "cascade", new AnnotationValue[] { temp } ); - } - else { - newAnnotationValueList.remove( cascadeValue ); - String[] cascadeTypes = cascadeValue.asEnumArray(); - boolean hasPersistDefined = false; - for ( String type : cascadeTypes ) { - if ( "PERSIST".equals( type ) ) { - hasPersistDefined = true; - continue; - } - } - if ( hasPersistDefined ) { - newAnnotationInstanceList.add( annotationInstance ); - continue; - } - String[] newCascadeTypes = new String[cascadeTypes.length + 1]; - newCascadeTypes[0] = "PERSIST"; - System.arraycopy( cascadeTypes, 0, newCascadeTypes, 1, cascadeTypes.length ); - AnnotationValue[] cascades = new AnnotationValue[newCascadeTypes.length]; - for ( int i = 0; i < newCascadeTypes.length; i++ ) { - cascades[i] = AnnotationValue.createEnumValue( "", JPADotNames.CASCADE_TYPE, newCascadeTypes[i] ); - } - cascadeValue = AnnotationValue.createArrayValue( "cascade", cascades ); - - } - newAnnotationValueList.add( cascadeValue ); - - AnnotationInstance newAnnotationInstance = MockHelper.create( - annotationInstance.name(), - annotationInstance.target(), - MockHelper.toArray( newAnnotationValueList ) - ); - newAnnotationInstanceList.add( newAnnotationInstance ); - } - indexedAnnotationMap.put( annName, newAnnotationInstanceList ); - } - - //@Table, @CollectionTable, @JoinTable, @SecondaryTable - private void overrideSchemaCatalogByDefault(DotName annName, Map> indexedAnnotationMap, EntityMappingsMocker.Default defaults) { - List annotationInstanceList = indexedAnnotationMap.get( annName ); - if ( annotationInstanceList == null || annotationInstanceList.isEmpty() ) { - return; - } - List newAnnotationInstanceList = new ArrayList( annotationInstanceList.size() ); - for ( AnnotationInstance annotationInstance : annotationInstanceList ) { - if ( annName.equals( IndexedAnnotationFilter.SECONDARY_TABLES ) ) { - AnnotationInstance[] secondaryTableAnnotationInstanceArray = annotationInstance.value().asNestedArray(); - AnnotationValue[] newAnnotationValueArray = new AnnotationValue[secondaryTableAnnotationInstanceArray.length]; - for ( int i = 0; i < secondaryTableAnnotationInstanceArray.length; i++ ) { - newAnnotationValueArray[i] = MockHelper.nestedAnnotationValue( - "", overrideSchemaCatalogByDefault( - secondaryTableAnnotationInstanceArray[i], - defaults - ) - ); - } - AnnotationInstance secondaryTablesAnnotationInstance = MockHelper.create( - annName, - annotationInstance.target(), - new AnnotationValue[] { - AnnotationValue.createArrayValue( "value", newAnnotationValueArray ) - } - ); - newAnnotationInstanceList.add( secondaryTablesAnnotationInstance ); - } - else { - newAnnotationInstanceList.add( overrideSchemaCatalogByDefault( annotationInstance, defaults ) ); - } - } - indexedAnnotationMap.put( annName, newAnnotationInstanceList ); - } - - private AnnotationInstance overrideSchemaCatalogByDefault(AnnotationInstance annotationInstance, EntityMappingsMocker.Default defaults) { - List newAnnotationValueList = new ArrayList(); - newAnnotationValueList.addAll( annotationInstance.values() ); - boolean schemaDefined = false; - boolean catalogDefined = false; - if ( annotationInstance.value( "schema" ) != null ) { - schemaDefined = true; - } - if ( annotationInstance.value( "catalog" ) != null ) { - catalogDefined = true; - } - if ( schemaDefined && catalogDefined ) { - return annotationInstance; - } - if ( !catalogDefined && StringHelper.isNotEmpty( defaults.getCatalog() ) ) { - newAnnotationValueList.add( - AnnotationValue.createStringValue( - "catalog", defaults.getCatalog() - ) - ); - } - if ( !schemaDefined && StringHelper.isNotEmpty( defaults.getSchema() ) ) { - newAnnotationValueList.add( - AnnotationValue.createStringValue( - "schema", defaults.getSchema() - ) - ); - } - return MockHelper.create( - annotationInstance.name(), - annotationInstance.target(), - MockHelper.toArray( newAnnotationValueList ) - ); - } - - private static interface EntityObject { - String getClazz(); - - void setClazz(String className); - - Boolean isMetadataComplete(); - - void setMetadataComplete(Boolean isMetadataComplete); - } - - private static class EntityEntityObject implements EntityObject { - private JaxbEntity entity; - - private EntityEntityObject(JaxbEntity entity) { - this.entity = entity; - } - - @Override - public String getClazz() { - return entity.getClazz(); - } - - @Override - public void setClazz(String className) { - entity.setClazz( className ); - } - - @Override - public Boolean isMetadataComplete() { - return entity.isMetadataComplete(); - } - - @Override - public void setMetadataComplete(Boolean isMetadataComplete) { - entity.setMetadataComplete( isMetadataComplete ); - } - } - - private static class EmbeddableEntityObject implements EntityObject { - private JaxbEmbeddable entity; - - private EmbeddableEntityObject(JaxbEmbeddable entity) { - this.entity = entity; - } - - @Override - public String getClazz() { - return entity.getClazz(); - } - - @Override - public void setClazz(String className) { - entity.setClazz( className ); - } - - @Override - public Boolean isMetadataComplete() { - return entity.isMetadataComplete(); - } - - @Override - public void setMetadataComplete(Boolean isMetadataComplete) { - entity.setMetadataComplete( isMetadataComplete ); - } - } - - private static class MappedSuperClassEntityObject implements EntityObject { - private JaxbMappedSuperclass entity; - - private MappedSuperClassEntityObject(JaxbMappedSuperclass entity) { - this.entity = entity; - } - - @Override - public String getClazz() { - return entity.getClazz(); - } - - @Override - public void setClazz(String className) { - entity.setClazz( className ); - } - - @Override - public Boolean isMetadataComplete() { - return entity.isMetadataComplete(); - } - - @Override - public void setMetadataComplete(Boolean isMetadataComplete) { - entity.setMetadataComplete( isMetadataComplete ); - } - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ElementCollectionMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ElementCollectionMocker.java deleted file mode 100644 index e58cee635fd6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ElementCollectionMocker.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; - -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class ElementCollectionMocker extends PropertyMocker { - private JaxbElementCollection elementCollection; - - ElementCollectionMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbElementCollection elementCollection) { - super( indexBuilder, classInfo, defaults ); - this.elementCollection = elementCollection; - } - - @Override - protected void processExtra() { - List annotationValueList = new ArrayList(); - MockHelper.classValue( - "targetClass", - elementCollection.getTargetClass(), - annotationValueList, - indexBuilder.getServiceRegistry() - ); - MockHelper.enumValue( "fetch", FETCH_TYPE, elementCollection.getFetch(), annotationValueList ); - create( ELEMENT_COLLECTION, annotationValueList ); - parserLob( elementCollection.getLob(), getTarget() ); - parserEnumType( elementCollection.getEnumerated(), getTarget() ); - parserColumn( elementCollection.getColumn(), getTarget() ); - parserTemporalType( elementCollection.getTemporal(), getTarget() ); - parserCollectionTable( elementCollection.getCollectionTable(), getTarget() ); - parserAssociationOverrides( elementCollection.getAssociationOverride(), getTarget() ); - parserAttributeOverrides( elementCollection.getAttributeOverride(), getTarget() ); - if ( elementCollection.getOrderBy() != null ) { - create( ORDER_BY, MockHelper.stringValueArray( "value", elementCollection.getOrderBy() ) ); - } - parserAttributeOverrides( elementCollection.getMapKeyAttributeOverride(), getTarget() ); - parserMapKeyJoinColumnList( elementCollection.getMapKeyJoinColumn(), getTarget() ); - parserMapKey( elementCollection.getMapKey(), getTarget() ); - parserMapKeyColumn( elementCollection.getMapKeyColumn(), getTarget() ); - parserMapKeyClass( elementCollection.getMapKeyClass(), getTarget() ); - parserMapKeyEnumerated( elementCollection.getMapKeyEnumerated(), getTarget() ); - parserMapKeyTemporal( elementCollection.getMapKeyTemporal(), getTarget() ); - } - - @Override - protected String getFieldName() { - return elementCollection.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return elementCollection.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - elementCollection.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java deleted file mode 100644 index c3692bb7d614..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableAttributesBuilder.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.Collections; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbBasic; -import org.hibernate.internal.jaxb.mapping.orm.JaxbElementCollection; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddableAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class EmbeddableAttributesBuilder extends AbstractAttributesBuilder { - private JaxbEmbeddableAttributes attributes; - - EmbeddableAttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, JaxbAccessType accessType, EntityMappingsMocker.Default defaults, JaxbEmbeddableAttributes embeddableAttributes) { - super( indexBuilder, classInfo, defaults ); - this.attributes = embeddableAttributes; - } - - @Override - List getBasic() { - return attributes.getBasic(); - } - - @Override - List getId() { - return Collections.emptyList(); - } - - @Override - List getTransient() { - return attributes.getTransient(); - } - - @Override - List getVersion() { - return Collections.emptyList(); - } - - @Override - List getElementCollection() { - return attributes.getElementCollection(); - } - - @Override - List getEmbedded() { - return attributes.getEmbedded(); - } - - @Override - List getManyToMany() { - return attributes.getManyToMany(); - } - - @Override - List getManyToOne() { - return attributes.getManyToOne(); - } - - @Override - List getOneToMany() { - return attributes.getOneToMany(); - } - - @Override - List getOneToOne() { - return attributes.getOneToOne(); - } - - @Override - JaxbEmbeddedId getEmbeddedId() { - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableMocker.java deleted file mode 100644 index cda89b1c5938..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddableMocker.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; - -import org.jboss.logging.Logger; - -/** - * Mock to {@link javax.persistence.Embeddable @Embeddable} - * - * @author Strong Liu - */ -class EmbeddableMocker extends AbstractEntityObjectMocker { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - EmbeddableMocker.class.getName() - ); - private JaxbEmbeddable embeddable; - - EmbeddableMocker(IndexBuilder indexBuilder, JaxbEmbeddable embeddable, EntityMappingsMocker.Default defaults) { - super( indexBuilder, defaults ); - this.embeddable = embeddable; - } - - @Override - protected AbstractAttributesBuilder getAttributesBuilder() { - if ( attributesBuilder == null ) { - attributesBuilder = new EmbeddableAttributesBuilder( - indexBuilder, classInfo, getAccessType(), getDefaults(), embeddable.getAttributes() - ); - } - return attributesBuilder; - } - - @Override - protected void processExtra() { - create( EMBEDDABLE ); - } - - @Override - protected void applyDefaults() { - DefaultConfigurationHelper.INSTANCE.applyDefaults( embeddable, getDefaults() ); - } - - @Override - protected boolean isMetadataComplete() { - return embeddable.isMetadataComplete() != null && embeddable.isMetadataComplete(); - } - - @Override - protected boolean isExcludeDefaultListeners() { - return false; - } - - @Override - protected boolean isExcludeSuperclassListeners() { - return false; - } - - @Override - protected JaxbIdClass getIdClass() { - return null; - } - - @Override - protected JaxbEntityListeners getEntityListeners() { - return null; - } - - @Override - protected JaxbAccessType getAccessType() { - return embeddable.getAccess(); - } - - @Override - protected String getClassName() { - return embeddable.getClazz(); - } - - @Override - protected JaxbPrePersist getPrePersist() { - return null; - } - - @Override - protected JaxbPreRemove getPreRemove() { - return null; - } - - @Override - protected JaxbPreUpdate getPreUpdate() { - return null; - } - - @Override - protected JaxbPostPersist getPostPersist() { - return null; - } - - @Override - protected JaxbPostUpdate getPostUpdate() { - return null; - } - - @Override - protected JaxbPostRemove getPostRemove() { - return null; - } - - @Override - protected JaxbPostLoad getPostLoad() { - return null; - } - - @Override - protected JaxbAttributes getAttributes() { - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedIdMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedIdMocker.java deleted file mode 100644 index 44f585005bd9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedIdMocker.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddedId; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class EmbeddedIdMocker extends PropertyMocker { - private JaxbEmbeddedId embeddedId; - - EmbeddedIdMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbEmbeddedId embeddedId) { - super( indexBuilder, classInfo, defaults ); - this.embeddedId = embeddedId; - } - - @Override - protected String getFieldName() { - return embeddedId.getName(); - } - - @Override - protected void processExtra() { - create( EMBEDDED_ID ); - } - - @Override - protected JaxbAccessType getAccessType() { - return embeddedId.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - embeddedId.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedMocker.java deleted file mode 100644 index f75a268c417d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EmbeddedMocker.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbedded; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class EmbeddedMocker extends PropertyMocker { - private JaxbEmbedded embedded; - - EmbeddedMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbEmbedded embedded) { - super( indexBuilder, classInfo, defaults ); - this.embedded = embedded; - } - - @Override - protected void processExtra() { - create( EMBEDDED ); - parserAttributeOverrides( embedded.getAttributeOverride(), getTarget() ); - parserAssociationOverrides( embedded.getAssociationOverride(), getTarget() ); - - } - - @Override - protected String getFieldName() { - return embedded.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return embedded.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - embedded.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMappingsMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMappingsMocker.java deleted file mode 100644 index 0f518669cc5c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMappingsMocker.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEmbeddable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMappedSuperclass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPersistenceUnitDefaults; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPersistenceUnitMetadata; -import org.hibernate.service.ServiceRegistry; - -import org.jboss.jandex.Index; -import org.jboss.logging.Logger; - -/** - * Parse all {@link org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings} generated from orm.xml. - * - * @author Strong Liu - */ -public class EntityMappingsMocker { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - EntityMappingsMocker.class.getName() - ); - private final List entityMappingsList; - /** - * Default configuration defined in Persistence Metadata Unit, one or zero per Persistence Unit. - */ - private Default globalDefaults; - private final IndexBuilder indexBuilder; - private final GlobalAnnotations globalAnnotations; - - public EntityMappingsMocker(List entityMappingsList, Index index, ServiceRegistry serviceRegistry) { - this.entityMappingsList = entityMappingsList; - this.indexBuilder = new IndexBuilder( index, serviceRegistry ); - this.globalAnnotations = new GlobalAnnotations(); - } - - /** - * Create new {@link Index} with mocking JPA annotations from {@link org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings} and merge them with existing {@link Index} - * - * @return new {@link Index} - */ - public Index mockNewIndex() { - processPersistenceUnitMetadata( entityMappingsList ); - processEntityMappings( entityMappingsList ); - processGlobalAnnotations(); - return indexBuilder.build( globalDefaults ); - } - - /** - * processing PersistenceUnitMetadata, there should be only one PersistenceUnitMetadata in all mapping xml files. - */ - private void processPersistenceUnitMetadata(List entityMappingsList) { - for ( JaxbEntityMappings entityMappings : entityMappingsList ) { - //we have to iterate entityMappingsList first to find persistence-unit-metadata - JaxbPersistenceUnitMetadata pum = entityMappings.getPersistenceUnitMetadata(); - if ( globalDefaults != null ) { - LOG.duplicateMetadata(); - return; - } - if ( pum == null ) { - continue; - } - globalDefaults = new Default(); - if ( pum.getXmlMappingMetadataComplete() != null ) { - globalDefaults.setMetadataComplete( true ); - indexBuilder.mappingMetadataComplete(); - } - JaxbPersistenceUnitDefaults pud = pum.getPersistenceUnitDefaults(); - if ( pud == null ) { - return; - } - globalDefaults.setSchema( pud.getSchema() ); - globalDefaults.setCatalog( pud.getCatalog() ); - //globalDefaults.setAccess( pud.getAccess() ); - globalDefaults.setCascadePersist( pud.getCascadePersist() != null ); - new PersistenceMetadataMocker( indexBuilder, pud ).process(); - } - } - - - private void processEntityMappings(List entityMappingsList) { - List mockerList = new ArrayList(); - for ( JaxbEntityMappings entityMappings : entityMappingsList ) { - final Default defaults = getEntityMappingsDefaults( entityMappings ); - globalAnnotations.collectGlobalMappings( entityMappings, defaults ); - for ( JaxbMappedSuperclass mappedSuperclass : entityMappings.getMappedSuperclass() ) { - AbstractEntityObjectMocker mocker = - new MappedSuperclassMocker( indexBuilder, mappedSuperclass, defaults ); - mockerList.add( mocker ); - mocker.preProcess(); - } - for ( JaxbEmbeddable embeddable : entityMappings.getEmbeddable() ) { - AbstractEntityObjectMocker mocker = - new EmbeddableMocker( indexBuilder, embeddable, defaults ); - mockerList.add( mocker ); - mocker.preProcess(); - } - for ( JaxbEntity entity : entityMappings.getEntity() ) { - globalAnnotations.collectGlobalMappings( entity, defaults ); - AbstractEntityObjectMocker mocker = - new EntityMocker( indexBuilder, entity, defaults ); - mockerList.add( mocker ); - mocker.preProcess(); - } - } - for ( AbstractEntityObjectMocker mocker : mockerList ) { - mocker.process(); - } - } - - private void processGlobalAnnotations() { - if ( globalAnnotations.hasGlobalConfiguration() ) { - indexBuilder.collectGlobalConfigurationFromIndex( globalAnnotations ); - new GlobalAnnotationMocker( - indexBuilder, globalAnnotations - ).process(); - } - } - - private Default getEntityMappingsDefaults(JaxbEntityMappings entityMappings) { - Default entityMappingDefault = new Default(); - entityMappingDefault.setPackageName( entityMappings.getPackage() ); - entityMappingDefault.setSchema( entityMappings.getSchema() ); - entityMappingDefault.setCatalog( entityMappings.getCatalog() ); - entityMappingDefault.setAccess( entityMappings.getAccess() ); - final Default defaults = new Default(); - defaults.override( globalDefaults ); - defaults.override( entityMappingDefault ); - return defaults; - } - - - public static class Default implements Serializable { - private JaxbAccessType access; - private String packageName; - private String schema; - private String catalog; - private Boolean metadataComplete; - private Boolean cascadePersist; - - public JaxbAccessType getAccess() { - return access; - } - - void setAccess(JaxbAccessType access) { - this.access = access; - } - - public String getCatalog() { - return catalog; - } - - void setCatalog(String catalog) { - this.catalog = catalog; - } - - public String getPackageName() { - return packageName; - } - - void setPackageName(String packageName) { - this.packageName = packageName; - } - - public String getSchema() { - return schema; - } - - void setSchema(String schema) { - this.schema = schema; - } - - public Boolean isMetadataComplete() { - return metadataComplete; - } - - void setMetadataComplete(Boolean metadataComplete) { - this.metadataComplete = metadataComplete; - } - - public Boolean isCascadePersist() { - return cascadePersist; - } - - void setCascadePersist(Boolean cascadePersist) { - this.cascadePersist = cascadePersist; - } - - void override(Default globalDefault) { - if ( globalDefault != null ) { - if ( globalDefault.getAccess() != null ) { - access = globalDefault.getAccess(); - } - if ( globalDefault.getPackageName() != null ) { - packageName = globalDefault.getPackageName(); - } - if ( globalDefault.getSchema() != null ) { - schema = globalDefault.getSchema(); - } - if ( globalDefault.getCatalog() != null ) { - catalog = globalDefault.getCatalog(); - } - if ( globalDefault.isCascadePersist() != null ) { - cascadePersist = globalDefault.isCascadePersist(); - } - if ( globalDefault.isMetadataComplete() != null ) { - metadataComplete = globalDefault.isMetadataComplete(); - } - - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMocker.java deleted file mode 100644 index 8ee892122ee2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityMocker.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import javax.persistence.AccessType; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbDiscriminatorColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbInheritance; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSecondaryTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTable; -import org.hibernate.internal.util.StringHelper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.logging.Logger; - -/** - * Mock to {@link javax.persistence.Entity @Entity} - * - * @author Strong Liu - */ -class EntityMocker extends AbstractEntityObjectMocker { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - EntityMocker.class.getName() - ); - private JaxbEntity entity; - - EntityMocker(IndexBuilder indexBuilder, JaxbEntity entity, EntityMappingsMocker.Default defaults) { - super( indexBuilder, defaults ); - this.entity = entity; - } - - @Override - protected String getClassName() { - return entity.getClazz(); - } - - @Override - protected void processExtra() { - //@Entity - create( ENTITY, MockHelper.stringValueArray( "name", entity.getName() ) ); - - - if ( entity.isCacheable() != null ) { - //@Cacheable - create( - CACHEABLE, - MockHelper.booleanValueArray( "value", entity.isCacheable() ) - - ); - } - if ( StringHelper.isNotEmpty( entity.getDiscriminatorValue() ) ) { - //@DiscriminatorValue - create( - DISCRIMINATOR_VALUE, - MockHelper.stringValueArray( "value", entity.getDiscriminatorValue() ) - - ); - } - //@Table - parserTable( entity.getTable() ); - parserInheritance( entity.getInheritance() ); - parserDiscriminatorColumn( entity.getDiscriminatorColumn() ); - parserAttributeOverrides( entity.getAttributeOverride(), getTarget() ); - parserAssociationOverrides( entity.getAssociationOverride(), getTarget() ); - parserPrimaryKeyJoinColumnList( entity.getPrimaryKeyJoinColumn(), getTarget() ); - parserSecondaryTableList( entity.getSecondaryTable(), getTarget() ); - - } - - //@Table (entity only) - private AnnotationInstance parserTable(JaxbTable table) { - if ( table == null ) { - return null; - } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.TableSchemaAware( table ), - getDefaults() - ); - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", table.getName(), annotationValueList ); - MockHelper.stringValue( "catalog", table.getCatalog(), annotationValueList ); - MockHelper.stringValue( "schema", table.getSchema(), annotationValueList ); - nestedUniqueConstraintList( "uniqueConstraints", table.getUniqueConstraint(), annotationValueList ); - return create( TABLE, annotationValueList ); - } - - protected AccessType getDefaultAccess() { - if ( entity.getAccess() != null ) { - return AccessType.valueOf( entity.getAccess().value() ); - } - - return null; - } - - protected AccessType getAccessFromIndex(DotName className) { - Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); - List accessAnnotationInstances = indexedAnnotations.get( ACCESS ); - if ( MockHelper.isNotEmpty( accessAnnotationInstances ) ) { - for ( AnnotationInstance annotationInstance : accessAnnotationInstances ) { - if ( annotationInstance.target() != null && annotationInstance.target() instanceof ClassInfo ) { - ClassInfo ci = (ClassInfo) ( annotationInstance.target() ); - if ( className.equals( ci.name() ) ) { - //todo does ci need to have @Entity or @MappedSuperClass ?? - return AccessType.valueOf( annotationInstance.value().asEnum() ); - } - } - } - } - return null; - } - - @Override - protected void applyDefaults() { - DefaultConfigurationHelper.INSTANCE.applyDefaults( entity, getDefaults() ); - } - - @Override - protected JaxbPrePersist getPrePersist() { - return entity.getPrePersist(); - } - - @Override - protected JaxbPreRemove getPreRemove() { - return entity.getPreRemove(); - } - - @Override - protected JaxbPreUpdate getPreUpdate() { - return entity.getPreUpdate(); - } - - @Override - protected JaxbPostPersist getPostPersist() { - return entity.getPostPersist(); - } - - @Override - protected JaxbPostUpdate getPostUpdate() { - return entity.getPostUpdate(); - } - - @Override - protected JaxbPostRemove getPostRemove() { - return entity.getPostRemove(); - } - - @Override - protected JaxbPostLoad getPostLoad() { - return entity.getPostLoad(); - } - - @Override - protected JaxbAttributes getAttributes() { - return entity.getAttributes(); - } - - @Override - protected boolean isMetadataComplete() { - return entity.isMetadataComplete() != null && entity.isMetadataComplete(); - } - - @Override - protected boolean isExcludeDefaultListeners() { - return entity.getExcludeDefaultListeners() != null; - } - - @Override - protected boolean isExcludeSuperclassListeners() { - return entity.getExcludeSuperclassListeners() != null; - } - - @Override - protected JaxbIdClass getIdClass() { - return entity.getIdClass(); - } - - @Override - protected JaxbEntityListeners getEntityListeners() { - return entity.getEntityListeners(); - } - - @Override - protected JaxbAccessType getAccessType() { - return entity.getAccess(); - } - - //@Inheritance - protected AnnotationInstance parserInheritance(JaxbInheritance inheritance) { - if ( inheritance == null ) { - return null; - } - return - create( - INHERITANCE, - MockHelper.enumValueArray( "strategy", INHERITANCE_TYPE, inheritance.getStrategy() ) - - ); - } - - //@DiscriminatorColumn - protected AnnotationInstance parserDiscriminatorColumn(JaxbDiscriminatorColumn discriminatorColumn) { - if ( discriminatorColumn == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", discriminatorColumn.getName(), annotationValueList ); - MockHelper.stringValue( - "columnDefinition", discriminatorColumn.getColumnDefinition(), annotationValueList - ); - MockHelper.integerValue( "length", discriminatorColumn.getLength(), annotationValueList ); - MockHelper.enumValue( - "discriminatorType", DISCRIMINATOR_TYPE, discriminatorColumn.getDiscriminatorType(), annotationValueList - ); - return - create( - DISCRIMINATOR_COLUMN, annotationValueList - - ); - - } - - //@SecondaryTable - protected AnnotationInstance parserSecondaryTable(JaxbSecondaryTable secondaryTable, AnnotationTarget target) { - if ( secondaryTable == null ) { - return null; - } - DefaultConfigurationHelper.INSTANCE.applyDefaults( - new SchemaAware.SecondaryTableSchemaAware( secondaryTable ), - getDefaults() - ); - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", secondaryTable.getName(), annotationValueList ); - MockHelper.stringValue( "catalog", secondaryTable.getCatalog(), annotationValueList ); - MockHelper.stringValue( "schema", secondaryTable.getSchema(), annotationValueList ); - nestedPrimaryKeyJoinColumnList( - "pkJoinColumns", secondaryTable.getPrimaryKeyJoinColumn(), annotationValueList - ); - nestedUniqueConstraintList( - "uniqueConstraints", secondaryTable.getUniqueConstraint(), annotationValueList - ); - return - create( - SECONDARY_TABLE, target, annotationValueList - ); - } - - - protected AnnotationInstance parserSecondaryTableList(List primaryKeyJoinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { - if ( primaryKeyJoinColumnList.size() == 1 ) { - return parserSecondaryTable( primaryKeyJoinColumnList.get( 0 ), target ); - } - else { - return create( - SECONDARY_TABLES, - target, - nestedSecondaryTableList( "value", primaryKeyJoinColumnList, null ) - ); - } - } - return null; - - } - - protected AnnotationValue[] nestedSecondaryTableList(String name, List secondaryTableList, List annotationValueList) { - if ( MockHelper.isNotEmpty( secondaryTableList ) ) { - AnnotationValue[] values = new AnnotationValue[secondaryTableList.size()]; - for ( int i = 0; i < secondaryTableList.size(); i++ ) { - AnnotationInstance annotationInstance = parserSecondaryTable( secondaryTableList.get( i ), null ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - return values; - } - return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; - - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotationMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotationMocker.java deleted file mode 100644 index b7ed83fa6872..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotationMocker.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbColumnResult; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityResult; -import org.hibernate.internal.jaxb.mapping.orm.JaxbFieldResult; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedNativeQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbQueryHint; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSequenceGenerator; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSqlResultSetMapping; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTableGenerator; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -/** - * @author Strong Liu - */ -class GlobalAnnotationMocker extends AbstractMocker { - private GlobalAnnotations globalAnnotations; - - GlobalAnnotationMocker(IndexBuilder indexBuilder, GlobalAnnotations globalAnnotations) { - super( indexBuilder ); - this.globalAnnotations = globalAnnotations; - } - - - void process() { - if ( !globalAnnotations.getTableGeneratorMap().isEmpty() ) { - for ( JaxbTableGenerator generator : globalAnnotations.getTableGeneratorMap().values() ) { - parserTableGenerator( generator ); - } - } - if ( !globalAnnotations.getSequenceGeneratorMap().isEmpty() ) { - for ( JaxbSequenceGenerator generator : globalAnnotations.getSequenceGeneratorMap().values() ) { - parserSequenceGenerator( generator ); - } - } - if ( !globalAnnotations.getNamedQueryMap().isEmpty() ) { - Collection namedQueries = globalAnnotations.getNamedQueryMap().values(); - if ( namedQueries.size() > 1 ) { - parserNamedQueries( namedQueries ); - } - else { - parserNamedQuery( namedQueries.iterator().next() ); - } - } - if ( !globalAnnotations.getNamedNativeQueryMap().isEmpty() ) { - Collection namedQueries = globalAnnotations.getNamedNativeQueryMap().values(); - if ( namedQueries.size() > 1 ) { - parserNamedNativeQueries( namedQueries ); - } - else { - parserNamedNativeQuery( namedQueries.iterator().next() ); - } - } - if ( !globalAnnotations.getSqlResultSetMappingMap().isEmpty() ) { - parserSqlResultSetMappings( globalAnnotations.getSqlResultSetMappingMap().values() ); - } - indexBuilder.finishGlobalConfigurationMocking( globalAnnotations ); - } - - private AnnotationInstance parserSqlResultSetMappings(Collection namedQueries) { - AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; - int i = 0; - for ( Iterator iterator = namedQueries.iterator(); iterator.hasNext(); ) { - AnnotationInstance annotationInstance = parserSqlResultSetMapping( iterator.next() ); - values[i++] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - return create( - SQL_RESULT_SET_MAPPINGS, null, - new AnnotationValue[] { AnnotationValue.createArrayValue( "values", values ) } - - ); - } - - - //@SqlResultSetMapping - private AnnotationInstance parserSqlResultSetMapping(JaxbSqlResultSetMapping mapping) { - - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", mapping.getName(), annotationValueList ); - nestedEntityResultList( "entities", mapping.getEntityResult(), annotationValueList ); - nestedColumnResultList( "columns", mapping.getColumnResult(), annotationValueList ); - return - create( - SQL_RESULT_SET_MAPPING, null, annotationValueList - - ); - } - - - //@EntityResult - private AnnotationInstance parserEntityResult(JaxbEntityResult result) { - - List annotationValueList = new ArrayList(); - MockHelper.stringValue( - "discriminatorColumn", result.getDiscriminatorColumn(), annotationValueList - ); - nestedFieldResultList( "fields", result.getFieldResult(), annotationValueList ); - MockHelper.classValue( - "entityClass", result.getEntityClass(), annotationValueList, indexBuilder.getServiceRegistry() - ); - return - create( - ENTITY_RESULT, null, annotationValueList - - ); - } - - private void nestedEntityResultList(String name, List entityResults, List annotationValueList) { - if ( MockHelper.isNotEmpty( entityResults ) ) { - AnnotationValue[] values = new AnnotationValue[entityResults.size()]; - for ( int i = 0; i < entityResults.size(); i++ ) { - AnnotationInstance annotationInstance = parserEntityResult( entityResults.get( i ) ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - } - } - - //@ColumnResult - private AnnotationInstance parserColumnResult(JaxbColumnResult result) { - return create( COLUMN_RESULT, null, MockHelper.stringValueArray( "name", result.getName() ) ); - } - - private void nestedColumnResultList(String name, List columnResults, List annotationValueList) { - if ( MockHelper.isNotEmpty( columnResults ) ) { - AnnotationValue[] values = new AnnotationValue[columnResults.size()]; - for ( int i = 0; i < columnResults.size(); i++ ) { - AnnotationInstance annotationInstance = parserColumnResult( columnResults.get( i ) ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - } - } - - //@FieldResult - private AnnotationInstance parserFieldResult(JaxbFieldResult result) { - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", result.getName(), annotationValueList ); - MockHelper.stringValue( "column", result.getColumn(), annotationValueList ); - return create( FIELD_RESULT, null, annotationValueList ); - } - - - private void nestedFieldResultList(String name, List fieldResultList, List annotationValueList) { - if ( MockHelper.isNotEmpty( fieldResultList ) ) { - AnnotationValue[] values = new AnnotationValue[fieldResultList.size()]; - for ( int i = 0; i < fieldResultList.size(); i++ ) { - AnnotationInstance annotationInstance = parserFieldResult( fieldResultList.get( i ) ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - } - } - - private AnnotationInstance parserNamedNativeQueries(Collection namedQueries) { - AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; - int i = 0; - for ( Iterator iterator = namedQueries.iterator(); iterator.hasNext(); ) { - AnnotationInstance annotationInstance = parserNamedNativeQuery( iterator.next() ); - values[i++] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - return create( - NAMED_NATIVE_QUERIES, null, - new AnnotationValue[] { AnnotationValue.createArrayValue( "values", values ) } - - ); - } - - //@NamedNativeQuery - private AnnotationInstance parserNamedNativeQuery(JaxbNamedNativeQuery namedNativeQuery) { - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", namedNativeQuery.getName(), annotationValueList ); - MockHelper.stringValue( "query", namedNativeQuery.getQuery(), annotationValueList ); - MockHelper.stringValue( - "resultSetMapping", namedNativeQuery.getResultSetMapping(), annotationValueList - ); - MockHelper.classValue( - "resultClass", namedNativeQuery.getResultClass(), annotationValueList, indexBuilder.getServiceRegistry() - ); - nestedQueryHintList( "hints", namedNativeQuery.getHint(), annotationValueList ); - return - create( - NAMED_NATIVE_QUERY, null, annotationValueList - - ); - } - - - private AnnotationInstance parserNamedQueries(Collection namedQueries) { - AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; - int i = 0; - for ( Iterator iterator = namedQueries.iterator(); iterator.hasNext(); ) { - AnnotationInstance annotationInstance = parserNamedQuery( iterator.next() ); - values[i++] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - return create( - NAMED_QUERIES, null, - new AnnotationValue[] { AnnotationValue.createArrayValue( "values", values ) } - - ); - } - - - //@NamedQuery - private AnnotationInstance parserNamedQuery(JaxbNamedQuery namedQuery) { - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", namedQuery.getName(), annotationValueList ); - MockHelper.stringValue( "query", namedQuery.getQuery(), annotationValueList ); - MockHelper.enumValue( "lockMode", LOCK_MODE_TYPE, namedQuery.getLockMode(), annotationValueList ); - nestedQueryHintList( "hints", namedQuery.getHint(), annotationValueList ); - return create( NAMED_QUERY, null, annotationValueList ); - } - - //@QueryHint - private AnnotationInstance parserQueryHint(JaxbQueryHint queryHint) { - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", queryHint.getName(), annotationValueList ); - MockHelper.stringValue( "value", queryHint.getValue(), annotationValueList ); - return create( QUERY_HINT, null, annotationValueList ); - - } - - private void nestedQueryHintList(String name, List constraints, List annotationValueList) { - if ( MockHelper.isNotEmpty( constraints ) ) { - AnnotationValue[] values = new AnnotationValue[constraints.size()]; - for ( int i = 0; i < constraints.size(); i++ ) { - AnnotationInstance annotationInstance = parserQueryHint( constraints.get( i ) ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - } - } - - - //@SequenceGenerator - private AnnotationInstance parserSequenceGenerator(JaxbSequenceGenerator generator) { - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", generator.getName(), annotationValueList ); - MockHelper.stringValue( "catalog", generator.getCatalog(), annotationValueList ); - MockHelper.stringValue( "schema", generator.getSchema(), annotationValueList ); - MockHelper.stringValue( "sequenceName", generator.getSequenceName(), annotationValueList ); - MockHelper.integerValue( "initialValue", generator.getInitialValue(), annotationValueList ); - MockHelper.integerValue( "allocationSize", generator.getAllocationSize(), annotationValueList ); - return - create( - SEQUENCE_GENERATOR, null, annotationValueList - - ); - } - - //@TableGenerator - private AnnotationInstance parserTableGenerator(JaxbTableGenerator generator) { - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", generator.getName(), annotationValueList ); - MockHelper.stringValue( "catalog", generator.getCatalog(), annotationValueList ); - MockHelper.stringValue( "schema", generator.getSchema(), annotationValueList ); - MockHelper.stringValue( "table", generator.getTable(), annotationValueList ); - MockHelper.stringValue( "pkColumnName", generator.getPkColumnName(), annotationValueList ); - MockHelper.stringValue( "valueColumnName", generator.getValueColumnName(), annotationValueList ); - MockHelper.stringValue( "pkColumnValue", generator.getPkColumnValue(), annotationValueList ); - MockHelper.integerValue( "initialValue", generator.getInitialValue(), annotationValueList ); - MockHelper.integerValue( "allocationSize", generator.getAllocationSize(), annotationValueList ); - nestedUniqueConstraintList( "uniqueConstraints", generator.getUniqueConstraint(), annotationValueList ); - return - create( - TABLE_GENERATOR, null, annotationValueList - - ); - } - - @Override - protected AnnotationInstance push(AnnotationInstance annotationInstance) { - if ( annotationInstance != null ) { - return globalAnnotations.push( annotationInstance.name(), annotationInstance ); - } - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotations.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotations.java deleted file mode 100644 index efba9e67e651..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/GlobalAnnotations.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedNativeQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbNamedQuery; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSequenceGenerator; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSqlResultSetMapping; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTableGenerator; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.annotations.JPADotNames; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.DotName; -import org.jboss.logging.Logger; - -/** - * @author Strong Liu - */ -class GlobalAnnotations implements JPADotNames { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - GlobalAnnotations.class.getName() - ); - private Map sequenceGeneratorMap = new HashMap(); - private Map tableGeneratorMap = new HashMap(); - private Map namedQueryMap = new HashMap(); - private Map namedNativeQueryMap = new HashMap(); - private Map sqlResultSetMappingMap = new HashMap(); - private Map> annotationInstanceMap = new HashMap>(); - private List indexedAnnotationInstanceList = new ArrayList(); - //--------------------------- - private Set defaultNamedNativeQueryNames = new HashSet(); - private Set defaultNamedQueryNames = new HashSet(); - private Set defaultNamedGenerators = new HashSet(); - private Set defaultSqlResultSetMappingNames = new HashSet(); - - Map> getAnnotationInstanceMap() { - return annotationInstanceMap; - } - - AnnotationInstance push(DotName name, AnnotationInstance annotationInstance) { - if ( name == null || annotationInstance == null ) { - return null; - } - List list = annotationInstanceMap.get( name ); - if ( list == null ) { - list = new ArrayList(); - annotationInstanceMap.put( name, list ); - } - list.add( annotationInstance ); - return annotationInstance; - } - - - void addIndexedAnnotationInstance(List annotationInstanceList) { - if ( MockHelper.isNotEmpty( annotationInstanceList ) ) { - indexedAnnotationInstanceList.addAll( annotationInstanceList ); - } - } - - /** - * do the orm xmls define global configurations? - */ - boolean hasGlobalConfiguration() { - return !( namedQueryMap.isEmpty() && namedNativeQueryMap.isEmpty() && sequenceGeneratorMap.isEmpty() && tableGeneratorMap - .isEmpty() && sqlResultSetMappingMap.isEmpty() ); - } - - Map getNamedNativeQueryMap() { - return namedNativeQueryMap; - } - - Map getNamedQueryMap() { - return namedQueryMap; - } - - Map getSequenceGeneratorMap() { - return sequenceGeneratorMap; - } - - Map getSqlResultSetMappingMap() { - return sqlResultSetMappingMap; - } - - Map getTableGeneratorMap() { - return tableGeneratorMap; - } - - - public void filterIndexedAnnotations() { - for ( AnnotationInstance annotationInstance : indexedAnnotationInstanceList ) { - pushIfNotExist( annotationInstance ); - } - } - - private void pushIfNotExist(AnnotationInstance annotationInstance) { - DotName annName = annotationInstance.name(); - boolean isNotExist = false; - if ( annName.equals( SQL_RESULT_SET_MAPPINGS ) ) { - AnnotationInstance[] annotationInstances = annotationInstance.value().asNestedArray(); - for ( AnnotationInstance ai : annotationInstances ) { - pushIfNotExist( ai ); - } - } - else { - AnnotationValue value = annotationInstance.value( "name" ); - String name = value.asString(); - isNotExist = ( annName.equals( TABLE_GENERATOR ) && !tableGeneratorMap.containsKey( name ) ) || - ( annName.equals( SEQUENCE_GENERATOR ) && !sequenceGeneratorMap.containsKey( name ) ) || - ( annName.equals( NAMED_QUERY ) && !namedQueryMap.containsKey( name ) ) || - ( annName.equals( NAMED_NATIVE_QUERY ) && !namedNativeQueryMap.containsKey( name ) ) || - ( annName.equals( SQL_RESULT_SET_MAPPING ) && !sqlResultSetMappingMap.containsKey( name ) ); - } - if ( isNotExist ) { - push( annName, annotationInstance ); - } - } - - void collectGlobalMappings(JaxbEntityMappings entityMappings, EntityMappingsMocker.Default defaults) { - for ( JaxbSequenceGenerator generator : entityMappings.getSequenceGenerator() ) { - put( generator, defaults ); - defaultNamedGenerators.add( generator.getName() ); - } - for ( JaxbTableGenerator generator : entityMappings.getTableGenerator() ) { - put( generator, defaults ); - defaultNamedGenerators.add( generator.getName() ); - } - for ( JaxbNamedQuery namedQuery : entityMappings.getNamedQuery() ) { - put( namedQuery ); - defaultNamedQueryNames.add( namedQuery.getName() ); - } - for ( JaxbNamedNativeQuery namedNativeQuery : entityMappings.getNamedNativeQuery() ) { - put( namedNativeQuery ); - defaultNamedNativeQueryNames.add( namedNativeQuery.getName() ); - } - for ( JaxbSqlResultSetMapping sqlResultSetMapping : entityMappings.getSqlResultSetMapping() ) { - put( sqlResultSetMapping ); - defaultSqlResultSetMappingNames.add( sqlResultSetMapping.getName() ); - } - } - - void collectGlobalMappings(JaxbEntity entity, EntityMappingsMocker.Default defaults) { - for ( JaxbNamedQuery namedQuery : entity.getNamedQuery() ) { - if ( !defaultNamedQueryNames.contains( namedQuery.getName() ) ) { - put( namedQuery ); - } - else { - LOG.warn( "Named Query [" + namedQuery.getName() + "] duplicated." ); - } - } - for ( JaxbNamedNativeQuery namedNativeQuery : entity.getNamedNativeQuery() ) { - if ( !defaultNamedNativeQueryNames.contains( namedNativeQuery.getName() ) ) { - put( namedNativeQuery ); - } - else { - LOG.warn( "Named native Query [" + namedNativeQuery.getName() + "] duplicated." ); - } - } - for ( JaxbSqlResultSetMapping sqlResultSetMapping : entity.getSqlResultSetMapping() ) { - if ( !defaultSqlResultSetMappingNames.contains( sqlResultSetMapping.getName() ) ) { - put( sqlResultSetMapping ); - } - } - JaxbSequenceGenerator sequenceGenerator = entity.getSequenceGenerator(); - if ( sequenceGenerator != null ) { - if ( !defaultNamedGenerators.contains( sequenceGenerator.getName() ) ) { - put( sequenceGenerator, defaults ); - } - } - JaxbTableGenerator tableGenerator = entity.getTableGenerator(); - if ( tableGenerator != null ) { - if ( !defaultNamedGenerators.contains( tableGenerator.getName() ) ) { - put( tableGenerator, defaults ); - } - } - JaxbAttributes attributes = entity.getAttributes(); - if ( attributes != null ) { - for ( JaxbId id : attributes.getId() ) { - sequenceGenerator = id.getSequenceGenerator(); - if ( sequenceGenerator != null ) { - put( sequenceGenerator, defaults ); - } - tableGenerator = id.getTableGenerator(); - if ( tableGenerator != null ) { - put( tableGenerator, defaults ); - } - } - } - } - - /** - * Override SequenceGenerator using info definded in EntityMappings/Persistence-Metadata-Unit - */ - private static JaxbSequenceGenerator overrideGenerator(JaxbSequenceGenerator generator, EntityMappingsMocker.Default defaults) { - if ( StringHelper.isEmpty( generator.getSchema() ) && defaults != null ) { - generator.setSchema( defaults.getSchema() ); - } - if ( StringHelper.isEmpty( generator.getCatalog() ) && defaults != null ) { - generator.setCatalog( defaults.getCatalog() ); - } - return generator; - } - - /** - * Override TableGenerator using info definded in EntityMappings/Persistence-Metadata-Unit - */ - private static JaxbTableGenerator overrideGenerator(JaxbTableGenerator generator, EntityMappingsMocker.Default defaults) { - if ( StringHelper.isEmpty( generator.getSchema() ) && defaults != null ) { - generator.setSchema( defaults.getSchema() ); - } - if ( StringHelper.isEmpty( generator.getCatalog() ) && defaults != null ) { - generator.setCatalog( defaults.getCatalog() ); - } - return generator; - } - - private void put(JaxbNamedNativeQuery query) { - if ( query != null ) { - checkQueryName( query.getName() ); - namedNativeQueryMap.put( query.getName(), query ); - } - } - - private void checkQueryName(String name) { - if ( namedQueryMap.containsKey( name ) || namedNativeQueryMap.containsKey( name ) ) { - throw new MappingException( "Duplicated query mapping " + name, null ); - } - } - - private void put(JaxbNamedQuery query) { - if ( query != null ) { - checkQueryName( query.getName() ); - namedQueryMap.put( query.getName(), query ); - } - } - - private void put(JaxbSequenceGenerator generator, EntityMappingsMocker.Default defaults) { - if ( generator != null ) { - Object old = sequenceGeneratorMap.put( generator.getName(), overrideGenerator( generator, defaults ) ); - if ( old != null ) { - LOG.duplicateGeneratorName( generator.getName() ); - } - } - } - - private void put(JaxbTableGenerator generator, EntityMappingsMocker.Default defaults) { - if ( generator != null ) { - Object old = tableGeneratorMap.put( generator.getName(), overrideGenerator( generator, defaults ) ); - if ( old != null ) { - LOG.duplicateGeneratorName( generator.getName() ); - } - } - } - - private void put(JaxbSqlResultSetMapping mapping) { - if ( mapping != null ) { - Object old = sqlResultSetMappingMap.put( mapping.getName(), mapping ); - if ( old != null ) { - throw new MappingException( "Duplicated SQL result set mapping " + mapping.getName(), null ); - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IdMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IdMocker.java deleted file mode 100644 index 150b8fa01137..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IdMocker.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbGeneratedValue; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class IdMocker extends PropertyMocker { - private JaxbId id; - - IdMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbId id) { - super( indexBuilder, classInfo, defaults ); - this.id = id; - } - - @Override - protected void processExtra() { - create( ID ); - parserColumn( id.getColumn(), getTarget() ); - parserGeneratedValue( id.getGeneratedValue(), getTarget() ); - parserTemporalType( id.getTemporal(), getTarget() ); - } - - private AnnotationInstance parserGeneratedValue(JaxbGeneratedValue generatedValue, AnnotationTarget target) { - if ( generatedValue == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "generator", generatedValue.getGenerator(), annotationValueList ); - MockHelper.enumValue( - "strategy", GENERATION_TYPE, generatedValue.getStrategy(), annotationValueList - ); - - return create( GENERATED_VALUE, target, annotationValueList ); - } - - @Override - protected String getFieldName() { - return id.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return id.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - id.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ListenerMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ListenerMocker.java deleted file mode 100644 index 58f946667a88..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ListenerMocker.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.MappingException; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListener; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * {@link javax.persistence.EntityListeners @EntityListeners} mocker - * - * @author Strong Liu - */ -class ListenerMocker extends AbstractMocker { - private final ClassInfo classInfo; - - ListenerMocker(IndexBuilder indexBuilder, ClassInfo classInfo) { - super( indexBuilder ); - this.classInfo = classInfo; - } - - AnnotationInstance parser(JaxbEntityListeners entityListeners) { - if ( entityListeners.getEntityListener().isEmpty() ) { - throw new MappingException( "No child element of found under ." ); - } - List annotationValueList = new ArrayList( 1 ); - List clazzNameList = new ArrayList( entityListeners.getEntityListener().size() ); - for ( JaxbEntityListener listener : entityListeners.getEntityListener() ) { - MockHelper.addToCollectionIfNotNull( clazzNameList, listener.getClazz() ); - parserEntityListener( listener ); - } - MockHelper.classArrayValue( "value", clazzNameList, annotationValueList, indexBuilder.getServiceRegistry() ); - return create( ENTITY_LISTENERS, classInfo, annotationValueList ); - } - - private void parserEntityListener(JaxbEntityListener listener) { - String clazz = listener.getClazz(); - ClassInfo tempClassInfo = indexBuilder.createClassInfo( clazz ); - ListenerMocker mocker = createListenerMocker( indexBuilder, tempClassInfo ); - mocker.parser( listener.getPostLoad() ); - mocker.parser( listener.getPostPersist() ); - mocker.parser( listener.getPostRemove() ); - mocker.parser( listener.getPostUpdate() ); - mocker.parser( listener.getPrePersist() ); - mocker.parser( listener.getPreRemove() ); - mocker.parser( listener.getPreUpdate() ); - indexBuilder.finishEntityObject( tempClassInfo.name(), null ); - } - - protected ListenerMocker createListenerMocker(IndexBuilder indexBuilder, ClassInfo classInfo) { - return new ListenerMocker( indexBuilder, classInfo ); - } - - //@PrePersist - AnnotationInstance parser(JaxbPrePersist callback) { - if ( callback == null ) { - return null; - } - return create( PRE_PERSIST, getListenerTarget( callback.getMethodName() ) ); - } - - //@PreRemove - AnnotationInstance parser(JaxbPreRemove callback) { - if ( callback == null ) { - return null; - } - return create( PRE_REMOVE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PreUpdate - AnnotationInstance parser(JaxbPreUpdate callback) { - if ( callback == null ) { - return null; - } - return create( PRE_UPDATE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostPersist - AnnotationInstance parser(JaxbPostPersist callback) { - if ( callback == null ) { - return null; - } - return create( POST_PERSIST, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostUpdate - AnnotationInstance parser(JaxbPostUpdate callback) { - if ( callback == null ) { - return null; - } - return create( POST_UPDATE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostRemove - AnnotationInstance parser(JaxbPostRemove callback) { - if ( callback == null ) { - return null; - } - return create( POST_REMOVE, getListenerTarget( callback.getMethodName() ) ); - } - - //@PostLoad - AnnotationInstance parser(JaxbPostLoad callback) { - if ( callback == null ) { - return null; - } - return create( POST_LOAD, getListenerTarget( callback.getMethodName() ) ); - } - - private AnnotationTarget getListenerTarget(String methodName) { - return MockHelper.getTarget( - indexBuilder.getServiceRegistry(), classInfo, methodName, MockHelper.TargetType.METHOD - ); - } - - @Override - protected AnnotationInstance push(AnnotationInstance annotationInstance) { - if ( annotationInstance != null && annotationInstance.target() != null ) { - indexBuilder.addAnnotationInstance( classInfo.name(), annotationInstance ); - } - return annotationInstance; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToManyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToManyMocker.java deleted file mode 100644 index 985892209a27..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToManyMocker.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToMany; - -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class ManyToManyMocker extends PropertyMocker { - private JaxbManyToMany manyToMany; - - ManyToManyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbManyToMany manyToMany) { - super( indexBuilder, classInfo, defaults ); - this.manyToMany = manyToMany; - } - - @Override - protected String getFieldName() { - return manyToMany.getName(); - } - - - @Override - protected void processExtra() { - List annotationValueList = new ArrayList(); - MockHelper.classValue( - "targetEntity", manyToMany.getTargetEntity(), annotationValueList, indexBuilder.getServiceRegistry() - ); - MockHelper.enumValue( "fetch", FETCH_TYPE, manyToMany.getFetch(), annotationValueList ); - MockHelper.stringValue( "mappedBy", manyToMany.getMappedBy(), annotationValueList ); - MockHelper.cascadeValue( "cascade", manyToMany.getCascade(), isDefaultCascadePersist(), annotationValueList ); - create( MANY_TO_MANY, annotationValueList ); - parserMapKeyClass( manyToMany.getMapKeyClass(), getTarget() ); - parserMapKeyTemporal( manyToMany.getMapKeyTemporal(), getTarget() ); - parserMapKeyEnumerated( manyToMany.getMapKeyEnumerated(), getTarget() ); - parserMapKey( manyToMany.getMapKey(), getTarget() ); - parserAttributeOverrides( manyToMany.getMapKeyAttributeOverride(), getTarget() ); - parserMapKeyJoinColumnList( manyToMany.getMapKeyJoinColumn(), getTarget() ); - parserOrderColumn( manyToMany.getOrderColumn(), getTarget() ); - parserJoinTable( manyToMany.getJoinTable(), getTarget() ); - if ( manyToMany.getOrderBy() != null ) { - create( ORDER_BY, MockHelper.stringValueArray( "value", manyToMany.getOrderBy() ) ); - } - } - - @Override - protected JaxbAccessType getAccessType() { - return manyToMany.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - manyToMany.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MappedSuperclassMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MappedSuperclassMocker.java deleted file mode 100644 index 018a1b53c0f2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MappedSuperclassMocker.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityListeners; -import org.hibernate.internal.jaxb.mapping.orm.JaxbIdClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMappedSuperclass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostLoad; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostPersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPostUpdate; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPrePersist; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreRemove; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPreUpdate; - -import org.jboss.logging.Logger; - -/** - * Mock to {@link javax.persistence.MappedSuperclass @MappedSuperClass} - * - * @author Strong Liu - */ -class MappedSuperclassMocker extends AbstractEntityObjectMocker { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - MappedSuperclassMocker.class.getName() - ); - private JaxbMappedSuperclass mappedSuperclass; - - MappedSuperclassMocker(IndexBuilder indexBuilder, JaxbMappedSuperclass mappedSuperclass, EntityMappingsMocker.Default defaults) { - super( indexBuilder, defaults ); - this.mappedSuperclass = mappedSuperclass; - } - - @Override - protected void applyDefaults() { - DefaultConfigurationHelper.INSTANCE.applyDefaults( mappedSuperclass, getDefaults() ); - } - - @Override - protected void processExtra() { - create( MAPPED_SUPERCLASS ); - } - - @Override - protected JaxbAttributes getAttributes() { - return mappedSuperclass.getAttributes(); - } - - @Override - protected JaxbAccessType getAccessType() { - return mappedSuperclass.getAccess(); - } - - @Override - protected boolean isMetadataComplete() { - return mappedSuperclass.isMetadataComplete() != null && mappedSuperclass.isMetadataComplete(); - } - - @Override - protected boolean isExcludeDefaultListeners() { - return mappedSuperclass.getExcludeDefaultListeners() != null; - } - - @Override - protected boolean isExcludeSuperclassListeners() { - return mappedSuperclass.getExcludeSuperclassListeners() != null; - } - - @Override - protected JaxbIdClass getIdClass() { - return mappedSuperclass.getIdClass(); - } - - @Override - protected JaxbEntityListeners getEntityListeners() { - return mappedSuperclass.getEntityListeners(); - } - - protected String getClassName() { - return mappedSuperclass.getClazz(); - } - - @Override - protected JaxbPrePersist getPrePersist() { - return mappedSuperclass.getPrePersist(); - } - - @Override - protected JaxbPreRemove getPreRemove() { - return mappedSuperclass.getPreRemove(); - } - - @Override - protected JaxbPreUpdate getPreUpdate() { - return mappedSuperclass.getPreUpdate(); - } - - @Override - protected JaxbPostPersist getPostPersist() { - return mappedSuperclass.getPostPersist(); - } - - @Override - protected JaxbPostUpdate getPostUpdate() { - return mappedSuperclass.getPostUpdate(); - } - - @Override - protected JaxbPostRemove getPostRemove() { - return mappedSuperclass.getPostRemove(); - } - - @Override - protected JaxbPostLoad getPostLoad() { - return mappedSuperclass.getPostLoad(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToManyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToManyMocker.java deleted file mode 100644 index ee957d0d5633..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToManyMocker.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToMany; - -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class OneToManyMocker extends PropertyMocker { - private JaxbOneToMany oneToMany; - - OneToManyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbOneToMany oneToMany) { - super( indexBuilder, classInfo, defaults ); - this.oneToMany = oneToMany; - } - - @Override - protected String getFieldName() { - return oneToMany.getName(); - } - - @Override - protected void processExtra() { - List annotationValueList = new ArrayList(); - MockHelper.classValue( - "targetEntity", oneToMany.getTargetEntity(), annotationValueList, indexBuilder.getServiceRegistry() - ); - MockHelper.enumValue( "fetch", FETCH_TYPE, oneToMany.getFetch(), annotationValueList ); - MockHelper.stringValue( "mappedBy", oneToMany.getMappedBy(), annotationValueList ); - MockHelper.booleanValue( "orphanRemoval", oneToMany.isOrphanRemoval(), annotationValueList ); - MockHelper.cascadeValue( "cascade", oneToMany.getCascade(), isDefaultCascadePersist(), annotationValueList ); - create( ONE_TO_MANY, getTarget(), annotationValueList ); - parserAttributeOverrides( oneToMany.getMapKeyAttributeOverride(), getTarget() ); - parserMapKeyJoinColumnList( oneToMany.getMapKeyJoinColumn(), getTarget() ); - parserMapKey( oneToMany.getMapKey(), getTarget() ); - parserMapKeyColumn( oneToMany.getMapKeyColumn(), getTarget() ); - parserMapKeyClass( oneToMany.getMapKeyClass(), getTarget() ); - parserMapKeyTemporal( oneToMany.getMapKeyTemporal(), getTarget() ); - parserMapKeyEnumerated( oneToMany.getMapKeyEnumerated(), getTarget() ); - parserJoinColumnList( oneToMany.getJoinColumn(), getTarget() ); - parserOrderColumn( oneToMany.getOrderColumn(), getTarget() ); - parserJoinTable( oneToMany.getJoinTable(), getTarget() ); - if ( oneToMany.getOrderBy() != null ) { - create( ORDER_BY, getTarget(), MockHelper.stringValueArray( "value", oneToMany.getOrderBy() ) ); - } - } - - @Override - protected JaxbAccessType getAccessType() { - return oneToMany.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - oneToMany.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToOneMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToOneMocker.java deleted file mode 100644 index f99f4eaa70f8..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/OneToOneMocker.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbOneToOne; - -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class OneToOneMocker extends PropertyMocker { - private JaxbOneToOne oneToOne; - - OneToOneMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbOneToOne oneToOne) { - super( indexBuilder, classInfo, defaults ); - this.oneToOne = oneToOne; - } - - @Override - protected String getFieldName() { - return oneToOne.getName(); - } - - @Override - protected void processExtra() { - List annotationValueList = new ArrayList(); - MockHelper.classValue( - "targetEntity", oneToOne.getTargetEntity(), annotationValueList, indexBuilder.getServiceRegistry() - ); - MockHelper.enumValue( "fetch", FETCH_TYPE, oneToOne.getFetch(), annotationValueList ); - MockHelper.booleanValue( "optional", oneToOne.isOptional(), annotationValueList ); - MockHelper.booleanValue( "orphanRemoval", oneToOne.isOrphanRemoval(), annotationValueList ); - MockHelper.stringValue( "mappedBy", oneToOne.getMappedBy(), annotationValueList ); - MockHelper.cascadeValue( "cascade", oneToOne.getCascade(), isDefaultCascadePersist(), annotationValueList ); - create( ONE_TO_ONE, annotationValueList ); - - parserPrimaryKeyJoinColumnList( oneToOne.getPrimaryKeyJoinColumn(), getTarget() ); - parserJoinColumnList( oneToOne.getJoinColumn(), getTarget() ); - parserJoinTable( oneToOne.getJoinTable(), getTarget() ); - if ( oneToOne.getMapsId() != null ) { - create( MAPS_ID, MockHelper.stringValueArray( "value", oneToOne.getMapsId() ) ); - } - if ( oneToOne.isId() != null && oneToOne.isId() ) { - create( ID ); - } - } - - @Override - protected JaxbAccessType getAccessType() { - return oneToOne.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - oneToOne.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PropertyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PropertyMocker.java deleted file mode 100644 index dccdbbeb11c4..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PropertyMocker.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.HibernateException; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEnumType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKey; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKeyClass; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKeyColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbMapKeyJoinColumn; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTemporalType; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; - -/** - * @author Strong Liu - */ -abstract class PropertyMocker extends AnnotationMocker { - protected ClassInfo classInfo; - private AnnotationTarget target; - - PropertyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults) { - super( indexBuilder, defaults ); - this.classInfo = classInfo; - } - - protected abstract void processExtra(); - - protected abstract String getFieldName(); - - protected abstract JaxbAccessType getAccessType(); - - protected abstract void setAccessType(JaxbAccessType accessType); - - @Override - protected DotName getTargetName() { - return classInfo.name(); - } - - protected void resolveTarget() { - //attribute in orm.xml has access sub-element - JaxbAccessType accessType = getAccessType(); - if ( accessType == null ) { - //attribute in the entity class has @Access - accessType = AccessHelper.getAccessFromAttributeAnnotation( getTargetName(), getFieldName(), indexBuilder ); - if ( accessType == null ) { - accessType = AccessHelper.getEntityAccess( getTargetName(), indexBuilder ); - } - if ( accessType == null ) { - accessType = AccessHelper.getAccessFromIdPosition( getTargetName(), indexBuilder ); - } - if (accessType == null ) { - //this should only for determin @Id position - accessType = AccessHelper.getAccessFromDefault( indexBuilder ); - } - if ( accessType == null ) { - accessType = JaxbAccessType.PROPERTY; - - } - setAccessType( accessType ); - } - - } - - @Override - protected AnnotationTarget getTarget() { - if ( target == null ) { - target = getTargetFromAttributeAccessType( getAccessType() ); - } - return target; - } - - protected AnnotationTarget getTargetFromAttributeAccessType(JaxbAccessType accessType) { - if ( accessType == null ) { - throw new IllegalArgumentException( "access type can't be null." ); - } - switch ( accessType ) { - case FIELD: - return MockHelper.getTarget( - indexBuilder.getServiceRegistry(), - classInfo, - getFieldName(), - MockHelper.TargetType.FIELD - ); - case PROPERTY: - return MockHelper.getTarget( - indexBuilder.getServiceRegistry(), - classInfo, - getFieldName(), - MockHelper.TargetType.PROPERTY - ); - default: - throw new HibernateException( "can't determin access type [" + accessType + "]" ); - } - } - - - @Override - final void process() { - resolveTarget(); - processExtra(); - } - - protected AnnotationInstance parserMapKeyColumn(JaxbMapKeyColumn mapKeyColumn, AnnotationTarget target) { - if ( mapKeyColumn == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", mapKeyColumn.getName(), annotationValueList ); - MockHelper.stringValue( "columnDefinition", mapKeyColumn.getColumnDefinition(), annotationValueList ); - MockHelper.stringValue( "table", mapKeyColumn.getTable(), annotationValueList ); - MockHelper.booleanValue( "nullable", mapKeyColumn.isNullable(), annotationValueList ); - MockHelper.booleanValue( "insertable", mapKeyColumn.isInsertable(), annotationValueList ); - MockHelper.booleanValue( "updatable", mapKeyColumn.isUpdatable(), annotationValueList ); - MockHelper.booleanValue( "unique", mapKeyColumn.isUnique(), annotationValueList ); - MockHelper.integerValue( "length", mapKeyColumn.getLength(), annotationValueList ); - MockHelper.integerValue( "precision", mapKeyColumn.getPrecision(), annotationValueList ); - MockHelper.integerValue( "scale", mapKeyColumn.getScale(), annotationValueList ); - return create( MAP_KEY_COLUMN, target, annotationValueList ); - } - - protected AnnotationInstance parserMapKeyClass(JaxbMapKeyClass mapKeyClass, AnnotationTarget target) { - if ( mapKeyClass == null ) { - return null; - } - return create( - MAP_KEY_CLASS, target, MockHelper.classValueArray( - "value", mapKeyClass.getClazz(), indexBuilder.getServiceRegistry() - ) - ); - } - - protected AnnotationInstance parserMapKeyTemporal(JaxbTemporalType temporalType, AnnotationTarget target) { - if ( temporalType == null ) { - return null; - } - return create( - MAP_KEY_TEMPORAL, target, - MockHelper.enumValueArray( "value", TEMPORAL_TYPE, temporalType ) - ); - } - - protected AnnotationInstance parserMapKeyEnumerated(JaxbEnumType enumType, AnnotationTarget target) { - if ( enumType == null ) { - return null; - } - return create( - MAP_KEY_ENUMERATED, target, - MockHelper.enumValueArray( "value", ENUM_TYPE, enumType ) - ); - } - - protected AnnotationInstance parserMapKey(JaxbMapKey mapKey, AnnotationTarget target) { - if ( mapKey == null ) { - return null; - } - return create( MAP_KEY, target, MockHelper.stringValueArray( "name", mapKey.getName() ) ); - } - - private AnnotationValue[] nestedMapKeyJoinColumnList(String name, List columns, List annotationValueList) { - if ( MockHelper.isNotEmpty( columns ) ) { - AnnotationValue[] values = new AnnotationValue[columns.size()]; - for ( int i = 0; i < columns.size(); i++ ) { - AnnotationInstance annotationInstance = parserMapKeyJoinColumn( columns.get( i ), null ); - values[i] = MockHelper.nestedAnnotationValue( - "", annotationInstance - ); - } - MockHelper.addToCollectionIfNotNull( - annotationValueList, AnnotationValue.createArrayValue( name, values ) - ); - return values; - } - return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; - } - - protected AnnotationInstance parserMapKeyJoinColumnList(List joinColumnList, AnnotationTarget target) { - if ( MockHelper.isNotEmpty( joinColumnList ) ) { - if ( joinColumnList.size() == 1 ) { - return parserMapKeyJoinColumn( joinColumnList.get( 0 ), target ); - } - else { - AnnotationValue[] values = nestedMapKeyJoinColumnList( "value", joinColumnList, null ); - return create( - MAP_KEY_JOIN_COLUMNS, - target, - values - ); - } - } - return null; - - } - - //@MapKeyJoinColumn - private AnnotationInstance parserMapKeyJoinColumn(JaxbMapKeyJoinColumn column, AnnotationTarget target) { - if ( column == null ) { - return null; - } - List annotationValueList = new ArrayList(); - MockHelper.stringValue( "name", column.getName(), annotationValueList ); - MockHelper.stringValue( "columnDefinition", column.getColumnDefinition(), annotationValueList ); - MockHelper.stringValue( "table", column.getTable(), annotationValueList ); - MockHelper.stringValue( - "referencedColumnName", column.getReferencedColumnName(), annotationValueList - ); - MockHelper.booleanValue( "unique", column.isUnique(), annotationValueList ); - MockHelper.booleanValue( "nullable", column.isNullable(), annotationValueList ); - MockHelper.booleanValue( "insertable", column.isInsertable(), annotationValueList ); - MockHelper.booleanValue( "updatable", column.isUpdatable(), annotationValueList ); - return create( MAP_KEY_JOIN_COLUMN, target, annotationValueList ); - } - - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java deleted file mode 100644 index d276b6d1aa2f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/SchemaAware.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbCollectionTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbJoinTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbSecondaryTable; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTable; - -/** - * @author Strong Liu - */ -interface SchemaAware { - String getSchema(); - - void setSchema(String schema); - - String getCatalog(); - - void setCatalog(String catalog); - - static class SecondaryTableSchemaAware implements SchemaAware { - private JaxbSecondaryTable table; - - SecondaryTableSchemaAware(JaxbSecondaryTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } - - static class TableSchemaAware implements SchemaAware { - private JaxbTable table; - - public TableSchemaAware(JaxbTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } - - static class JoinTableSchemaAware implements SchemaAware { - private JaxbJoinTable table; - - public JoinTableSchemaAware(JaxbJoinTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } - - static class CollectionTableSchemaAware implements SchemaAware { - private JaxbCollectionTable table; - - public CollectionTableSchemaAware(JaxbCollectionTable table) { - this.table = table; - } - - @Override - public String getCatalog() { - return table.getCatalog(); - } - - @Override - public String getSchema() { - return table.getSchema(); - } - - @Override - public void setSchema(String schema) { - table.setSchema( schema ); - } - - @Override - public void setCatalog(String catalog) { - table.setCatalog( catalog ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/TransientMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/TransientMocker.java deleted file mode 100644 index 7154dcff64b6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/TransientMocker.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbTransient; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class TransientMocker extends PropertyMocker { - private JaxbTransient transientObj; - - TransientMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbTransient transientObj) { - super( indexBuilder, classInfo, defaults ); - this.transientObj = transientObj; - } - - @Override - protected void processExtra() { - create( TRANSIENT ); - } - - @Override - protected String getFieldName() { - return transientObj.getName(); - } - - @Override - protected JaxbAccessType getAccessType() { - return JaxbAccessType.FIELD; - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - //ignore - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/VersionMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/VersionMocker.java deleted file mode 100644 index d54c94168e78..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/VersionMocker.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbVersion; - -import org.jboss.jandex.ClassInfo; - -/** - * @author Strong Liu - */ -class VersionMocker extends PropertyMocker { - private JaxbVersion version; - - VersionMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbVersion version) { - super( indexBuilder, classInfo, defaults ); - this.version = version; - } - - @Override - protected String getFieldName() { - return version.getName(); - } - - @Override - protected void processExtra() { - create( VERSION ); - parserColumn( version.getColumn(), getTarget() ); - parserTemporalType( version.getTemporal(), getTarget() ); - } - - @Override - protected JaxbAccessType getAccessType() { - return version.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - version.setAccess( accessType ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AssociationAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AssociationAttributeSource.java deleted file mode 100644 index 57743a69e417..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AssociationAttributeSource.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; - -/** - * Contract describing sources for attributes which model associations. - * - * @author Steve Ebersole - */ -public interface AssociationAttributeSource extends AttributeSource { - /** - * Obtain the cascade styles to be applied to this association. - * - * @return The cascade styles. - */ - public Iterable getCascadeStyles(); - - /** - * Obtain the fetch mode to be applied to this association. - * - * @return The fetch mode. - */ - public FetchMode getFetchMode(); - - public FetchTiming getFetchTiming(); - - public FetchStyle getFetchStyle(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSource.java deleted file mode 100644 index 2999634f1a8d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSource.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * Contract for sources of persistent attribute descriptions. - * - * @author Steve Ebersole - */ -public interface AttributeSource { - /** - * Obtain the attribute name. - * - * @return The attribute name. {@code null} ais NOT allowed! - */ - public String getName(); - - /** - * Is this a singular attribute? Specifically, can it be cast to {@link SingularAttributeSource}? - * - * @return {@code true} indicates this is castable to {@link SingularAttributeSource}; {@code false} otherwise. - */ - public boolean isSingular(); - - /** - * Obtain information about the Hibernate type ({@link org.hibernate.type.Type}) for this attribute. - * - * @return The Hibernate type information - */ - public ExplicitHibernateTypeSource getTypeInformation(); - - /** - * Obtain the name of the property accessor style used to access this attribute. - * - * @return The property accessor style for this attribute. - * - * @see org.hibernate.property.PropertyAccessor - */ - public String getPropertyAccessorName(); - - /** - * If the containing entity is using {@link org.hibernate.engine.OptimisticLockStyle#ALL} or - * {@link org.hibernate.engine.OptimisticLockStyle#DIRTY} style optimistic locking, should this attribute - * be used? - * - * @return {@code true} indicates it should be included; {@code false}, it should not. - */ - public boolean isIncludedInOptimisticLocking(); - - /** - * Obtain the meta-attribute sources associated with this attribute. - * - * @return The meta-attribute sources. - */ - public Iterable metaAttributes(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSourceContainer.java deleted file mode 100644 index d4d088bbe3b8..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/AttributeSourceContainer.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.metamodel.source.LocalBindingContext; - -/** - * Contract for a container of {@link AttributeSource} references. Both entities and components contain - * attributes. - * - * @author Steve Ebersole - */ -public interface AttributeSourceContainer { - /** - * Obtain the path used to uniquely identify this container. - * - * @return The unique identifier path - */ - public String getPath(); - - /** - * Obtain this container's attribute sources. - * - * @return The attribute sources. - */ - public Iterable attributeSources(); - - /** - * Obtain the local binding context associated with this container. - * - * @return The local binding context - */ - public LocalBindingContext getLocalBindingContext(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/BasicPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/BasicPluralAttributeElementSource.java deleted file mode 100644 index bf1d055bd892..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/BasicPluralAttributeElementSource.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.util.List; - -/** - * @author Steve Ebersole - */ -public interface BasicPluralAttributeElementSource extends PluralAttributeElementSource { - public List getValueSources(); - public ExplicitHibernateTypeSource getExplicitHibernateTypeSource(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java deleted file mode 100644 index 2e5e2c84d3e8..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.beans.BeanInfoHelper; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.AttributeBindingContainer; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.BasicCollectionElement; -import org.hibernate.metamodel.binding.CollectionElementNature; -import org.hibernate.metamodel.binding.CollectionLaziness; -import org.hibernate.metamodel.binding.ComponentAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityDiscriminator; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.binding.ManyToOneAttributeBinding; -import org.hibernate.metamodel.binding.MetaAttribute; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.domain.Component; -import org.hibernate.metamodel.domain.Entity; -import org.hibernate.metamodel.domain.PluralAttribute; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.Identifier; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.metamodel.relational.Tuple; -import org.hibernate.metamodel.relational.UniqueKey; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.hbm.Helper; -import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.tuple.entity.EntityTuplizer; - -/** - * The common binder shared between annotations and {@code hbm.xml} processing. - *

      - * The API consists of {@link #Binder(MetadataImplementor, List)} and {@link #processEntityHierarchy(EntityHierarchy)} - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class Binder { - private final MetadataImplementor metadata; - private final List processedEntityNames; - - private InheritanceType currentInheritanceType; - private EntityMode currentHierarchyEntityMode; - private LocalBindingContext currentBindingContext; - - public Binder(MetadataImplementor metadata, List processedEntityNames) { - this.metadata = metadata; - this.processedEntityNames = processedEntityNames; - } - - /** - * Process an entity hierarchy. - * - * @param entityHierarchy THe hierarchy to process. - */ - public void processEntityHierarchy(EntityHierarchy entityHierarchy) { - currentInheritanceType = entityHierarchy.getHierarchyInheritanceType(); - EntityBinding rootEntityBinding = createEntityBinding( entityHierarchy.getRootEntitySource(), null ); - if ( currentInheritanceType != InheritanceType.NO_INHERITANCE ) { - processHierarchySubEntities( entityHierarchy.getRootEntitySource(), rootEntityBinding ); - } - currentHierarchyEntityMode = null; - } - - private void processHierarchySubEntities(SubclassEntityContainer subclassEntitySource, EntityBinding superEntityBinding) { - for ( SubclassEntitySource subEntity : subclassEntitySource.subclassEntitySources() ) { - EntityBinding entityBinding = createEntityBinding( subEntity, superEntityBinding ); - processHierarchySubEntities( subEntity, entityBinding ); - } - } - - - // Entities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - private EntityBinding createEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - if ( processedEntityNames.contains( entitySource.getEntityName() ) ) { - return metadata.getEntityBinding( entitySource.getEntityName() ); - } - - currentBindingContext = entitySource.getLocalBindingContext(); - try { - final EntityBinding entityBinding = doCreateEntityBinding( entitySource, superEntityBinding ); - - metadata.addEntity( entityBinding ); - processedEntityNames.add( entityBinding.getEntity().getName() ); - - processFetchProfiles( entitySource, entityBinding ); - - return entityBinding; - } - finally { - currentBindingContext = null; - } - } - - private EntityBinding doCreateEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = createBasicEntityBinding( entitySource, superEntityBinding ); - - bindSecondaryTables( entitySource, entityBinding ); - bindAttributes( entitySource, entityBinding ); - - bindTableUniqueConstraints( entitySource, entityBinding ); - - return entityBinding; - } - - private EntityBinding createBasicEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - if ( superEntityBinding == null ) { - return makeRootEntityBinding( (RootEntitySource) entitySource ); - } - else { - switch ( currentInheritanceType ) { - case SINGLE_TABLE: - return makeDiscriminatedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding ); - case JOINED: - return makeJoinedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding ); - case TABLE_PER_CLASS: - return makeUnionedSubclassBinding( (SubclassEntitySource) entitySource, superEntityBinding ); - default: - // extreme internal error! - throw new AssertionFailure( "Internal condition failure" ); - } - } - } - - private EntityBinding makeRootEntityBinding(RootEntitySource entitySource) { - currentHierarchyEntityMode = entitySource.getEntityMode(); - - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, null ); - - bindPrimaryTable( entitySource, entityBinding ); - - bindIdentifier( entitySource, entityBinding ); - bindVersion( entityBinding, entitySource ); - bindDiscriminator( entitySource, entityBinding ); - - entityBinding.getHierarchyDetails().setCaching( entitySource.getCaching() ); - entityBinding.getHierarchyDetails().setExplicitPolymorphism( entitySource.isExplicitPolymorphism() ); - entityBinding.getHierarchyDetails().setOptimisticLockStyle( entitySource.getOptimisticLockStyle() ); - - entityBinding.setMutable( entitySource.isMutable() ); - entityBinding.setWhereFilter( entitySource.getWhere() ); - entityBinding.setRowId( entitySource.getRowId() ); - - return entityBinding; - } - - private EntityBinding buildBasicEntityBinding(EntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = superEntityBinding == null - ? new EntityBinding( currentInheritanceType, currentHierarchyEntityMode ) - : new EntityBinding( superEntityBinding ); - - final String entityName = entitySource.getEntityName(); - final String className = currentHierarchyEntityMode == EntityMode.POJO ? entitySource.getClassName() : null; - - final Entity entity = new Entity( - entityName, - className, - currentBindingContext.makeClassReference( className ), - superEntityBinding == null ? null : superEntityBinding.getEntity() - ); - entityBinding.setEntity( entity ); - - entityBinding.setJpaEntityName( entitySource.getJpaEntityName() ); - - if ( currentHierarchyEntityMode == EntityMode.POJO ) { - final String proxy = entitySource.getProxy(); - if ( proxy != null ) { - entityBinding.setProxyInterfaceType( - currentBindingContext.makeClassReference( - currentBindingContext.qualifyClassName( proxy ) - ) - ); - entityBinding.setLazy( true ); - } - else if ( entitySource.isLazy() ) { - entityBinding.setProxyInterfaceType( entityBinding.getEntity().getClassReferenceUnresolved() ); - entityBinding.setLazy( true ); - } - } - else { - entityBinding.setProxyInterfaceType( null ); - entityBinding.setLazy( entitySource.isLazy() ); - } - - final String customTuplizerClassName = entitySource.getCustomTuplizerClassName(); - if ( customTuplizerClassName != null ) { - entityBinding.setCustomEntityTuplizerClass( - currentBindingContext.locateClassByName( - customTuplizerClassName - ) - ); - } - - final String customPersisterClassName = entitySource.getCustomPersisterClassName(); - if ( customPersisterClassName != null ) { - entityBinding.setCustomEntityPersisterClass( - currentBindingContext.locateClassByName( - customPersisterClassName - ) - ); - } - - entityBinding.setMetaAttributeContext( buildMetaAttributeContext( entitySource ) ); - - entityBinding.setDynamicUpdate( entitySource.isDynamicUpdate() ); - entityBinding.setDynamicInsert( entitySource.isDynamicInsert() ); - entityBinding.setBatchSize( entitySource.getBatchSize() ); - entityBinding.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() ); - entityBinding.setAbstract( entitySource.isAbstract() ); - - entityBinding.setCustomLoaderName( entitySource.getCustomLoaderName() ); - entityBinding.setCustomInsert( entitySource.getCustomSqlInsert() ); - entityBinding.setCustomUpdate( entitySource.getCustomSqlUpdate() ); - entityBinding.setCustomDelete( entitySource.getCustomSqlDelete() ); - - if ( entitySource.getSynchronizedTableNames() != null ) { - entityBinding.addSynchronizedTableNames( entitySource.getSynchronizedTableNames() ); - } - - entityBinding.setJpaCallbackClasses(entitySource.getJpaCallbackClasses()); - - return entityBinding; - } - - private EntityBinding makeDiscriminatedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding ); - - entityBinding.setPrimaryTable( superEntityBinding.getPrimaryTable() ); - entityBinding.setPrimaryTableName( superEntityBinding.getPrimaryTableName() ); - bindDiscriminatorValue( entitySource, entityBinding ); - - return entityBinding; - } - - private EntityBinding makeJoinedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding ); - - bindPrimaryTable( entitySource, entityBinding ); - - // todo : join - - return entityBinding; - } - - private EntityBinding makeUnionedSubclassBinding(SubclassEntitySource entitySource, EntityBinding superEntityBinding) { - final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding ); - - bindPrimaryTable( entitySource, entityBinding ); - - // todo : ?? - - return entityBinding; - } - - // Attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - private void bindIdentifier(RootEntitySource entitySource, EntityBinding entityBinding) { - if ( entitySource.getIdentifierSource() == null ) { - throw new AssertionFailure( "Expecting identifier information on root entity descriptor" ); - } - switch ( entitySource.getIdentifierSource().getNature() ) { - case SIMPLE: { - bindSimpleIdentifier( (SimpleIdentifierSource) entitySource.getIdentifierSource(), entityBinding ); - break; - } - case AGGREGATED_COMPOSITE: { - // composite id with an actual component class - break; - } - case COMPOSITE: { - // what we used to term an "embedded composite identifier", which is not tobe confused with the JPA - // term embedded. Specifically a composite id where there is no component class, though there may - // be a @IdClass :/ - break; - } - } - } - - private void bindSimpleIdentifier(SimpleIdentifierSource identifierSource, EntityBinding entityBinding) { - final BasicAttributeBinding idAttributeBinding = doBasicSingularAttributeBindingCreation( - identifierSource.getIdentifierAttributeSource(), entityBinding - ); - - entityBinding.getHierarchyDetails().getEntityIdentifier().setValueBinding( idAttributeBinding ); - IdGenerator generator = identifierSource.getIdentifierGeneratorDescriptor(); - if ( generator == null ) { - Map params = new HashMap(); - params.put( IdentifierGenerator.ENTITY_NAME, entityBinding.getEntity().getName() ); - generator = new IdGenerator( "default_assign_identity_generator", "assigned", params ); - } - entityBinding.getHierarchyDetails() - .getEntityIdentifier() - .setIdGenerator( generator ); - - final org.hibernate.metamodel.relational.Value relationalValue = idAttributeBinding.getValue(); - - if ( SimpleValue.class.isInstance( relationalValue ) ) { - if ( !Column.class.isInstance( relationalValue ) ) { - // this should never ever happen.. - throw new AssertionFailure( "Simple-id was not a column." ); - } - entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( relationalValue ) ); - } - else { - for ( SimpleValue subValue : ( (Tuple) relationalValue ).values() ) { - if ( Column.class.isInstance( subValue ) ) { - entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( subValue ) ); - } - } - } - } - - private void bindVersion(EntityBinding entityBinding, RootEntitySource entitySource) { - final SingularAttributeSource versioningAttributeSource = entitySource.getVersioningAttributeSource(); - if ( versioningAttributeSource == null ) { - return; - } - - BasicAttributeBinding attributeBinding = doBasicSingularAttributeBindingCreation( - versioningAttributeSource, entityBinding - ); - entityBinding.getHierarchyDetails().setVersioningAttributeBinding( attributeBinding ); - } - - private void bindDiscriminator(RootEntitySource entitySource, EntityBinding entityBinding) { - final DiscriminatorSource discriminatorSource = entitySource.getDiscriminatorSource(); - if ( discriminatorSource == null ) { - return; - } - - EntityDiscriminator discriminator = new EntityDiscriminator(); - SimpleValue relationalValue = makeSimpleValue( - entityBinding, - discriminatorSource.getDiscriminatorRelationalValueSource() - ); - discriminator.setBoundValue( relationalValue ); - - discriminator.getExplicitHibernateTypeDescriptor().setExplicitTypeName( - discriminatorSource.getExplicitHibernateTypeName() != null - ? discriminatorSource.getExplicitHibernateTypeName() - : "string" - ); - - discriminator.setInserted( discriminatorSource.isInserted() ); - discriminator.setForced( discriminatorSource.isForced() ); - - entityBinding.getHierarchyDetails().setEntityDiscriminator( discriminator ); - entityBinding.setDiscriminatorMatchValue( entitySource.getDiscriminatorMatchValue() ); - } - - private void bindDiscriminatorValue(SubclassEntitySource entitySource, EntityBinding entityBinding) { - final String discriminatorValue = entitySource.getDiscriminatorMatchValue(); - if ( discriminatorValue == null ) { - return; - } - entityBinding.setDiscriminatorMatchValue( discriminatorValue ); - } - - private void bindAttributes(AttributeSourceContainer attributeSourceContainer, AttributeBindingContainer attributeBindingContainer) { - // todo : we really need the notion of a Stack here for the table from which the columns come for binding these attributes. - // todo : adding the concept (interface) of a source of attribute metadata would allow reuse of this method for entity, component, unique-key, etc - // for now, simply assume all columns come from the base table.... - - for ( AttributeSource attributeSource : attributeSourceContainer.attributeSources() ) { - if ( attributeSource.isSingular() ) { - final SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource; - if ( singularAttributeSource.getNature() == SingularAttributeNature.COMPONENT ) { - bindComponent( (ComponentAttributeSource) singularAttributeSource, attributeBindingContainer ); - } - else { - doBasicSingularAttributeBindingCreation( singularAttributeSource, attributeBindingContainer ); - } - } - else { - bindPersistentCollection( (PluralAttributeSource) attributeSource, attributeBindingContainer ); - } - } - } - - private void bindComponent(ComponentAttributeSource attributeSource, AttributeBindingContainer container) { - final String attributeName = attributeSource.getName(); - SingularAttribute attribute = container.getAttributeContainer().locateComponentAttribute( attributeName ); - if ( attribute == null ) { - final Component component = new Component( - attributeSource.getPath(), - attributeSource.getClassName(), - attributeSource.getClassReference(), - null // component inheritance not YET supported - ); - attribute = container.getAttributeContainer().createComponentAttribute( attributeName, component ); - } - ComponentAttributeBinding componentAttributeBinding = container.makeComponentAttributeBinding( attribute ); - - if ( StringHelper.isNotEmpty( attributeSource.getParentReferenceAttributeName() ) ) { - final SingularAttribute parentReferenceAttribute = - componentAttributeBinding.getComponent() - .createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); - componentAttributeBinding.setParentReference( parentReferenceAttribute ); - } - - componentAttributeBinding.setMetaAttributeContext( - buildMetaAttributeContext( attributeSource.metaAttributes(), container.getMetaAttributeContext() ) - ); - - bindAttributes( attributeSource, componentAttributeBinding ); - } - - private void bindPersistentCollection(PluralAttributeSource attributeSource, AttributeBindingContainer attributeBindingContainer) { - final PluralAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() - .locatePluralAttribute( attributeSource.getName() ); - final AbstractPluralAttributeBinding pluralAttributeBinding; - - if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.BAG ) { - final PluralAttribute attribute = existingAttribute != null - ? existingAttribute - : attributeBindingContainer.getAttributeContainer().createBag( attributeSource.getName() ); - pluralAttributeBinding = attributeBindingContainer.makeBagAttributeBinding( - attribute, - convert( attributeSource.getElementSource().getNature() ) - ); - } - else if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.SET ) { - final PluralAttribute attribute = existingAttribute != null - ? existingAttribute - : attributeBindingContainer.getAttributeContainer().createSet( attributeSource.getName() ); - pluralAttributeBinding = attributeBindingContainer.makeSetAttributeBinding( - attribute, - convert( attributeSource.getElementSource().getNature() ) - ); - } - else { - // todo : implement other collection types - throw new NotYetImplementedException( "Collections other than bag and set not yet implemented :(" ); - } - - doBasicPluralAttributeBinding( attributeSource, pluralAttributeBinding ); - - bindCollectionTable( attributeSource, pluralAttributeBinding ); - bindSortingAndOrdering( attributeSource, pluralAttributeBinding ); - - bindCollectionKey( attributeSource, pluralAttributeBinding ); - bindCollectionElement( attributeSource, pluralAttributeBinding ); - bindCollectionIndex( attributeSource, pluralAttributeBinding ); - - metadata.addCollection( pluralAttributeBinding ); - } - - private void doBasicPluralAttributeBinding(PluralAttributeSource source, AbstractPluralAttributeBinding binding) { - binding.setFetchTiming( source.getFetchTiming() ); - binding.setFetchStyle( source.getFetchStyle() ); - binding.setCascadeStyles( source.getCascadeStyles() ); - - binding.setCaching( source.getCaching() ); - - binding.getHibernateTypeDescriptor().setJavaTypeName( - source.getPluralAttributeNature().reportedJavaType().getName() - ); - binding.getHibernateTypeDescriptor().setExplicitTypeName( source.getTypeInformation().getName() ); - binding.getHibernateTypeDescriptor().getTypeParameters().putAll( source.getTypeInformation().getParameters() ); - - if ( StringHelper.isNotEmpty( source.getCustomPersisterClassName() ) ) { - binding.setCollectionPersisterClass( - currentBindingContext.locateClassByName( source.getCustomPersisterClassName() ) - ); - } - - if ( source.getCustomPersisterClassName() != null ) { - binding.setCollectionPersisterClass( - metadata.locateClassByName( source.getCustomPersisterClassName() ) - ); - } - - binding.setCustomLoaderName( source.getCustomLoaderName() ); - binding.setCustomSqlInsert( source.getCustomSqlInsert() ); - binding.setCustomSqlUpdate( source.getCustomSqlUpdate() ); - binding.setCustomSqlDelete( source.getCustomSqlDelete() ); - binding.setCustomSqlDeleteAll( source.getCustomSqlDeleteAll() ); - - binding.setMetaAttributeContext( - buildMetaAttributeContext( - source.metaAttributes(), - binding.getContainer().getMetaAttributeContext() - ) - ); - - doBasicAttributeBinding( source, binding ); - } - - private CollectionLaziness interpretLaziness(String laziness) { - if ( laziness == null ) { - laziness = Boolean.toString( metadata.getMappingDefaults().areAssociationsLazy() ); - } - - if ( "extra".equals( laziness ) ) { - return CollectionLaziness.EXTRA; - } - else if ( "false".equals( laziness ) ) { - return CollectionLaziness.NOT; - } - else if ( "true".equals( laziness ) ) { - return CollectionLaziness.LAZY; - } - - throw new MappingException( - String.format( "Unexpected collection laziness value %s", laziness ), - currentBindingContext.getOrigin() - ); - } - - private void bindCollectionTable( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - if ( attributeSource.getElementSource().getNature() == PluralAttributeElementNature.ONE_TO_MANY ) { - return; - } - - final Schema.Name schemaName = Helper.determineDatabaseSchemaName( - attributeSource.getExplicitSchemaName(), - attributeSource.getExplicitCatalogName(), - currentBindingContext - ); - final Schema schema = metadata.getDatabase().locateSchema( schemaName ); - - final String tableName = attributeSource.getExplicitCollectionTableName(); - if ( StringHelper.isNotEmpty( tableName ) ) { - final Identifier tableIdentifier = Identifier.toIdentifier( - currentBindingContext.getNamingStrategy().tableName( tableName ) - ); - Table collectionTable = schema.locateTable( tableIdentifier ); - if ( collectionTable == null ) { - collectionTable = schema.createTable( tableIdentifier ); - } - pluralAttributeBinding.setCollectionTable( collectionTable ); - } - else { - // todo : not sure wel have all the needed info here in all cases, specifically when needing to know the "other side" - final EntityBinding owner = pluralAttributeBinding.getContainer().seekEntityBinding(); - final String ownerTableLogicalName = Table.class.isInstance( owner.getPrimaryTable() ) - ? Table.class.cast( owner.getPrimaryTable() ).getTableName().getName() - : null; - String collectionTableName = currentBindingContext.getNamingStrategy().collectionTableName( - owner.getEntity().getName(), - ownerTableLogicalName, - null, // todo : here - null, // todo : and here - pluralAttributeBinding.getContainer().getPathBase() + '.' + attributeSource.getName() - ); - collectionTableName = quoteIdentifier( collectionTableName ); - pluralAttributeBinding.setCollectionTable( - schema.locateOrCreateTable( - Identifier.toIdentifier( - collectionTableName - ) - ) - ); - } - - if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableComment() ) ) { - pluralAttributeBinding.getCollectionTable().addComment( attributeSource.getCollectionTableComment() ); - } - - if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableCheck() ) ) { - pluralAttributeBinding.getCollectionTable().addCheckConstraint( attributeSource.getCollectionTableCheck() ); - } - - pluralAttributeBinding.setWhere( attributeSource.getWhere() ); - } - - private void bindCollectionKey( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - pluralAttributeBinding.getCollectionKey().prepareForeignKey( - attributeSource.getKeySource().getExplicitForeignKeyName(), - null // todo : handle secondary table names - ); - pluralAttributeBinding.getCollectionKey().getForeignKey().setDeleteRule( - attributeSource.getKeySource().getOnDeleteAction() - ); - // todo : need to bind "relational values", account for property-ref - } - - private void bindCollectionElement( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - final PluralAttributeElementSource elementSource = attributeSource.getElementSource(); - if ( elementSource.getNature() == PluralAttributeElementNature.BASIC ) { - final BasicPluralAttributeElementSource basicElementSource = (BasicPluralAttributeElementSource) elementSource; - final BasicCollectionElement basicCollectionElement = (BasicCollectionElement) pluralAttributeBinding.getCollectionElement(); - resolveTypeInformation( - basicElementSource.getExplicitHibernateTypeSource(), - pluralAttributeBinding.getAttribute(), - basicCollectionElement - ); - // todo : temp - return; - } - // todo : implement - throw new NotYetImplementedException( - String.format( - "Support for collection elements of type %s not yet implemented", - elementSource.getNature() - ) - ); - } - - private void bindCollectionIndex( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - if ( attributeSource.getPluralAttributeNature() != PluralAttributeNature.LIST - && attributeSource.getPluralAttributeNature() != PluralAttributeNature.MAP ) { - return; - } - - // todo : implement - throw new NotYetImplementedException(); - } - - private void bindSortingAndOrdering( - PluralAttributeSource attributeSource, - AbstractPluralAttributeBinding pluralAttributeBinding) { - if ( Sortable.class.isInstance( attributeSource ) ) { - final Sortable sortable = Sortable.class.cast( attributeSource ); - if ( sortable.isSorted() ) { - // todo : handle setting comparator - - // and then return because sorting and ordering are mutually exclusive - return; - } - } - - if ( Orderable.class.isInstance( attributeSource ) ) { - final Orderable orderable = Orderable.class.cast( attributeSource ); - if ( orderable.isOrdered() ) { - // todo : handle setting ordering - } - } - } - - private void doBasicAttributeBinding(AttributeSource attributeSource, AttributeBinding attributeBinding) { - attributeBinding.setPropertyAccessorName( attributeSource.getPropertyAccessorName() ); - attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() ); - } - - private CollectionElementNature convert(PluralAttributeElementNature pluralAttributeElementNature) { - return CollectionElementNature.valueOf( pluralAttributeElementNature.name() ); - } - - private BasicAttributeBinding doBasicSingularAttributeBindingCreation( - SingularAttributeSource attributeSource, - AttributeBindingContainer attributeBindingContainer) { - final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() - .locateSingularAttribute( attributeSource.getName() ); - final SingularAttribute attribute; - if ( existingAttribute != null ) { - attribute = existingAttribute; - } - else if ( attributeSource.isVirtualAttribute() ) { - attribute = attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( - attributeSource.getName() - ); - } - else { - attribute = attributeBindingContainer.getAttributeContainer() - .createSingularAttribute( attributeSource.getName() ); - } - - final BasicAttributeBinding attributeBinding; - if ( attributeSource.getNature() == SingularAttributeNature.BASIC ) { - attributeBinding = attributeBindingContainer.makeBasicAttributeBinding( attribute ); - resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); - } - else if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) { - attributeBinding = attributeBindingContainer.makeManyToOneAttributeBinding( attribute ); - resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); - resolveToOneInformation( - (ToOneAttributeSource) attributeSource, - (ManyToOneAttributeBinding) attributeBinding - ); - } - else { - throw new NotYetImplementedException(); - } - - attributeBinding.setGeneration( attributeSource.getGeneration() ); - attributeBinding.setLazy( attributeSource.isLazy() ); - attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() ); - - attributeBinding.setPropertyAccessorName( - Helper.getPropertyAccessorName( - attributeSource.getPropertyAccessorName(), - false, - currentBindingContext.getMappingDefaults().getPropertyAccessorName() - ) - ); - - bindRelationalValues( attributeSource, attributeBinding ); - - attributeBinding.setMetaAttributeContext( - buildMetaAttributeContext( - attributeSource.metaAttributes(), - attributeBindingContainer.getMetaAttributeContext() - ) - ); - - return attributeBinding; - } - - private void resolveTypeInformation(ExplicitHibernateTypeSource typeSource, BasicAttributeBinding attributeBinding) { - final Class attributeJavaType = determineJavaType( attributeBinding.getAttribute() ); - if ( attributeJavaType != null ) { - attributeBinding.getAttribute() - .resolveType( currentBindingContext.makeJavaType( attributeJavaType.getName() ) ); - } - - resolveTypeInformation( typeSource, attributeBinding.getHibernateTypeDescriptor(), attributeJavaType ); - } - - private void resolveTypeInformation( - ExplicitHibernateTypeSource typeSource, - PluralAttribute attribute, - BasicCollectionElement collectionElement) { - final Class attributeJavaType = determineJavaType( attribute ); - resolveTypeInformation( typeSource, collectionElement.getHibernateTypeDescriptor(), attributeJavaType ); - } - - private void resolveTypeInformation( - ExplicitHibernateTypeSource typeSource, - HibernateTypeDescriptor hibernateTypeDescriptor, - Class discoveredJavaType) { - if ( discoveredJavaType != null ) { - hibernateTypeDescriptor.setJavaTypeName( discoveredJavaType.getName() ); - } - - final String explicitTypeName = typeSource.getName(); - if ( explicitTypeName != null ) { - final TypeDef typeDef = currentBindingContext.getMetadataImplementor() - .getTypeDefinition( explicitTypeName ); - if ( typeDef != null ) { - hibernateTypeDescriptor.setExplicitTypeName( typeDef.getTypeClass() ); - hibernateTypeDescriptor.getTypeParameters().putAll( typeDef.getParameters() ); - } - else { - hibernateTypeDescriptor.setExplicitTypeName( explicitTypeName ); - } - final Map parameters = typeSource.getParameters(); - if ( parameters != null ) { - hibernateTypeDescriptor.getTypeParameters().putAll( parameters ); - } - } - else { - if ( discoveredJavaType == null ) { - // we will have problems later determining the Hibernate Type to use. Should we throw an - // exception now? Might be better to get better contextual info - } - } - } - - /** - * @param attribute the domain attribute - * - * @return Returns the Java type of the attribute using reflection or {@code null} if the type cannot be discovered - */ - private Class determineJavaType(final SingularAttribute attribute) { - try { - final Class ownerClass = attribute.getAttributeContainer().getClassReference(); - AttributeJavaTypeDeterminerDelegate delegate = new AttributeJavaTypeDeterminerDelegate( attribute.getName() ); - BeanInfoHelper.visitBeanInfo( ownerClass, delegate ); - return delegate.javaType; - } - catch ( Exception ignore ) { - // todo : log it? - } - return null; - } - - private Class determineJavaType(PluralAttribute attribute) { - try { - final Class ownerClass = attribute.getAttributeContainer().getClassReference(); - PluralAttributeJavaTypeDeterminerDelegate delegate = new PluralAttributeJavaTypeDeterminerDelegate( - ownerClass, - attribute.getName() - ); - BeanInfoHelper.visitBeanInfo( ownerClass, delegate ); - return delegate.javaType; - } - catch ( Exception ignore ) { - // todo : log it? - } - return null; - } - - private class PluralAttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { - private final Class ownerClass; - private final String attributeName; - - private Class javaType = null; - - private PluralAttributeJavaTypeDeterminerDelegate(Class ownerClass, String attributeName) { - this.ownerClass = ownerClass; - this.attributeName = attributeName; - } - - @Override - public void processBeanInfo(BeanInfo beanInfo) throws Exception { - for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) { - if ( propertyDescriptor.getName().equals( attributeName ) ) { - javaType = extractCollectionComponentType( beanInfo, propertyDescriptor ); - break; - } - } - } - - @SuppressWarnings( { "unchecked" }) - private Class extractCollectionComponentType(BeanInfo beanInfo, PropertyDescriptor propertyDescriptor) { - final java.lang.reflect.Type collectionAttributeType; - if ( propertyDescriptor.getReadMethod() != null ) { - collectionAttributeType = propertyDescriptor.getReadMethod().getGenericReturnType(); - } - else if ( propertyDescriptor.getWriteMethod() != null ) { - collectionAttributeType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0]; - } - else { - // we need to look for the field and look at it... - try { - collectionAttributeType = ownerClass.getField( propertyDescriptor.getName() ).getGenericType(); - } - catch ( Exception e ) { - return null; - } - } - - if ( ParameterizedType.class.isInstance( collectionAttributeType ) ) { - final java.lang.reflect.Type[] types = ( (ParameterizedType) collectionAttributeType ).getActualTypeArguments(); - if ( types == null ) { - return null; - } - else if ( types.length == 1 ) { - return (Class) types[0]; - } - else if ( types.length == 2 ) { - // Map - return (Class) types[1]; - } - } - return null; - } - } - - private void resolveToOneInformation(ToOneAttributeSource attributeSource, ManyToOneAttributeBinding attributeBinding) { - final String referencedEntityName = attributeSource.getReferencedEntityName() != null - ? attributeSource.getReferencedEntityName() - : attributeBinding.getAttribute().getSingularAttributeType().getClassName(); - attributeBinding.setReferencedEntityName( referencedEntityName ); - // todo : we should consider basing references on columns instead of property-ref, which would require a resolution (later) of property-ref to column names - attributeBinding.setReferencedAttributeName( attributeSource.getReferencedEntityAttributeName() ); - - attributeBinding.setCascadeStyles( attributeSource.getCascadeStyles() ); - attributeBinding.setFetchTiming( attributeSource.getFetchTiming() ); - attributeBinding.setFetchStyle( attributeSource.getFetchStyle() ); - } - - private MetaAttributeContext buildMetaAttributeContext(EntitySource entitySource) { - return buildMetaAttributeContext( - entitySource.metaAttributes(), - true, - currentBindingContext.getMetadataImplementor().getGlobalMetaAttributeContext() - ); - } - - private static MetaAttributeContext buildMetaAttributeContext( - Iterable metaAttributeSources, - MetaAttributeContext parentContext) { - return buildMetaAttributeContext( metaAttributeSources, false, parentContext ); - } - - private static MetaAttributeContext buildMetaAttributeContext( - Iterable metaAttributeSources, - boolean onlyInheritable, - MetaAttributeContext parentContext) { - final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); - - for ( MetaAttributeSource metaAttributeSource : metaAttributeSources ) { - if ( onlyInheritable & !metaAttributeSource.isInheritable() ) { - continue; - } - - final String name = metaAttributeSource.getName(); - final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name ); - MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); - if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) { - metaAttribute = new MetaAttribute( name ); - subContext.add( metaAttribute ); - } - metaAttribute.addValue( metaAttributeSource.getValue() ); - } - - return subContext; - } - - // Relational ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - private void bindPrimaryTable(EntitySource entitySource, EntityBinding entityBinding) { - final TableSource tableSource = entitySource.getPrimaryTable(); - final Table table = createTable( entityBinding, tableSource ); - entityBinding.setPrimaryTable( table ); - entityBinding.setPrimaryTableName( table.getTableName().getName() ); - } - - private void bindSecondaryTables(EntitySource entitySource, EntityBinding entityBinding) { - for ( TableSource secondaryTableSource : entitySource.getSecondaryTables() ) { - final Table table = createTable( entityBinding, secondaryTableSource ); - entityBinding.addSecondaryTable( secondaryTableSource.getLogicalName(), table ); - } - } - - private Table createTable(EntityBinding entityBinding, TableSource tableSource) { - String tableName = tableSource.getExplicitTableName(); - if ( StringHelper.isEmpty( tableName ) ) { - tableName = currentBindingContext.getNamingStrategy() - .classToTableName( entityBinding.getEntity().getClassName() ); - } - else { - tableName = currentBindingContext.getNamingStrategy().tableName( tableName ); - } - tableName = quoteIdentifier( tableName ); - - final Schema.Name databaseSchemaName = Helper.determineDatabaseSchemaName( - tableSource.getExplicitSchemaName(), - tableSource.getExplicitCatalogName(), - currentBindingContext - ); - return currentBindingContext.getMetadataImplementor() - .getDatabase() - .locateSchema( databaseSchemaName ) - .locateOrCreateTable( Identifier.toIdentifier( tableName ) ); - } - - private void bindTableUniqueConstraints(EntitySource entitySource, EntityBinding entityBinding) { - for ( ConstraintSource constraintSource : entitySource.getConstraints() ) { - if ( constraintSource instanceof UniqueConstraintSource ) { - TableSpecification table = entityBinding.locateTable( constraintSource.getTableName() ); - if ( table == null ) { - // throw exception !? - } - String constraintName = constraintSource.name(); - if ( constraintName == null ) { - // create a default name - } - - UniqueKey uniqueKey = table.getOrCreateUniqueKey( constraintName ); - for ( String columnName : constraintSource.columnNames() ) { - uniqueKey.addColumn( table.locateOrCreateColumn( quoteIdentifier( columnName ) ) ); - } - } - } - } - - private void bindRelationalValues( - RelationalValueSourceContainer relationalValueSourceContainer, - SingularAttributeBinding attributeBinding) { - - List valueBindings = new ArrayList(); - - if ( !relationalValueSourceContainer.relationalValueSources().isEmpty() ) { - for ( RelationalValueSource valueSource : relationalValueSourceContainer.relationalValueSources() ) { - final TableSpecification table = attributeBinding.getContainer() - .seekEntityBinding() - .locateTable( valueSource.getContainingTableName() ); - - if ( ColumnSource.class.isInstance( valueSource ) ) { - final ColumnSource columnSource = ColumnSource.class.cast( valueSource ); - final Column column = makeColumn( (ColumnSource) valueSource, table ); - valueBindings.add( - new SimpleValueBinding( - column, - columnSource.isIncludedInInsert(), - columnSource.isIncludedInUpdate() - ) - ); - } - else { - valueBindings.add( - new SimpleValueBinding( - makeDerivedValue( ( (DerivedValueSource) valueSource ), table ) - ) - ); - } - } - } - else { - String name = metadata.getOptions() - .getNamingStrategy() - .propertyToColumnName( attributeBinding.getAttribute().getName() ); - name = quoteIdentifier( name ); - Column column = attributeBinding.getContainer() - .seekEntityBinding() - .getPrimaryTable() - .locateOrCreateColumn( name ); - column.setNullable( relationalValueSourceContainer.areValuesNullableByDefault() ); - valueBindings.add( - new SimpleValueBinding( - column, - relationalValueSourceContainer.areValuesIncludedInInsertByDefault(), - relationalValueSourceContainer.areValuesIncludedInUpdateByDefault() - ) - ); - } - attributeBinding.setSimpleValueBindings( valueBindings ); - } - - private String quoteIdentifier(String identifier) { - return currentBindingContext.isGloballyQuotedIdentifiers() ? StringHelper.quote( identifier ) : identifier; - } - - private SimpleValue makeSimpleValue( - EntityBinding entityBinding, - RelationalValueSource valueSource) { - final TableSpecification table = entityBinding.locateTable( valueSource.getContainingTableName() ); - - if ( ColumnSource.class.isInstance( valueSource ) ) { - return makeColumn( (ColumnSource) valueSource, table ); - } - else { - return makeDerivedValue( (DerivedValueSource) valueSource, table ); - } - } - - private Column makeColumn(ColumnSource columnSource, TableSpecification table) { - String name = columnSource.getName(); - name = metadata.getOptions().getNamingStrategy().columnName( name ); - name = quoteIdentifier( name ); - final Column column = table.locateOrCreateColumn( name ); - column.setNullable( columnSource.isNullable() ); - column.setDefaultValue( columnSource.getDefaultValue() ); - column.setSqlType( columnSource.getSqlType() ); - column.setSize( columnSource.getSize() ); - column.setDatatype( columnSource.getDatatype() ); - column.setReadFragment( columnSource.getReadFragment() ); - column.setWriteFragment( columnSource.getWriteFragment() ); - column.setUnique( columnSource.isUnique() ); - column.setCheckCondition( columnSource.getCheckCondition() ); - column.setComment( columnSource.getComment() ); - return column; - } - - private DerivedValue makeDerivedValue(DerivedValueSource derivedValueSource, TableSpecification table) { - return table.locateOrCreateDerivedValue( derivedValueSource.getExpression() ); - } - - private void processFetchProfiles(EntitySource entitySource, EntityBinding entityBinding) { - // todo : process the entity-local fetch-profile declaration - } - - private static class AttributeJavaTypeDeterminerDelegate implements BeanInfoHelper.BeanInfoDelegate { - private final String attributeName; - private Class javaType = null; - - private AttributeJavaTypeDeterminerDelegate(String attributeName) { - this.attributeName = attributeName; - } - - @Override - public void processBeanInfo(BeanInfo beanInfo) throws Exception { - for ( PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors() ) { - if ( propertyDescriptor.getName().equals( attributeName ) ) { - javaType = propertyDescriptor.getPropertyType(); - break; - } - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java deleted file mode 100644 index 3f86bd6b0f1c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; - -/** - * Contract for source information pertaining to a column definition. - * - * @author Steve Ebersole - */ -public interface ColumnSource extends RelationalValueSource { - /** - * Obtain the name of the column. - * - * @return The name of the column. Can be {@code null}, in which case a naming strategy is applied. - */ - public String getName(); - - /** - * A SQL fragment to apply to the column value on read. - * - * @return The SQL read fragment - */ - public String getReadFragment(); - - /** - * A SQL fragment to apply to the column value on write. - * - * @return The SQL write fragment - */ - public String getWriteFragment(); - - /** - * Is this column nullable? - * - * @return {@code true} indicates it is nullable; {@code false} non-nullable. - */ - public boolean isNullable(); - - /** - * Obtain a specified default value for the column - * - * @return THe column default - */ - public String getDefaultValue(); - - /** - * Obtain the free-hand definition of the column's type. - * - * @return The free-hand column type - */ - public String getSqlType(); - - /** - * The deduced (and dialect convertible) type for this column - * - * @return The column's SQL data type. - */ - public Datatype getDatatype(); - - /** - * Obtain the specified column size. - * - * @return The column size. - */ - public Size getSize(); - - /** - * Is this column unique? - * - * @return {@code true} indicates it is unique; {@code false} non-unique. - */ - public boolean isUnique(); - - /** - * Obtain the specified check constraint condition - * - * @return Check constraint condition - */ - public String getCheckCondition(); - - /** - * Obtain the specified SQL comment - * - * @return SQL comment - */ - public String getComment(); - - public boolean isIncludedInInsert(); - - public boolean isIncludedInUpdate(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentAttributeSource.java deleted file mode 100644 index a4804893970a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentAttributeSource.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.internal.util.ValueHolder; - -/** - * @author Steve Ebersole - */ -public interface ComponentAttributeSource extends SingularAttributeSource, AttributeSourceContainer { - public String getClassName(); - - public ValueHolder> getClassReference(); - - public String getParentReferenceAttributeName(); - - public String getExplicitTuplizerClassName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentIdentifierSource.java deleted file mode 100644 index feb396751cc2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ComponentIdentifierSource.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.binder; - -/** - * @author Strong Liu - */ -public interface ComponentIdentifierSource extends IdentifierSource { - /** - * Obtain the source descriptor for the identifier attribute. - * - * @return The identifier attribute source. - */ - public ComponentAttributeSource getIdentifierAttributeSource(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/CompositePluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/CompositePluralAttributeElementSource.java deleted file mode 100644 index 0965d93fc88e..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/CompositePluralAttributeElementSource.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.internal.util.ValueHolder; - -/** - * @author Steve Ebersole - */ -public interface CompositePluralAttributeElementSource extends PluralAttributeElementSource, AttributeSourceContainer { - public String getClassName(); - - public ValueHolder> getClassReference(); - - public String getParentReferenceAttributeName(); - - public String getExplicitTuplizerClassName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntityHierarchy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntityHierarchy.java deleted file mode 100644 index fdfdf9ec4f89..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntityHierarchy.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.metamodel.binding.InheritanceType; - -/** - * Models the source-agnostic view of an entity hierarchy. - * - * @author Steve Ebersole - */ -public interface EntityHierarchy { - /** - * The inheritance type/strategy for the hierarchy. - *

      - * NOTE : The entire hierarchy must comply with the same inheritance strategy. - * - * @return The inheritance type. - */ - public InheritanceType getHierarchyInheritanceType(); - - /** - * Obtain the hierarchy's root entity. - * - * @return THe root entity. - */ - public RootEntitySource getRootEntitySource(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ExplicitHibernateTypeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ExplicitHibernateTypeSource.java deleted file mode 100644 index c64fb0789cf9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ExplicitHibernateTypeSource.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.util.Map; - -/** - * Source-agnostic descriptor for explicit user-supplied Hibernate type information - * - * @author Steve Ebersole - */ -public interface ExplicitHibernateTypeSource { - /** - * Obtain the supplied Hibernate type name. - * - * @return The Hibernate type name - */ - public String getName(); - - /** - * Obtain any supplied Hibernate type parameters. - * - * @return The Hibernate type parameters. - */ - public Map getParameters(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/IdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/IdentifierSource.java deleted file mode 100644 index fe9a33d8e701..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/IdentifierSource.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.metamodel.binding.IdGenerator; - -/** - * Contract describing source of identifier information for the entity. - * - * @author Steve Ebersole - */ -public interface IdentifierSource { - /** - * Obtain the identifier generator source. - * - * @return The generator source. - */ - IdGenerator getIdentifierGeneratorDescriptor(); - - public static enum Nature { - /** - * A single, simple identifier. Equivalent of an {@code } mapping or a single {@code @Id} - * annotation. Indicates the {@link IdentifierSource} is castable to {@link SimpleIdentifierSource}. - */ - SIMPLE, - - /** - * What we used to term an "embedded composite identifier", which is not to be confused with the JPA - * term embedded. Specifically a composite id where there is no component class, though there may be an - * {@code @IdClass}. - */ - COMPOSITE, - - /** - * Composite identifier with an actual component class used to aggregate the individual attributes - */ - AGGREGATED_COMPOSITE - } - - /** - * Obtain the nature of this identifier source. - * - * @return The identifier source's nature. - */ - public Nature getNature(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/JpaCallbackClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/JpaCallbackClass.java deleted file mode 100644 index 5101befc4a91..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/JpaCallbackClass.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import javax.persistence.Entity; -import javax.persistence.EntityListeners; -import javax.persistence.MappedSuperclass; -import javax.persistence.PostLoad; -import javax.persistence.PostPersist; -import javax.persistence.PostRemove; -import javax.persistence.PostUpdate; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; -import javax.persistence.PreUpdate; - -public interface JpaCallbackClass { - - /** - * @param callbackType {@link PrePersist}, {@link PreRemove}, {@link PreUpdate}, {@link PostLoad}, - * {@link PostPersist}, {@link PostRemove}, or {@link PostUpdate} - * @return the name of the JPA callback method defined for the associated {@link Entity entity} or {@link MappedSuperclass - * mapped superclass} and for the supplied callback annotation class. - */ - String getCallbackMethod(Class callbackType); - - /** - * @return the name of the instantiated container where the JPA callbacks for the associated {@link Entity entity} or - * {@link MappedSuperclass mapped superclass} are defined. This can be either the entity/mapped superclass itself or an - * {@link EntityListeners entity listener}. - */ - String getName(); - - /** - * @return true if this callback class represents callbacks defined within an {@link EntityListeners entity - * listener}. - */ - boolean isListener(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToAnyPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToAnyPluralAttributeElementSource.java deleted file mode 100644 index 89d49a8a056b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToAnyPluralAttributeElementSource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * @author Steve Ebersole - */ -public interface ManyToAnyPluralAttributeElementSource extends PluralAttributeElementSource { -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToManyPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToManyPluralAttributeElementSource.java deleted file mode 100644 index e1c9cfb8aede..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ManyToManyPluralAttributeElementSource.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.util.List; - -import org.hibernate.FetchMode; - -/** - * @author Steve Ebersole - */ -public interface ManyToManyPluralAttributeElementSource extends PluralAttributeElementSource { - public String getReferencedEntityName(); - public String getReferencedEntityAttributeName(); - - public List getValueSources(); // these describe the "outgoing" link - - public boolean isNotFoundAnException(); - public String getExplicitForeignKeyName(); - public boolean isUnique(); - - public String getOrderBy(); - public String getWhere(); - - public FetchMode getFetchMode(); - public boolean fetchImmediately(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/MetaAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/MetaAttributeSource.java deleted file mode 100644 index ab44fc4a23d6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/MetaAttributeSource.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * Describes incoming {@link org.hibernate.mapping.MetaAttribute} values. This is only from {@code hbm} via the - * {@code } element(s). - * - * @author Steve Ebersole - */ -public interface MetaAttributeSource { - /** - * Obtain the supplied meta-attribute name - * - * @return The meta-attribute name - */ - public String getName(); - - /** - * Obtain the supplied meta-attribute value. - * - * @return The meta-attribute value - */ - public String getValue(); - - /** - * Is the meta-attribute value inheritable? - * - * @return Is the value inheritable? - */ - public boolean isInheritable(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/OneToManyPluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/OneToManyPluralAttributeElementSource.java deleted file mode 100644 index aecc755706a5..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/OneToManyPluralAttributeElementSource.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * @author Steve Ebersole - */ -public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource { - public String getReferencedEntityName(); - public boolean isNotFoundAnException(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Orderable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Orderable.java deleted file mode 100644 index 115f67aef9f7..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Orderable.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * @author Steve Ebersole - */ -public interface Orderable { - public boolean isOrdered(); - public String getOrder(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementNature.java deleted file mode 100644 index 0e063a3b90f2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementNature.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * Describes the nature of the collection elements as declared by the metadata. - * - * @author Steve Ebersole - */ -public enum PluralAttributeElementNature { - BASIC, - COMPONENT, - ONE_TO_MANY, - MANY_TO_MANY, - MANY_TO_ANY -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeKeySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeKeySource.java deleted file mode 100644 index 815a7828fa95..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeKeySource.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.util.List; - -import org.hibernate.metamodel.relational.ForeignKey; - -/** - * @author Steve Ebersole - */ -public interface PluralAttributeKeySource { - public List getValueSources(); - public String getExplicitForeignKeyName(); - public ForeignKey.ReferentialAction getOnDeleteAction(); - public String getReferencedEntityAttributeName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeNature.java deleted file mode 100644 index 9c766e0735c8..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeNature.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Describes the nature of the collection itself as declared by the metadata. - * - * @author Steve Ebersole - */ -public enum PluralAttributeNature { - BAG( Collection.class ), - ID_BAG( Collection.class ), - SET( Set.class ), - LIST( List.class ), - MAP( Map.class ); - - private final Class reportedJavaType; - - PluralAttributeNature(Class reportedJavaType) { - this.reportedJavaType = reportedJavaType; - } - - public Class reportedJavaType() { - return reportedJavaType; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeSource.java deleted file mode 100644 index 2f19b86b6191..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeSource.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.CustomSQL; - -/** - * @author Steve Ebersole - */ -public interface PluralAttributeSource extends AssociationAttributeSource { - public PluralAttributeNature getPluralAttributeNature(); - - public PluralAttributeKeySource getKeySource(); - - public PluralAttributeElementSource getElementSource(); - - public String getExplicitSchemaName(); - public String getExplicitCatalogName(); - public String getExplicitCollectionTableName(); - - public String getCollectionTableComment(); - public String getCollectionTableCheck(); - - public Caching getCaching(); - - /** - * Obtain the name of a custom persister class to be used. - * - * @return The custom persister class name - */ - public String getCustomPersisterClassName(); - - public String getWhere(); - - public boolean isInverse(); - - public String getCustomLoaderName(); - - public CustomSQL getCustomSqlInsert(); - - public CustomSQL getCustomSqlUpdate(); - - public CustomSQL getCustomSqlDelete(); - - public CustomSQL getCustomSqlDeleteAll(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSource.java deleted file mode 100644 index 8fd839220a50..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSource.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * Unifying interface for {@link ColumnSource} and {@link DerivedValueSource}. - * - * @author Steve Ebersole - * @see ColumnSource - * @see DerivedValueSource - */ -public interface RelationalValueSource { - /** - * @return returns the name of the table that contains this value. - */ - public String getContainingTableName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSourceContainer.java deleted file mode 100644 index 5a167f44e047..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RelationalValueSourceContainer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import java.util.List; - -/** - * Contract for a container of {@link RelationalValueSource} references. - * - * @author Steve Ebersole - */ -public interface RelationalValueSourceContainer { - public boolean areValuesIncludedInInsertByDefault(); - - public boolean areValuesIncludedInUpdateByDefault(); - - public boolean areValuesNullableByDefault(); - - /** - * Obtain the contained {@link RelationalValueSource} references. - * - * @return The contained {@link RelationalValueSource} references. - */ - public List relationalValueSources(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RootEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RootEntitySource.java deleted file mode 100644 index 6d18eccd02b4..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/RootEntitySource.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.EntityMode; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.metamodel.binding.Caching; - -/** - * Contract for the entity that is the root of an inheritance hierarchy. - *

      - * NOTE : I think most of this could be moved to {@link EntityHierarchy} much like was done with - * {@link org.hibernate.metamodel.binding.HierarchyDetails} - * - * @author Steve Ebersole - * - * @todo Move these concepts to {@link EntityHierarchy} ? - */ -public interface RootEntitySource extends EntitySource { - /** - * Obtain source information about this entity's identifier. - * - * @return Identifier source information. - */ - public IdentifierSource getIdentifierSource(); - - /** - * Obtain the source information about the attribute used for versioning. - * - * @return the source information about the attribute used for versioning - */ - public SingularAttributeSource getVersioningAttributeSource(); - - /** - * Obtain the source information about the discriminator attribute for single table inheritance - * - * @return the source information about the discriminator attribute for single table inheritance - */ - public DiscriminatorSource getDiscriminatorSource(); - - /** - * Obtain the entity mode for this entity. - * - * @return The entity mode. - */ - public EntityMode getEntityMode(); - - /** - * Is this root entity mutable? - * - * @return {@code true} indicates mutable; {@code false} non-mutable. - */ - public boolean isMutable(); - - /** - * Should explicit polymorphism (querying) be applied to this entity? - * - * @return {@code true} indicates explicit polymorphism; {@code false} implicit. - */ - public boolean isExplicitPolymorphism(); - - /** - * Obtain the specified extra where condition to be applied to this entity. - * - * @return The extra where condition - */ - public String getWhere(); - - /** - * Obtain the row-id name for this entity - * - * @return The row-id name - */ - public String getRowId(); - - /** - * Obtain the optimistic locking style for this entity. - * - * @return The optimistic locking style. - */ - public OptimisticLockStyle getOptimisticLockStyle(); - - /** - * Obtain the caching configuration for this entity. - * - * @return The caching configuration. - */ - public Caching getCaching(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeSource.java deleted file mode 100644 index 33978afb0f84..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeSource.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -import org.hibernate.mapping.PropertyGeneration; - -/** - * Source-agnostic description of information needed to bind a singular attribute. - * - * @author Steve Ebersole - */ -public interface SingularAttributeSource extends AttributeSource, RelationalValueSourceContainer { - /** - * Determine whether this is a virtual attribute or whether it physically exists on the users domain model. - * - * @return {@code true} indicates the attribute is virtual, meaning it does NOT exist on the domain model; - * {@code false} indicates the attribute physically exists. - */ - public boolean isVirtualAttribute(); - - /** - * Obtain the nature of this attribute type. - * - * @return The attribute type nature - */ - public SingularAttributeNature getNature(); - - /** - * Determine whether this attribute is insertable. - * - * @return {@code true} indicates the attribute value should be used in the {@code SQL INSERT}; {@code false} - * indicates it should not. - */ - public boolean isInsertable(); - - /** - * Determine whether this attribute is updateable. - * - * @return {@code true} indicates the attribute value should be used in the {@code SQL UPDATE}; {@code false} - * indicates it should not. - */ - public boolean isUpdatable(); - - /** - * Obtain a description of if/when the attribute value is generated by the database. - * - * @return The attribute value generation information - */ - public PropertyGeneration getGeneration(); - - /** - * Should the attribute be (bytecode enhancement) lazily loaded? - * - * @return {@code true} to indicate the attribute should be lazily loaded. - */ - public boolean isLazy(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Sortable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Sortable.java deleted file mode 100644 index cba0da79968c..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Sortable.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * @author Steve Ebersole - */ -public interface Sortable { - public boolean isSorted(); - public String getComparatorName(); - -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/TableSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/TableSource.java deleted file mode 100644 index ff18012e2996..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/TableSource.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * Contract describing source of table information - * - * @author Steve Ebersole - */ -public interface TableSource { - /** - * Obtain the supplied schema name - * - * @return The schema name. If {@code null}, the binder will apply the default. - */ - public String getExplicitSchemaName(); - - /** - * Obtain the supplied catalog name - * - * @return The catalog name. If {@code null}, the binder will apply the default. - */ - public String getExplicitCatalogName(); - - /** - * Obtain the supplied table name. - * - * @return The table name. - */ - public String getExplicitTableName(); - - /** - * Obtain the logical name of the table. This value is used to uniquely reference the table when binding - * values to the binding model. - * - * @return The logical name. Can be {@code null} in the case of the "primary table". - * - * @see RelationalValueSource#getContainingTableName() - */ - public String getLogicalName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ToOneAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ToOneAttributeSource.java deleted file mode 100644 index 91d408037d34..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ToOneAttributeSource.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.binder; - -/** - * Further contract for sources of {@code *-to-one} style associations. - * - * @author Steve Ebersole - */ -public interface ToOneAttributeSource extends SingularAttributeSource, AssociationAttributeSource { - /** - * Obtain the name of the referenced entity. - * - * @return The name of the referenced entity - */ - public String getReferencedEntityName(); - - /** - * Obtain the name of the referenced attribute. Typically the reference is built based on the identifier - * attribute of the {@link #getReferencedEntityName() referenced entity}, but this value allows using a different - * attribute instead. - * - * @return The name of the referenced attribute; {@code null} indicates the identifier attribute. - */ - public String getReferencedEntityAttributeName(); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java deleted file mode 100644 index 32877a03853a..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntitySourceImpl.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.hibernate.AssertionFailure; -import org.hibernate.EntityMode; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbAnyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbBagElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbIdbagElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbListElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbMapElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSetElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSynchronizeElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.ConstraintSource; -import org.hibernate.metamodel.source.binder.EntitySource; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public abstract class AbstractEntitySourceImpl implements EntitySource { - private final MappingDocument sourceMappingDocument; - private final EntityElement entityElement; - - private List subclassEntitySources = new ArrayList(); - - protected AbstractEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) { - this.sourceMappingDocument = sourceMappingDocument; - this.entityElement = entityElement; - } - - protected EntityElement entityElement() { - return entityElement; - } - - protected MappingDocument sourceMappingDocument() { - return sourceMappingDocument; - } - - @Override - public Origin getOrigin() { - return sourceMappingDocument.getOrigin(); - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return sourceMappingDocument.getMappingLocalBindingContext(); - } - - @Override - public String getEntityName() { - return StringHelper.isNotEmpty( entityElement.getEntityName() ) - ? entityElement.getEntityName() - : getClassName(); - } - - @Override - public String getClassName() { - return getLocalBindingContext().qualifyClassName( entityElement.getName() ); - } - - @Override - public String getJpaEntityName() { - return null; - } - - @Override - public boolean isAbstract() { - return Helper.getBooleanValue( entityElement.isAbstract(), false ); - } - - @Override - public boolean isLazy() { - return Helper.getBooleanValue( entityElement.isAbstract(), true ); - } - - @Override - public String getProxy() { - return entityElement.getProxy(); - } - - @Override - public int getBatchSize() { - return Helper.getIntValue( entityElement.getBatchSize(), -1 ); - } - - @Override - public boolean isDynamicInsert() { - return entityElement.isDynamicInsert(); - } - - @Override - public boolean isDynamicUpdate() { - return entityElement.isDynamicUpdate(); - } - - @Override - public boolean isSelectBeforeUpdate() { - return entityElement.isSelectBeforeUpdate(); - } - - protected EntityMode determineEntityMode() { - return StringHelper.isNotEmpty( getClassName() ) ? EntityMode.POJO : EntityMode.MAP; - } - - @Override - public String getCustomTuplizerClassName() { - if ( entityElement.getTuplizer() == null ) { - return null; - } - final EntityMode entityMode = determineEntityMode(); - for ( JaxbTuplizerElement tuplizerElement : entityElement.getTuplizer() ) { - if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode() ) ) { - return tuplizerElement.getClazz(); - } - } - return null; - } - - @Override - public String getCustomPersisterClassName() { - return getLocalBindingContext().qualifyClassName( entityElement.getPersister() ); - } - - @Override - public String getCustomLoaderName() { - return entityElement.getLoader() != null ? entityElement.getLoader().getQueryRef() : null; - } - - @Override - public CustomSQL getCustomSqlInsert() { - return Helper.buildCustomSql( entityElement.getSqlInsert() ); - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return Helper.buildCustomSql( entityElement.getSqlUpdate() ); - } - - @Override - public CustomSQL getCustomSqlDelete() { - return Helper.buildCustomSql( entityElement.getSqlDelete() ); - } - - @Override - public List getSynchronizedTableNames() { - List tableNames = new ArrayList(); - for ( JaxbSynchronizeElement synchronizeElement : entityElement.getSynchronize() ) { - tableNames.add( synchronizeElement.getTable() ); - } - return tableNames; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( entityElement.getMeta() ); - } - - @Override - public String getPath() { - return sourceMappingDocument.getMappingLocalBindingContext().determineEntityName( entityElement ); - } - - @Override - public Iterable attributeSources() { - List attributeSources = new ArrayList(); - for ( Object attributeElement : entityElement.getPropertyOrManyToOneOrOneToOne() ) { - if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new PropertyAttributeSourceImpl( - JaxbPropertyElement.class.cast( attributeElement ), - sourceMappingDocument().getMappingLocalBindingContext() - ) - ); - } - else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ComponentAttributeSourceImpl( - (JaxbComponentElement) attributeElement, - this, - sourceMappingDocument.getMappingLocalBindingContext() - ) - ); - } - else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ManyToOneAttributeSourceImpl( - JaxbManyToOneElement.class.cast( attributeElement ), - sourceMappingDocument().getMappingLocalBindingContext() - ) - ); - } - else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbBagElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new BagAttributeSourceImpl( - JaxbBagElement.class.cast( attributeElement ), - this - ) - ); - } - else if ( JaxbIdbagElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbSetElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new SetAttributeSourceImpl( - JaxbSetElement.class.cast( attributeElement ), - this - ) - ); - } - else if ( JaxbListElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbMapElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else { - throw new AssertionFailure( "Unexpected attribute element type encountered : " + attributeElement.getClass() ); - } - } - return attributeSources; - } - - private EntityHierarchyImpl entityHierarchy; - - public void injectHierarchy(EntityHierarchyImpl entityHierarchy) { - this.entityHierarchy = entityHierarchy; - } - - @Override - public void add(SubclassEntitySource subclassEntitySource) { - add( (SubclassEntitySourceImpl) subclassEntitySource ); - } - - public void add(SubclassEntitySourceImpl subclassEntitySource) { - entityHierarchy.processSubclass( subclassEntitySource ); - subclassEntitySources.add( subclassEntitySource ); - } - - @Override - public Iterable subclassEntitySources() { - return subclassEntitySources; - } - - @Override - public String getDiscriminatorMatchValue() { - return null; - } - - @Override - public Iterable getConstraints() { - return Collections.emptySet(); - } - - @Override - public Iterable getSecondaryTables() { - return Collections.emptySet(); - } - - @Override - public List getJpaCallbackClasses() { - return Collections.EMPTY_LIST; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractPluralAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractPluralAttributeSourceImpl.java deleted file mode 100644 index c39dfc0833fc..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractPluralAttributeSourceImpl.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.Collections; -import java.util.Map; - -import org.hibernate.FetchMode; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbCacheElement; -import org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeKeySource; -import org.hibernate.metamodel.source.binder.PluralAttributeSource; - -/** - * @author Steve Ebersole - */ -public abstract class AbstractPluralAttributeSourceImpl implements PluralAttributeSource { - private final PluralAttributeElement pluralAttributeElement; - private final AttributeSourceContainer container; - - private final ExplicitHibernateTypeSource typeInformation; - - private final PluralAttributeKeySource keySource; - private final PluralAttributeElementSource elementSource; - - protected AbstractPluralAttributeSourceImpl( - final PluralAttributeElement pluralAttributeElement, - AttributeSourceContainer container) { - this.pluralAttributeElement = pluralAttributeElement; - this.container = container; - - this.keySource = new PluralAttributeKeySourceImpl( pluralAttributeElement.getKey(), container ); - this.elementSource = interpretElementType(); - - this.typeInformation = new ExplicitHibernateTypeSource() { - @Override - public String getName() { - return pluralAttributeElement.getCollectionType(); - } - - @Override - public Map getParameters() { - return Collections.emptyMap(); - } - }; - } - - private PluralAttributeElementSource interpretElementType() { - if ( pluralAttributeElement.getElement() != null ) { - return new BasicPluralAttributeElementSourceImpl( - pluralAttributeElement.getElement(), container.getLocalBindingContext() - ); - } - else if ( pluralAttributeElement.getCompositeElement() != null ) { - return new CompositePluralAttributeElementSourceImpl( - pluralAttributeElement.getCompositeElement(), container.getLocalBindingContext() - ); - } - else if ( pluralAttributeElement.getOneToMany() != null ) { - return new OneToManyPluralAttributeElementSourceImpl( - pluralAttributeElement.getOneToMany(), container.getLocalBindingContext() - ); - } - else if ( pluralAttributeElement.getManyToMany() != null ) { - return new ManyToManyPluralAttributeElementSourceImpl( - pluralAttributeElement.getManyToMany(), container.getLocalBindingContext() - ); - } - else if ( pluralAttributeElement.getManyToAny() != null ) { - throw new NotYetImplementedException( "Support for many-to-any not yet implemented" ); -// return PluralAttributeElementNature.MANY_TO_ANY; - } - else { - throw new MappingException( - "Unexpected collection element type : " + pluralAttributeElement.getName(), - bindingContext().getOrigin() - ); - } - } - - public PluralAttributeElement getPluralAttributeElement() { - return pluralAttributeElement; - } - - protected AttributeSourceContainer container() { - return container; - } - - protected LocalBindingContext bindingContext() { - return container().getLocalBindingContext(); - } - - @Override - public PluralAttributeKeySource getKeySource() { - return keySource; - } - - @Override - public PluralAttributeElementSource getElementSource() { - return elementSource; - } - - @Override - public String getExplicitSchemaName() { - return pluralAttributeElement.getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return pluralAttributeElement.getCatalog(); - } - - @Override - public String getExplicitCollectionTableName() { - return pluralAttributeElement.getTable(); - } - - @Override - public String getCollectionTableComment() { - return pluralAttributeElement.getComment(); - } - - @Override - public String getCollectionTableCheck() { - return pluralAttributeElement.getCheck(); - } - - @Override - public Caching getCaching() { - final JaxbCacheElement cache = pluralAttributeElement.getCache(); - if ( cache == null ) { - return null; - } - final String region = cache.getRegion() != null - ? cache.getRegion() - : StringHelper.qualify( container().getPath(), getName() ); - final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() ); - final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() ); - return new Caching( region, accessType, cacheLazyProps ); - } - - @Override - public String getWhere() { - return pluralAttributeElement.getWhere(); - } - - @Override - public String getName() { - return pluralAttributeElement.getName(); - } - - @Override - public boolean isSingular() { - return false; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return typeInformation; - } - - @Override - public String getPropertyAccessorName() { - return pluralAttributeElement.getAccess(); - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return pluralAttributeElement.isOptimisticLock(); - } - - @Override - public boolean isInverse() { - return pluralAttributeElement.isInverse(); - } - - @Override - public String getCustomPersisterClassName() { - return pluralAttributeElement.getPersister(); - } - - @Override - public String getCustomLoaderName() { - return pluralAttributeElement.getLoader() == null - ? null - : pluralAttributeElement.getLoader().getQueryRef(); - } - - @Override - public CustomSQL getCustomSqlInsert() { - return Helper.buildCustomSql( pluralAttributeElement.getSqlInsert() ); - } - - @Override - public CustomSQL getCustomSqlUpdate() { - return Helper.buildCustomSql( pluralAttributeElement.getSqlUpdate() ); - } - - @Override - public CustomSQL getCustomSqlDelete() { - return Helper.buildCustomSql( pluralAttributeElement.getSqlDelete() ); - } - - @Override - public CustomSQL getCustomSqlDeleteAll() { - return Helper.buildCustomSql( pluralAttributeElement.getSqlDeleteAll() ); - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( pluralAttributeElement.getMeta() ); - } - - @Override - public Iterable getCascadeStyles() { - return Helper.interpretCascadeStyles( pluralAttributeElement.getCascade(), bindingContext() ); - } - - @Override - public FetchTiming getFetchTiming() { - final String fetchSelection = pluralAttributeElement.getFetch() != null ? - pluralAttributeElement.getFetch().value() : - null; - final String lazySelection = pluralAttributeElement.getLazy() != null - ? pluralAttributeElement.getLazy().value() - : null; - final String outerJoinSelection = pluralAttributeElement.getOuterJoin() != null - ? pluralAttributeElement.getOuterJoin().value() - : null; - - if ( lazySelection == null ) { - if ( "join".equals( fetchSelection ) || "true".equals( outerJoinSelection ) ) { - return FetchTiming.IMMEDIATE; - } - else if ( "false".equals( outerJoinSelection ) ) { - return FetchTiming.DELAYED; - } - else { - return bindingContext().getMappingDefaults().areAssociationsLazy() - ? FetchTiming.DELAYED - : FetchTiming.IMMEDIATE; - } - } - else if ( "extra".equals( lazySelection ) ) { - return FetchTiming.EXTRA_LAZY; - } - else if ( "true".equals( lazySelection ) ) { - return FetchTiming.DELAYED; - } - else if ( "false".equals( lazySelection ) ) { - return FetchTiming.IMMEDIATE; - } - - throw new MappingException( - String.format( - "Unexpected lazy selection [%s] on '%s'", - lazySelection, - pluralAttributeElement.getName() - ), - bindingContext().getOrigin() - ); - } - - @Override - public FetchStyle getFetchStyle() { - final String fetchSelection = pluralAttributeElement.getFetch() != null ? - pluralAttributeElement.getFetch().value() : - null; - final String outerJoinSelection = pluralAttributeElement.getOuterJoin() != null - ? pluralAttributeElement.getOuterJoin().value() - : null; - final int batchSize = Helper.getIntValue( pluralAttributeElement.getBatchSize(), -1 ); - - if ( fetchSelection == null ) { - if ( outerJoinSelection == null ) { - return batchSize > 1 ? FetchStyle.BATCH : FetchStyle.SELECT; - } - else { - if ( "auto".equals( outerJoinSelection ) ) { - return bindingContext().getMappingDefaults().areAssociationsLazy() - ? FetchStyle.SELECT - : FetchStyle.JOIN; - } - else { - return "true".equals( outerJoinSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; - } - } - } - else { - if ( "subselect".equals( fetchSelection ) ) { - return FetchStyle.SUBSELECT; - } - else { - return "join".equals( fetchSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; - } - } - } - - @Override - public FetchMode getFetchMode() { - return pluralAttributeElement.getFetch() == null - ? FetchMode.DEFAULT - : FetchMode.valueOf( pluralAttributeElement.getFetch().value() ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BagAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BagAttributeSourceImpl.java deleted file mode 100644 index 4c29db82ab2b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BagAttributeSourceImpl.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbBagElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.Orderable; -import org.hibernate.metamodel.source.binder.PluralAttributeNature; - -/** - * @author Steve Ebersole - */ -public class BagAttributeSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable { - public BagAttributeSourceImpl(JaxbBagElement bagElement, AttributeSourceContainer container) { - super( bagElement, container ); - } - - @Override - public PluralAttributeNature getPluralAttributeNature() { - return PluralAttributeNature.BAG; - } - - @Override - public JaxbBagElement getPluralAttributeElement() { - return (JaxbBagElement) super.getPluralAttributeElement(); - } - - @Override - public boolean isOrdered() { - return StringHelper.isNotEmpty( getOrder() ); - } - - @Override - public String getOrder() { - return getPluralAttributeElement().getOrderBy(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BasicPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BasicPluralAttributeElementSourceImpl.java deleted file mode 100644 index 355117b0c576..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/BasicPluralAttributeElementSourceImpl.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbElementElement; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.BasicPluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; -import org.hibernate.metamodel.source.binder.RelationalValueSource; - -/** - * @author Steve Ebersole - */ -public class BasicPluralAttributeElementSourceImpl implements BasicPluralAttributeElementSource { - private final List valueSources; - private final ExplicitHibernateTypeSource typeSource; - - public BasicPluralAttributeElementSourceImpl( - final JaxbElementElement elementElement, - LocalBindingContext bindingContext) { - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getContainingTableName() { - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return true; - } - - @Override - public String getColumnAttribute() { - return elementElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return elementElement.getFormula(); - } - - @Override - public List getColumnOrFormulaElements() { - return elementElement.getColumnOrFormula(); - } - }, - bindingContext - ); - - this.typeSource = new ExplicitHibernateTypeSource() { - @Override - public String getName() { - if ( elementElement.getTypeAttribute() != null ) { - return elementElement.getTypeAttribute(); - } - else if ( elementElement.getType() != null ) { - return elementElement.getType().getName(); - } - else { - return null; - } - } - - @Override - public Map getParameters() { - return elementElement.getType() != null - ? Helper.extractParameters( elementElement.getType().getParam() ) - : java.util.Collections.emptyMap(); - } - }; - } - - @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.BASIC; - } - - @Override - public List getValueSources() { - return valueSources; - } - - @Override - public ExplicitHibernateTypeSource getExplicitHibernateTypeSource() { - return typeSource; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnAttributeSourceImpl.java deleted file mode 100644 index 664215c030e9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnAttributeSourceImpl.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; - -/** -* @author Steve Ebersole -*/ -class ColumnAttributeSourceImpl implements ColumnSource { - private final String tableName; - private final String columnName; - private boolean includedInInsert; - private boolean includedInUpdate; - private boolean isForceNotNull; - - ColumnAttributeSourceImpl( - String tableName, - String columnName, - boolean includedInInsert, - boolean includedInUpdate) { - this(tableName, columnName, includedInInsert, includedInUpdate, false); - } - - ColumnAttributeSourceImpl( - String tableName, - String columnName, - boolean includedInInsert, - boolean includedInUpdate, - boolean isForceNotNull) { - this.tableName = tableName; - this.columnName = columnName; - this.includedInInsert = includedInInsert; - this.includedInUpdate = includedInUpdate; - this.isForceNotNull = isForceNotNull; - } - - @Override - public boolean isIncludedInInsert() { - return includedInInsert; - } - - @Override - public boolean isIncludedInUpdate() { - return includedInUpdate; - } - - @Override - public String getContainingTableName() { - return tableName; - } - - @Override - public String getName() { - return columnName; - } - - @Override - public boolean isNullable() { - return !isForceNotNull; - } - - @Override - public String getDefaultValue() { - return null; - } - - @Override - public String getSqlType() { - return null; - } - - @Override - public Datatype getDatatype() { - return null; - } - - @Override - public Size getSize() { - return null; - } - - @Override - public String getReadFragment() { - return null; - } - - @Override - public String getWriteFragment() { - return null; - } - - @Override - public boolean isUnique() { - return false; - } - - @Override - public String getCheckCondition() { - return null; - } - - @Override - public String getComment() { - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnSourceImpl.java deleted file mode 100644 index a5cb4737ecc9..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ColumnSourceImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.source.binder.ColumnSource; - -/** -* @author Steve Ebersole -*/ -class ColumnSourceImpl implements ColumnSource { - private final String tableName; - private final JaxbColumnElement columnElement; - private boolean includedInInsert; - private boolean includedInUpdate; - private final boolean isForceNotNull; - - ColumnSourceImpl( - String tableName, - JaxbColumnElement columnElement, - boolean isIncludedInInsert, - boolean isIncludedInUpdate) { - this(tableName, columnElement, isIncludedInInsert, isIncludedInUpdate, false); - } - ColumnSourceImpl( - String tableName, - JaxbColumnElement columnElement, - boolean isIncludedInInsert, - boolean isIncludedInUpdate, - boolean isForceNotNull) { - this.tableName = tableName; - this.columnElement = columnElement; - this.isForceNotNull = isForceNotNull; - includedInInsert = isIncludedInInsert; - includedInUpdate = isIncludedInUpdate; - } - - @Override - public String getName() { - return columnElement.getName(); - } - - @Override - public boolean isNullable() { - if(isForceNotNull)return false; - return ! columnElement.isNotNull(); - } - - @Override - public String getDefaultValue() { - return columnElement.getDefault(); - } - - @Override - public String getSqlType() { - return columnElement.getSqlType(); - } - - @Override - public Datatype getDatatype() { - return null; - } - - @Override - public Size getSize() { - return new Size( - Helper.getIntValue( columnElement.getPrecision(), -1 ), - Helper.getIntValue( columnElement.getScale(), -1 ), - Helper.getLongValue( columnElement.getLength(), -1 ), - Size.LobMultiplier.NONE - ); - } - - @Override - public String getReadFragment() { - return columnElement.getRead(); - } - - @Override - public String getWriteFragment() { - return columnElement.getWrite(); - } - - @Override - public boolean isUnique() { - return columnElement.isUnique(); - } - - @Override - public String getCheckCondition() { - return columnElement.getCheck(); - } - - @Override - public String getComment() { - return columnElement.getComment(); - } - - @Override - public boolean isIncludedInInsert() { - return includedInInsert; - } - - @Override - public boolean isIncludedInUpdate() { - return includedInUpdate; - } - - @Override - public String getContainingTableName() { - return tableName; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java deleted file mode 100644 index b091df0f2f4b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ComponentAttributeSourceImpl.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.EntityMode; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbAnyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToManyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToManyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToOneElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.ComponentAttributeSource; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; - -/** - * @author Steve Ebersole - */ -public class ComponentAttributeSourceImpl implements ComponentAttributeSource { - private final JaxbComponentElement componentElement; - private final AttributeSourceContainer parentContainer; - - private final ValueHolder> componentClassReference; - private final String path; - - public ComponentAttributeSourceImpl( - JaxbComponentElement componentElement, - AttributeSourceContainer parentContainer, - LocalBindingContext bindingContext) { - this.componentElement = componentElement; - this.parentContainer = parentContainer; - - this.componentClassReference = bindingContext.makeClassReference( - bindingContext.qualifyClassName( componentElement.getClazz() ) - ); - this.path = parentContainer.getPath() + '.' + componentElement.getName(); - } - - @Override - public String getClassName() { - return componentElement.getClazz(); - } - - @Override - public ValueHolder> getClassReference() { - return componentClassReference; - } - - @Override - public String getPath() { - return path; - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return parentContainer.getLocalBindingContext(); - } - - @Override - public String getParentReferenceAttributeName() { - return componentElement.getParent() == null ? null : componentElement.getParent().getName(); - } - - @Override - public String getExplicitTuplizerClassName() { - if ( componentElement.getTuplizer() == null ) { - return null; - } - final EntityMode entityMode = StringHelper.isEmpty( componentElement.getClazz() ) ? EntityMode.MAP : EntityMode.POJO; - for ( JaxbTuplizerElement tuplizerElement : componentElement.getTuplizer() ) { - if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode() ) ) { - return tuplizerElement.getClazz(); - } - } - return null; - } - - @Override - public Iterable attributeSources() { - List attributeSources = new ArrayList(); - for ( Object attributeElement : componentElement.getPropertyOrManyToOneOrOneToOne() ) { - if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new PropertyAttributeSourceImpl( - JaxbPropertyElement.class.cast( attributeElement ), - getLocalBindingContext() - ) - ); - } - else if ( JaxbComponentElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ComponentAttributeSourceImpl( - (JaxbComponentElement) attributeElement, - this, - getLocalBindingContext() - ) - ); - } - else if ( JaxbManyToOneElement.class.isInstance( attributeElement ) ) { - attributeSources.add( - new ManyToOneAttributeSourceImpl( - JaxbManyToOneElement.class.cast( attributeElement ), - getLocalBindingContext() - ) - ); - } - else if ( JaxbOneToOneElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbAnyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbOneToManyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - else if ( JaxbManyToManyElement.class.isInstance( attributeElement ) ) { - // todo : implement - } - } - return attributeSources; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.COMPONENT; - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - // does not support type information. - return null; - } - - @Override - public String getName() { - return componentElement.getName(); - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public String getPropertyAccessorName() { - return componentElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return componentElement.isInsert(); - } - - @Override - public boolean isUpdatable() { - return componentElement.isUpdate(); - } - - @Override - public PropertyGeneration getGeneration() { - // todo : is this correct here? - return null; - } - - @Override - public boolean isLazy() { - return componentElement.isLazy(); - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return componentElement.isOptimisticLock(); - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( componentElement.getMeta() ); - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return isInsertable(); - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return isUpdatable(); - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } - - @Override - public List relationalValueSources() { - // none, they are defined on the simple sub-attributes - return null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java deleted file mode 100644 index 50181f6380a2..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/CompositePluralAttributeElementSourceImpl.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.EntityMode; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbCompositeElementElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.AttributeSource; -import org.hibernate.metamodel.source.binder.CompositePluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; - -/** - * @author Steve Ebersole - */ -public class CompositePluralAttributeElementSourceImpl implements CompositePluralAttributeElementSource { - private final JaxbCompositeElementElement compositeElement; - private final LocalBindingContext bindingContext; - - public CompositePluralAttributeElementSourceImpl( - JaxbCompositeElementElement compositeElement, - LocalBindingContext bindingContext) { - this.compositeElement = compositeElement; - this.bindingContext = bindingContext; - } - - @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.COMPONENT; - } - - @Override - public String getClassName() { - return bindingContext.qualifyClassName( compositeElement.getClazz() ); - } - - @Override - public ValueHolder> getClassReference() { - return bindingContext.makeClassReference( getClassName() ); - } - - @Override - public String getParentReferenceAttributeName() { - return compositeElement.getParent() != null - ? compositeElement.getParent().getName() - : null; - } - - @Override - public String getExplicitTuplizerClassName() { - if ( compositeElement.getTuplizer() == null ) { - return null; - } - final EntityMode entityMode = StringHelper.isEmpty( compositeElement.getClazz() ) ? EntityMode.MAP : EntityMode.POJO; - for ( JaxbTuplizerElement tuplizerElement : compositeElement.getTuplizer() ) { - if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode() ) ) { - return tuplizerElement.getClazz(); - } - } - return null; - } - - @Override - public String getPath() { - // todo : implementing this requires passing in the collection source and being able to resolve the collection's role - return null; - } - - @Override - public Iterable attributeSources() { - List attributeSources = new ArrayList(); - for ( Object attribute : compositeElement.getPropertyOrManyToOneOrAny() ) { - - } - return attributeSources; - } - - @Override - public LocalBindingContext getLocalBindingContext() { - return bindingContext; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/EntityHierarchyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/EntityHierarchyImpl.java deleted file mode 100644 index c3acf22596d5..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/EntityHierarchyImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.RootEntitySource; - -/** - * @author Steve Ebersole - */ -public class EntityHierarchyImpl implements org.hibernate.metamodel.source.binder.EntityHierarchy { - private final RootEntitySourceImpl rootEntitySource; - private InheritanceType hierarchyInheritanceType = InheritanceType.NO_INHERITANCE; - - public EntityHierarchyImpl(RootEntitySourceImpl rootEntitySource) { - this.rootEntitySource = rootEntitySource; - this.rootEntitySource.injectHierarchy( this ); - } - - @Override - public InheritanceType getHierarchyInheritanceType() { - return hierarchyInheritanceType; - } - - @Override - public RootEntitySource getRootEntitySource() { - return rootEntitySource; - } - - public void processSubclass(SubclassEntitySourceImpl subclassEntitySource) { - final InheritanceType inheritanceType = Helper.interpretInheritanceType( subclassEntitySource.entityElement() ); - if ( hierarchyInheritanceType == InheritanceType.NO_INHERITANCE ) { - hierarchyInheritanceType = inheritanceType; - } - else if ( hierarchyInheritanceType != inheritanceType ) { - throw new MappingException( "Mixed inheritance strategies not supported", subclassEntitySource.getOrigin() ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java deleted file mode 100644 index c35775989d30..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmMetadataSourceProcessorImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.MetadataSourceProcessor; -import org.hibernate.metamodel.source.binder.Binder; - -/** - * The {@link org.hibernate.metamodel.source.MetadataSourceProcessor} implementation responsible for processing {@code hbm.xml} sources. - * - * @author Steve Ebersole - */ -public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor { - private final MetadataImplementor metadata; - - private List processors = new ArrayList(); - private List entityHierarchies; - - public HbmMetadataSourceProcessorImpl(MetadataImplementor metadata) { - this.metadata = metadata; - } - - @Override - @SuppressWarnings( {"unchecked"}) - public void prepare(MetadataSources sources) { - final HierarchyBuilder hierarchyBuilder = new HierarchyBuilder(); - - for ( JaxbRoot jaxbRoot : sources.getJaxbRootList() ) { - if ( ! JaxbHibernateMapping.class.isInstance( jaxbRoot.getRoot() ) ) { - continue; - } - - final MappingDocument mappingDocument = new MappingDocument( jaxbRoot, metadata ); - processors.add( new HibernateMappingProcessor( metadata, mappingDocument ) ); - - hierarchyBuilder.processMappingDocument( mappingDocument ); - } - - this.entityHierarchies = hierarchyBuilder.groupEntityHierarchies(); - } - - @Override - public void processIndependentMetadata(MetadataSources sources) { - for ( HibernateMappingProcessor processor : processors ) { - processor.processIndependentMetadata(); - } - } - - @Override - public void processTypeDependentMetadata(MetadataSources sources) { - for ( HibernateMappingProcessor processor : processors ) { - processor.processTypeDependentMetadata(); - } - } - - @Override - public void processMappingMetadata(MetadataSources sources, List processedEntityNames) { - Binder binder = new Binder( metadata, processedEntityNames ); - for ( EntityHierarchyImpl entityHierarchy : entityHierarchies ) { - binder.processEntityHierarchy( entityHierarchy ); - } - } - - @Override - public void processMappingDependentMetadata(MetadataSources sources) { - for ( HibernateMappingProcessor processor : processors ) { - processor.processMappingDependentMetadata(); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java deleted file mode 100644 index aa10976d2624..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/Helper.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.MappingException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbMetaElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbParamElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.binding.MetaAttribute; -import org.hibernate.metamodel.relational.Identifier; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.service.ServiceRegistry; - -/** - * @author Steve Ebersole - * @author Gail Badner - */ -public class Helper { - public static final ExplicitHibernateTypeSource TO_ONE_ATTRIBUTE_TYPE_SOURCE = new ExplicitHibernateTypeSource() { - @Override - public String getName() { - return null; - } - - @Override - public Map getParameters() { - return null; - } - }; - - public static InheritanceType interpretInheritanceType(EntityElement entityElement) { - if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { - return InheritanceType.SINGLE_TABLE; - } - else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { - return InheritanceType.JOINED; - } - else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { - return InheritanceType.TABLE_PER_CLASS; - } - else { - return InheritanceType.NO_INHERITANCE; - } - } - - /** - * Given a user-specified description of how to perform custom SQL, build the {@link CustomSQL} representation. - * - * @param customSqlElement User-specified description of how to perform custom SQL - * - * @return The {@link CustomSQL} representation - */ - public static CustomSQL buildCustomSql(CustomSqlElement customSqlElement) { - if ( customSqlElement == null ) { - return null; - } - final ExecuteUpdateResultCheckStyle checkStyle = customSqlElement.getCheck() == null - ? customSqlElement.isCallable() - ? ExecuteUpdateResultCheckStyle.NONE - : ExecuteUpdateResultCheckStyle.COUNT - : ExecuteUpdateResultCheckStyle.fromExternalName( customSqlElement.getCheck().value() ); - return new CustomSQL( customSqlElement.getValue(), customSqlElement.isCallable(), checkStyle ); - } - - /** - * Given the user-specified entity mapping, determine the appropriate entity name - * - * @param entityElement The user-specified entity mapping - * @param unqualifiedClassPackage The package to use for unqualified class names - * - * @return The appropriate entity name - */ - public static String determineEntityName(EntityElement entityElement, String unqualifiedClassPackage) { - return entityElement.getEntityName() != null - ? entityElement.getEntityName() - : qualifyIfNeeded( entityElement.getName(), unqualifiedClassPackage ); - } - - /** - * Qualify a (supposed class) name with the unqualified-class package name if it is not already qualified - * - * @param name The name - * @param unqualifiedClassPackage The unqualified-class package name - * - * @return {@code null} if the incoming name was {@code null}; or the qualified name. - */ - public static String qualifyIfNeeded(String name, String unqualifiedClassPackage) { - if ( name == null ) { - return null; - } - if ( name.indexOf( '.' ) < 0 && unqualifiedClassPackage != null ) { - return unqualifiedClassPackage + '.' + name; - } - return name; - } - - public static String getPropertyAccessorName(String access, boolean isEmbedded, String defaultAccess) { - return getStringValue( access, isEmbedded ? "embedded" : defaultAccess ); - } - - public static MetaAttributeContext extractMetaAttributeContext( - List metaElementList, - boolean onlyInheritable, - MetaAttributeContext parentContext) { - final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); - - for ( JaxbMetaElement metaElement : metaElementList ) { - if ( onlyInheritable & !metaElement.isInherit() ) { - continue; - } - - final String name = metaElement.getAttribute(); - final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name ); - MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); - if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) { - metaAttribute = new MetaAttribute( name ); - subContext.add( metaAttribute ); - } - metaAttribute.addValue( metaElement.getValue() ); - } - - return subContext; - } - - public static String getStringValue(String value, String defaultValue) { - return value == null ? defaultValue : value; - } - - public static int getIntValue(String value, int defaultValue) { - return value == null ? defaultValue : Integer.parseInt( value ); - } - - public static long getLongValue(String value, long defaultValue) { - return value == null ? defaultValue : Long.parseLong( value ); - } - - public static boolean getBooleanValue(Boolean value, boolean defaultValue) { - return value == null ? defaultValue : value; - } - - public static Iterable interpretCascadeStyles(String cascades, LocalBindingContext bindingContext) { - final Set cascadeStyles = new HashSet(); - if ( StringHelper.isEmpty( cascades ) ) { - cascades = bindingContext.getMappingDefaults().getCascadeStyle(); - } - for ( String cascade : StringHelper.split( ",", cascades ) ) { - cascadeStyles.add( CascadeStyles.getCascadeStyle( cascade ) ); - } - return cascadeStyles; - } - - public static Map extractParameters(List xmlParamElements) { - if ( xmlParamElements == null || xmlParamElements.isEmpty() ) { - return null; - } - final HashMap params = new HashMap(); - for ( JaxbParamElement paramElement : xmlParamElements ) { - params.put( paramElement.getName(), paramElement.getValue() ); - } - return params; - } - - public static Iterable buildMetaAttributeSources(List metaElements) { - ArrayList result = new ArrayList(); - if ( metaElements == null || metaElements.isEmpty() ) { - // do nothing - } - else { - for ( final JaxbMetaElement metaElement : metaElements ) { - result.add( - new MetaAttributeSource() { - @Override - public String getName() { - return metaElement.getAttribute(); - } - - @Override - public String getValue() { - return metaElement.getValue(); - } - - @Override - public boolean isInheritable() { - return metaElement.isInherit(); - } - } - ); - } - } - return result; - } - - public static Schema.Name determineDatabaseSchemaName( - String explicitSchemaName, - String explicitCatalogName, - LocalBindingContext bindingContext) { - return new Schema.Name( - resolveIdentifier( - explicitSchemaName, - bindingContext.getMappingDefaults().getSchemaName(), - bindingContext.isGloballyQuotedIdentifiers() - ), - resolveIdentifier( - explicitCatalogName, - bindingContext.getMappingDefaults().getCatalogName(), - bindingContext.isGloballyQuotedIdentifiers() - ) - ); - } - - public static Identifier resolveIdentifier(String explicitName, String defaultName, boolean globalQuoting) { - String name = StringHelper.isNotEmpty( explicitName ) ? explicitName : defaultName; - if ( globalQuoting ) { - name = StringHelper.quote( name ); - } - return Identifier.toIdentifier( name ); - } - - public static class ValueSourcesAdapter { - public String getContainingTableName() { - return null; - } - - public boolean isIncludedInInsertByDefault() { - return false; - } - - public boolean isIncludedInUpdateByDefault() { - return false; - } - - public String getColumnAttribute() { - return null; - } - - public String getFormulaAttribute() { - return null; - } - - public List getColumnOrFormulaElements() { - return null; - } - - public boolean isForceNotNull() { - return false; - } - } - - public static List buildValueSources( - ValueSourcesAdapter valueSourcesAdapter, - LocalBindingContext bindingContext) { - List result = new ArrayList(); - - if ( StringHelper.isNotEmpty( valueSourcesAdapter.getColumnAttribute() ) ) { - if ( valueSourcesAdapter.getColumnOrFormulaElements() != null - && ! valueSourcesAdapter.getColumnOrFormulaElements().isEmpty() ) { - throw new org.hibernate.metamodel.source.MappingException( - "column/formula attribute may not be used together with / subelement", - bindingContext.getOrigin() - ); - } - if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { - throw new org.hibernate.metamodel.source.MappingException( - "column and formula attributes may not be used together", - bindingContext.getOrigin() - ); - } - result.add( - new ColumnAttributeSourceImpl( - valueSourcesAdapter.getContainingTableName(), - valueSourcesAdapter.getColumnAttribute(), - valueSourcesAdapter.isIncludedInInsertByDefault(), - valueSourcesAdapter.isIncludedInUpdateByDefault(), - valueSourcesAdapter.isForceNotNull() - ) - ); - } - else if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { - if ( valueSourcesAdapter.getColumnOrFormulaElements() != null - && ! valueSourcesAdapter.getColumnOrFormulaElements().isEmpty() ) { - throw new org.hibernate.metamodel.source.MappingException( - "column/formula attribute may not be used together with / subelement", - bindingContext.getOrigin() - ); - } - // column/formula attribute combo checked already - result.add( - new FormulaImpl( - valueSourcesAdapter.getContainingTableName(), - valueSourcesAdapter.getFormulaAttribute() - ) - ); - } - else if ( valueSourcesAdapter.getColumnOrFormulaElements() != null - && ! valueSourcesAdapter.getColumnOrFormulaElements().isEmpty() ) { - for ( Object columnOrFormulaElement : valueSourcesAdapter.getColumnOrFormulaElements() ) { - if ( JaxbColumnElement.class.isInstance( columnOrFormulaElement ) ) { - result.add( - new ColumnSourceImpl( - valueSourcesAdapter.getContainingTableName(), - (JaxbColumnElement) columnOrFormulaElement, - valueSourcesAdapter.isIncludedInInsertByDefault(), - valueSourcesAdapter.isIncludedInUpdateByDefault(), - valueSourcesAdapter.isForceNotNull() - ) - ); - } - else { - result.add( - new FormulaImpl( - valueSourcesAdapter.getContainingTableName(), - (String) columnOrFormulaElement - ) - ); - } - } - } - return result; - } - - // todo : remove this once the state objects are cleaned up - - public static Class classForName(String className, ServiceRegistry serviceRegistry) { - ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - try { - return classLoaderService.classForName( className ); - } - catch ( ClassLoadingException e ) { - throw new MappingException( "Could not find class: " + className ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java deleted file mode 100644 index b03c33ab7b81..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingProcessor.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbFetchProfileElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbParamElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbQueryElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSqlQueryElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject; -import org.hibernate.metamodel.relational.BasicAuxiliaryDatabaseObjectImpl; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.type.Type; - -/** - * Responsible for processing a {@code } element. Allows processing to be coordinated across - * all hbm files in an ordered fashion. The order is essentially the same as defined in - * {@link org.hibernate.metamodel.source.MetadataSourceProcessor} - * - * @author Steve Ebersole - */ -public class HibernateMappingProcessor { - private final MetadataImplementor metadata; - private final MappingDocument mappingDocument; - - private ValueHolder classLoaderService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public ClassLoaderService initialize() { - return metadata.getServiceRegistry().getService( ClassLoaderService.class ); - } - } - ); - - public HibernateMappingProcessor(MetadataImplementor metadata, MappingDocument mappingDocument) { - this.metadata = metadata; - this.mappingDocument = mappingDocument; - } - - private JaxbHibernateMapping mappingRoot() { - return mappingDocument.getMappingRoot(); - } - - private Origin origin() { - return mappingDocument.getOrigin(); - } - - private HbmBindingContext bindingContext() { - return mappingDocument.getMappingLocalBindingContext(); - } - - private Class classForName(String name) { - return classLoaderService.getValue().classForName( bindingContext().qualifyClassName( name ) ); - } - - public void processIndependentMetadata() { - processDatabaseObjectDefinitions(); - processTypeDefinitions(); - } - - private void processDatabaseObjectDefinitions() { - if ( mappingRoot().getDatabaseObject() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbDatabaseObject databaseObjectElement : mappingRoot().getDatabaseObject() ) { - final AuxiliaryDatabaseObject auxiliaryDatabaseObject; - if ( databaseObjectElement.getDefinition() != null ) { - final String className = databaseObjectElement.getDefinition().getClazz(); - try { - auxiliaryDatabaseObject = (AuxiliaryDatabaseObject) classForName( className ).newInstance(); - } - catch (ClassLoadingException e) { - throw e; - } - catch (Exception e) { - throw new MappingException( - "could not instantiate custom database object class [" + className + "]", - origin() - ); - } - } - else { - Set dialectScopes = new HashSet(); - if ( databaseObjectElement.getDialectScope() != null ) { - for ( JaxbHibernateMapping.JaxbDatabaseObject.JaxbDialectScope dialectScope : databaseObjectElement.getDialectScope() ) { - dialectScopes.add( dialectScope.getName() ); - } - } - auxiliaryDatabaseObject = new BasicAuxiliaryDatabaseObjectImpl( - metadata.getDatabase().getDefaultSchema(), - databaseObjectElement.getCreate(), - databaseObjectElement.getDrop(), - dialectScopes - ); - } - metadata.getDatabase().addAuxiliaryDatabaseObject( auxiliaryDatabaseObject ); - } - } - - private void processTypeDefinitions() { - if ( mappingRoot().getTypedef() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbTypedef typedef : mappingRoot().getTypedef() ) { - final Map parameters = new HashMap(); - for ( JaxbParamElement paramElement : typedef.getParam() ) { - parameters.put( paramElement.getName(), paramElement.getValue() ); - } - metadata.addTypeDefinition( - new TypeDef( - typedef.getName(), - typedef.getClazz(), - parameters - ) - ); - } - } - - public void processTypeDependentMetadata() { - processFilterDefinitions(); - processIdentifierGenerators(); - } - - private void processFilterDefinitions() { - if ( mappingRoot().getFilterDef() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbFilterDef filterDefinition : mappingRoot().getFilterDef() ) { - final String name = filterDefinition.getName(); - final Map parameters = new HashMap(); - String condition = null; - for ( Object o : filterDefinition.getContent() ) { - if ( o instanceof String ) { - // represents the condition - if ( condition != null ) { - // log? - } - condition = (String) o; - } - else if ( o instanceof JaxbHibernateMapping.JaxbFilterDef.JaxbFilterParam ) { - final JaxbHibernateMapping.JaxbFilterDef.JaxbFilterParam paramElement = - JaxbHibernateMapping.JaxbFilterDef.JaxbFilterParam.class.cast( o ); - // todo : should really delay this resolution until later to allow typedef names - parameters.put( - paramElement.getName(), - metadata.getTypeResolver().heuristicType( paramElement.getType() ) - ); - } - else { - throw new MappingException( "Unrecognized nested filter content", origin() ); - } - } - if ( condition == null ) { - condition = filterDefinition.getCondition(); - } - metadata.addFilterDefinition( new FilterDefinition( name, condition, parameters ) ); - } - } - - private void processIdentifierGenerators() { - if ( mappingRoot().getIdentifierGenerator() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbIdentifierGenerator identifierGeneratorElement : mappingRoot().getIdentifierGenerator() ) { - metadata.registerIdentifierGenerator( - identifierGeneratorElement.getName(), - identifierGeneratorElement.getClazz() - ); - } - } - - public void processMappingDependentMetadata() { - processFetchProfiles(); - processImports(); - processResultSetMappings(); - processNamedQueries(); - } - - private void processFetchProfiles(){ - if ( mappingRoot().getFetchProfile() == null ) { - return; - } - - processFetchProfiles( mappingRoot().getFetchProfile(), null ); - } - - public void processFetchProfiles(List fetchProfiles, String containingEntityName) { - for ( JaxbFetchProfileElement fetchProfile : fetchProfiles ) { - String profileName = fetchProfile.getName(); - Set fetches = new HashSet(); - for ( JaxbFetchProfileElement.JaxbFetch fetch : fetchProfile.getFetch() ) { - String entityName = fetch.getEntity() == null ? containingEntityName : fetch.getEntity(); - if ( entityName == null ) { - throw new MappingException( - "could not determine entity for fetch-profile fetch [" + profileName + "]:[" + - fetch.getAssociation() + "]", - origin() - ); - } - fetches.add( new FetchProfile.Fetch( entityName, fetch.getAssociation(), fetch.getStyle() ) ); - } - metadata.addFetchProfile( new FetchProfile( profileName, fetches ) ); - } - } - - private void processImports() { - if ( mappingRoot().getImport() == null ) { - return; - } - - for ( JaxbHibernateMapping.JaxbImport importValue : mappingRoot().getImport() ) { - String className = mappingDocument.getMappingLocalBindingContext().qualifyClassName( importValue.getClazz() ); - String rename = importValue.getRename(); - rename = ( rename == null ) ? StringHelper.unqualify( className ) : rename; - metadata.addImport( className, rename ); - } - } - - private void processResultSetMappings() { - if ( mappingRoot().getResultset() == null ) { - return; - } - -// bindResultSetMappingDefinitions( element, null, mappings ); - } - - private void processNamedQueries() { - if ( mappingRoot().getQueryOrSqlQuery() == null ) { - return; - } - - for ( Object queryOrSqlQuery : mappingRoot().getQueryOrSqlQuery() ) { - if ( JaxbQueryElement.class.isInstance( queryOrSqlQuery ) ) { -// bindNamedQuery( element, null, mappings ); - } - else if ( JaxbSqlQueryElement.class.isInstance( queryOrSqlQuery ) ) { -// bindNamedSQLQuery( element, null, mappings ); - } - else { - throw new MappingException( - "unknown type of query: " + - queryOrSqlQuery.getClass().getName(), origin() - ); - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java deleted file mode 100644 index 2582a8b32fc0..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HierarchyBuilder.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.hibernate.MappingException; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement; -import org.hibernate.metamodel.source.binder.SubclassEntityContainer; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; - -/** - * @author Steve Ebersole - */ -public class HierarchyBuilder { - private final List entityHierarchies = new ArrayList(); - - // process state - private final Map subEntityContainerMap = new HashMap(); - private final List extendsQueue = new ArrayList(); - - // mapping file specific state - private MappingDocument currentMappingDocument; - - public void processMappingDocument(MappingDocument mappingDocument) { - this.currentMappingDocument = mappingDocument; - try { - processCurrentMappingDocument(); - } - finally { - this.currentMappingDocument = null; - } - } - - private void processCurrentMappingDocument() { - for ( Object entityElementO : currentMappingDocument.getMappingRoot().getClazzOrSubclassOrJoinedSubclass() ) { - final EntityElement entityElement = (EntityElement) entityElementO; - if ( JaxbHibernateMapping.JaxbClass.class.isInstance( entityElement ) ) { - // we can immediately handle elements in terms of creating the hierarchy entry - final JaxbHibernateMapping.JaxbClass jaxbClass = (JaxbHibernateMapping.JaxbClass) entityElement; - final RootEntitySourceImpl rootEntitySource = new RootEntitySourceImpl( currentMappingDocument, - jaxbClass - ); - final EntityHierarchyImpl hierarchy = new EntityHierarchyImpl( rootEntitySource ); - - entityHierarchies.add( hierarchy ); - subEntityContainerMap.put( rootEntitySource.getEntityName(), rootEntitySource ); - - processSubElements( entityElement, rootEntitySource ); - } - else { - // we have to see if this things super-type has been found yet, and if not add it to the - // extends queue - final SubclassEntitySourceImpl subClassEntitySource = new SubclassEntitySourceImpl( currentMappingDocument, entityElement ); - final String entityName = subClassEntitySource.getEntityName(); - subEntityContainerMap.put( entityName, subClassEntitySource ); - final String entityItExtends = currentMappingDocument.getMappingLocalBindingContext().qualifyClassName( - ((SubEntityElement) entityElement).getExtends() - ); - processSubElements( entityElement, subClassEntitySource ); - final SubclassEntityContainer container = subEntityContainerMap.get( entityItExtends ); - if ( container != null ) { - // we already have this entity's super, attach it and continue - container.add( subClassEntitySource ); - } - else { - // we do not yet have the super and have to wait, so add it fto the extends queue - extendsQueue.add( new ExtendsQueueEntry( subClassEntitySource, entityItExtends ) ); - } - } - } - } - - public List groupEntityHierarchies() { - while ( ! extendsQueue.isEmpty() ) { - // set up a pass over the queue - int numberOfMappingsProcessed = 0; - Iterator iterator = extendsQueue.iterator(); - while ( iterator.hasNext() ) { - final ExtendsQueueEntry entry = iterator.next(); - final SubclassEntityContainer container = subEntityContainerMap.get( entry.entityItExtends ); - if ( container != null ) { - // we now have this entity's super, attach it and remove entry from extends queue - container.add( entry.subClassEntitySource ); - iterator.remove(); - numberOfMappingsProcessed++; - } - } - - if ( numberOfMappingsProcessed == 0 ) { - // todo : we could log the waiting dependencies... - throw new MappingException( "Unable to process extends dependencies in hbm files" ); - } - } - - return entityHierarchies; - } - - private void processSubElements(EntityElement entityElement, SubclassEntityContainer container) { - if ( JaxbHibernateMapping.JaxbClass.class.isInstance( entityElement ) ) { - final JaxbHibernateMapping.JaxbClass jaxbClass = (JaxbHibernateMapping.JaxbClass) entityElement; - processElements( jaxbClass.getJoinedSubclass(), container ); - processElements( jaxbClass.getSubclass(), container ); - processElements( jaxbClass.getUnionSubclass(), container ); - } - else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { - final JaxbSubclassElement jaxbSubclass = (JaxbSubclassElement) entityElement; - processElements( jaxbSubclass.getSubclass(), container ); - } - else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { - final JaxbJoinedSubclassElement jaxbJoinedSubclass = (JaxbJoinedSubclassElement) entityElement; - processElements( jaxbJoinedSubclass.getJoinedSubclass(), container ); - } - else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { - final JaxbUnionSubclassElement jaxbUnionSubclass = (JaxbUnionSubclassElement) entityElement; - processElements( jaxbUnionSubclass.getUnionSubclass(), container ); - } - } - - private void processElements(List subElements, SubclassEntityContainer container) { - for ( Object subElementO : subElements ) { - final SubEntityElement subElement = (SubEntityElement) subElementO; - final SubclassEntitySourceImpl subclassEntitySource = new SubclassEntitySourceImpl( currentMappingDocument, subElement ); - container.add( subclassEntitySource ); - final String subEntityName = subclassEntitySource.getEntityName(); - subEntityContainerMap.put( subEntityName, subclassEntitySource ); - } - } - - private static class ExtendsQueueEntry { - private final SubclassEntitySource subClassEntitySource; - private final String entityItExtends; - - private ExtendsQueueEntry(SubclassEntitySource subClassEntitySource, String entityItExtends) { - this.subClassEntitySource = subClassEntitySource; - this.entityItExtends = entityItExtends; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java deleted file mode 100644 index e4618e76cf2d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; - -import org.hibernate.FetchMode; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToManyElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.ManyToManyPluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; -import org.hibernate.metamodel.source.binder.RelationalValueSource; - -/** - * @author Steve Ebersole - */ -public class ManyToManyPluralAttributeElementSourceImpl implements ManyToManyPluralAttributeElementSource { - private final JaxbManyToManyElement manyToManyElement; - private final LocalBindingContext bindingContext; - - private final List valueSources; - - public ManyToManyPluralAttributeElementSourceImpl( - final JaxbManyToManyElement manyToManyElement, - final LocalBindingContext bindingContext) { - this.manyToManyElement = manyToManyElement; - this.bindingContext = bindingContext; - - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getContainingTableName() { - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return true; - } - - @Override - public String getColumnAttribute() { - return manyToManyElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return manyToManyElement.getFormula(); - } - - @Override - public List getColumnOrFormulaElements() { - return manyToManyElement.getColumnOrFormula(); - } - }, - bindingContext - ); - } - - @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.MANY_TO_MANY; - } - - @Override - public String getReferencedEntityName() { - return StringHelper.isNotEmpty( manyToManyElement.getEntityName() ) - ? manyToManyElement.getEntityName() - : bindingContext.qualifyClassName( manyToManyElement.getClazz() ); - } - - @Override - public String getReferencedEntityAttributeName() { - return manyToManyElement.getPropertyRef(); - } - - @Override - public List getValueSources() { - return valueSources; - } - - @Override - public boolean isNotFoundAnException() { - return manyToManyElement.getNotFound() == null - || ! "ignore".equals( manyToManyElement.getNotFound().value() ); - } - - @Override - public String getExplicitForeignKeyName() { - return manyToManyElement.getForeignKey(); - } - - @Override - public boolean isUnique() { - return manyToManyElement.isUnique(); - } - - @Override - public String getOrderBy() { - return manyToManyElement.getOrderBy(); - } - - @Override - public String getWhere() { - return manyToManyElement.getWhere(); - } - - @Override - public FetchMode getFetchMode() { - return null; - } - - @Override - public boolean fetchImmediately() { - if ( manyToManyElement.getLazy() != null ) { - if ( "false".equals( manyToManyElement.getLazy().value() ) ) { - return true; - } - } - - if ( manyToManyElement.getOuterJoin() == null ) { - return ! bindingContext.getMappingDefaults().areAssociationsLazy(); - } - else { - final String value = manyToManyElement.getOuterJoin().value(); - if ( "auto".equals( value ) ) { - return ! bindingContext.getMappingDefaults().areAssociationsLazy(); - } - return "true".equals( value ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java deleted file mode 100644 index 902bec8dfd44..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/ManyToOneAttributeSourceImpl.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; - -import org.hibernate.FetchMode; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.ToOneAttributeSource; - -/** - * Implementation for {@code mappings} - * - * @author Steve Ebersole - */ -class ManyToOneAttributeSourceImpl implements ToOneAttributeSource { - private final JaxbManyToOneElement manyToOneElement; - private final LocalBindingContext bindingContext; - private final List valueSources; - - ManyToOneAttributeSourceImpl(final JaxbManyToOneElement manyToOneElement, LocalBindingContext bindingContext) { - this.manyToOneElement = manyToOneElement; - this.bindingContext = bindingContext; - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getColumnAttribute() { - return manyToOneElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return manyToOneElement.getFormula(); - } - - @Override - public List getColumnOrFormulaElements() { - return manyToOneElement.getColumnOrFormula(); - } - - @Override - public String getContainingTableName() { - // todo : need to implement this... - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return manyToOneElement.isInsert(); - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return manyToOneElement.isUpdate(); - } - }, - bindingContext - ); - } - - @Override - public String getName() { - return manyToOneElement.getName(); - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return Helper.TO_ONE_ATTRIBUTE_TYPE_SOURCE; - } - - @Override - public String getPropertyAccessorName() { - return manyToOneElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return manyToOneElement.isInsert(); - } - - @Override - public boolean isUpdatable() { - return manyToOneElement.isUpdate(); - } - - @Override - public PropertyGeneration getGeneration() { - return PropertyGeneration.NEVER; - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return manyToOneElement.isOptimisticLock(); - } - - @Override - public Iterable getCascadeStyles() { - return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext ); - } - - @Override - public FetchTiming getFetchTiming() { - final String fetchSelection = manyToOneElement.getFetch() != null - ? manyToOneElement.getFetch().value() - : null; - final String lazySelection = manyToOneElement.getLazy() != null - ? manyToOneElement.getLazy().value() - : null; - final String outerJoinSelection = manyToOneElement.getOuterJoin() != null - ? manyToOneElement.getOuterJoin().value() - : null; - - if ( lazySelection == null ) { - if ( "join".equals( fetchSelection ) || "true".equals( outerJoinSelection ) ) { - return FetchTiming.IMMEDIATE; - } - else if ( "false".equals( outerJoinSelection ) ) { - return FetchTiming.DELAYED; - } - else { - return bindingContext.getMappingDefaults().areAssociationsLazy() - ? FetchTiming.DELAYED - : FetchTiming.IMMEDIATE; - } - } - else if ( "extra".equals( lazySelection ) ) { - return FetchTiming.EXTRA_LAZY; - } - else if ( "true".equals( lazySelection ) ) { - return FetchTiming.DELAYED; - } - else if ( "false".equals( lazySelection ) ) { - return FetchTiming.IMMEDIATE; - } - - throw new MappingException( - String.format( - "Unexpected lazy selection [%s] on '%s'", - lazySelection, - manyToOneElement.getName() - ), - bindingContext.getOrigin() - ); - } - - @Override - public FetchStyle getFetchStyle() { - // todo : handle batch fetches? - - final String fetchSelection = manyToOneElement.getFetch() != null - ? manyToOneElement.getFetch().value() - : null; - final String outerJoinSelection = manyToOneElement.getOuterJoin() != null - ? manyToOneElement.getOuterJoin().value() - : null; - - if ( fetchSelection == null ) { - if ( outerJoinSelection == null ) { - return FetchStyle.SELECT; - } - else { - if ( "auto".equals( outerJoinSelection ) ) { - return bindingContext.getMappingDefaults().areAssociationsLazy() - ? FetchStyle.SELECT - : FetchStyle.JOIN; - } - else { - return "true".equals( outerJoinSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; - } - } - } - else { - return "join".equals( fetchSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; - } - } - - @Override - public FetchMode getFetchMode() { - return manyToOneElement.getFetch() == null - ? FetchMode.DEFAULT - : FetchMode.valueOf( manyToOneElement.getFetch().value() ); - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.MANY_TO_ONE; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return manyToOneElement.isInsert(); - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return manyToOneElement.isUpdate(); - } - - @Override - public boolean areValuesNullableByDefault() { - return ! Helper.getBooleanValue( manyToOneElement.isNotNull(), false ); - } - - @Override - public List relationalValueSources() { - return valueSources; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( manyToOneElement.getMeta() ); - } - - @Override - public String getReferencedEntityName() { - return manyToOneElement.getClazz() != null - ? manyToOneElement.getClazz() - : manyToOneElement.getEntityName(); - } - - @Override - public String getReferencedEntityAttributeName() { - return manyToOneElement.getPropertyRef(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/MappingDocument.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/MappingDocument.java deleted file mode 100644 index b9d8cb609b71..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/MappingDocument.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; - -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbFetchProfileElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.internal.OverriddenMappingDefaults; -import org.hibernate.service.ServiceRegistry; - -/** - * Aggregates together information about a mapping document. - * - * @author Steve Ebersole - */ -public class MappingDocument { - private final JaxbRoot hbmJaxbRoot; - private final LocalBindingContextImpl mappingLocalBindingContext; - - public MappingDocument(JaxbRoot hbmJaxbRoot, MetadataImplementor metadata) { - this.hbmJaxbRoot = hbmJaxbRoot; - this.mappingLocalBindingContext = new LocalBindingContextImpl( metadata ); - - } - - public JaxbHibernateMapping getMappingRoot() { - return hbmJaxbRoot.getRoot(); - } - - public Origin getOrigin() { - return hbmJaxbRoot.getOrigin(); - } - - public JaxbRoot getJaxbRoot() { - return hbmJaxbRoot; - } - - public HbmBindingContext getMappingLocalBindingContext() { - return mappingLocalBindingContext; - } - - private class LocalBindingContextImpl implements HbmBindingContext { - private final MetadataImplementor metadata; - private final MappingDefaults localMappingDefaults; - private final MetaAttributeContext metaAttributeContext; - - private LocalBindingContextImpl(MetadataImplementor metadata) { - this.metadata = metadata; - this.localMappingDefaults = new OverriddenMappingDefaults( - metadata.getMappingDefaults(), - hbmJaxbRoot.getRoot().getPackage(), - hbmJaxbRoot.getRoot().getSchema(), - hbmJaxbRoot.getRoot().getCatalog(), - null, - null, - hbmJaxbRoot.getRoot().getDefaultCascade(), - hbmJaxbRoot.getRoot().getDefaultAccess(), - hbmJaxbRoot.getRoot().isDefaultLazy() - ); - if ( hbmJaxbRoot.getRoot().getMeta() == null || hbmJaxbRoot.getRoot().getMeta().isEmpty() ) { - this.metaAttributeContext = new MetaAttributeContext( metadata.getGlobalMetaAttributeContext() ); - } - else { - this.metaAttributeContext = Helper.extractMetaAttributeContext( - hbmJaxbRoot.getRoot().getMeta(), - true, - metadata.getGlobalMetaAttributeContext() - ); - } - } - - @Override - public ServiceRegistry getServiceRegistry() { - return metadata.getServiceRegistry(); - } - - @Override - public NamingStrategy getNamingStrategy() { - return metadata.getNamingStrategy(); - } - - @Override - public MappingDefaults getMappingDefaults() { - return localMappingDefaults; - } - - @Override - public MetadataImplementor getMetadataImplementor() { - return metadata; - } - - @Override - public Class locateClassByName(String name) { - return metadata.locateClassByName( name ); - } - - @Override - public Type makeJavaType(String className) { - return metadata.makeJavaType( className ); - } - - @Override - public ValueHolder> makeClassReference(String className) { - return metadata.makeClassReference( className ); - } - - @Override - public boolean isAutoImport() { - return hbmJaxbRoot.getRoot().isAutoImport(); - } - - @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - @Override - public Origin getOrigin() { - return hbmJaxbRoot.getOrigin(); - } - - @Override - public String qualifyClassName(String unqualifiedName) { - return Helper.qualifyIfNeeded( unqualifiedName, getMappingDefaults().getPackageName() ); - } - - @Override - public String determineEntityName(EntityElement entityElement) { - return Helper.determineEntityName( entityElement, getMappingDefaults().getPackageName() ); - } - - @Override - public boolean isGloballyQuotedIdentifiers() { - return metadata.isGloballyQuotedIdentifiers(); - } - - @Override - public void processFetchProfiles(List fetchProfiles, String containingEntityName) { - // todo : this really needs to not be part of the context - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/OneToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/OneToManyPluralAttributeElementSourceImpl.java deleted file mode 100644 index 8176952c40f3..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/OneToManyPluralAttributeElementSourceImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToManyElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.OneToManyPluralAttributeElementSource; -import org.hibernate.metamodel.source.binder.PluralAttributeElementNature; - -/** - * @author Steve Ebersole - */ -public class OneToManyPluralAttributeElementSourceImpl implements OneToManyPluralAttributeElementSource { - private final JaxbOneToManyElement oneToManyElement; - private final LocalBindingContext bindingContext; - - public OneToManyPluralAttributeElementSourceImpl( - JaxbOneToManyElement oneToManyElement, - LocalBindingContext bindingContext) { - this.oneToManyElement = oneToManyElement; - this.bindingContext = bindingContext; - } - - @Override - public PluralAttributeElementNature getNature() { - return PluralAttributeElementNature.ONE_TO_MANY; - } - - @Override - public String getReferencedEntityName() { - return StringHelper.isNotEmpty( oneToManyElement.getEntityName() ) - ? oneToManyElement.getEntityName() - : bindingContext.qualifyClassName( oneToManyElement.getClazz() ); - } - - @Override - public boolean isNotFoundAnException() { - return oneToManyElement.getNotFound() == null - || ! "ignore".equals( oneToManyElement.getNotFound().value() ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PluralAttributeKeySourceImpl.java deleted file mode 100644 index 1def9cc4ab01..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PluralAttributeKeySourceImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbKeyElement; -import org.hibernate.metamodel.relational.ForeignKey; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.PluralAttributeKeySource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; - -/** - * @author Steve Ebersole - */ -public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { - private final JaxbKeyElement keyElement; - - private final List valueSources; - - public PluralAttributeKeySourceImpl( - final JaxbKeyElement keyElement, - final AttributeSourceContainer container) { - this.keyElement = keyElement; - - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getContainingTableName() { - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return Helper.getBooleanValue( keyElement.isUpdate(), true ); - } - - @Override - public String getColumnAttribute() { - return keyElement.getColumnAttribute(); - } - - @Override - public String getFormulaAttribute() { - return null; - } - - @Override - public List getColumnOrFormulaElements() { - return keyElement.getColumn(); - } - }, - container.getLocalBindingContext() - ); - } - - @Override - public List getValueSources() { - return valueSources; - } - - @Override - public String getExplicitForeignKeyName() { - return keyElement.getForeignKey(); - } - - @Override - public ForeignKey.ReferentialAction getOnDeleteAction() { - return "cascade".equals( keyElement.getOnDelete() ) - ? ForeignKey.ReferentialAction.CASCADE - : ForeignKey.ReferentialAction.NO_ACTION; - } - - @Override - public String getReferencedEntityAttributeName() { - return keyElement.getPropertyRef(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PropertyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PropertyAttributeSourceImpl.java deleted file mode 100644 index 815cad854835..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/PropertyAttributeSourceImpl.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * Implementation for {@code } mappings - * - * @author Steve Ebersole - */ -class PropertyAttributeSourceImpl implements SingularAttributeSource { - private final JaxbPropertyElement propertyElement; - private final ExplicitHibernateTypeSource typeSource; - private final List valueSources; - - PropertyAttributeSourceImpl(final JaxbPropertyElement propertyElement, LocalBindingContext bindingContext) { - this.propertyElement = propertyElement; - this.typeSource = new ExplicitHibernateTypeSource() { - private final String name = propertyElement.getTypeAttribute() != null - ? propertyElement.getTypeAttribute() - : propertyElement.getType() != null - ? propertyElement.getType().getName() - : null; - private final Map parameters = ( propertyElement.getType() != null ) - ? Helper.extractParameters( propertyElement.getType().getParam() ) - : null; - - @Override - public String getName() { - return name; - } - - @Override - public Map getParameters() { - return parameters; - } - }; - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getColumnAttribute() { - return propertyElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return propertyElement.getFormula(); - } - - @Override - public List getColumnOrFormulaElements() { - return propertyElement.getColumnOrFormula(); - } - - @Override - public String getContainingTableName() { - // todo : need to implement this... - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return Helper.getBooleanValue( propertyElement.isInsert(), true ); - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return Helper.getBooleanValue( propertyElement.isUpdate(), true ); - } - }, - bindingContext - ); - } - - @Override - public String getName() { - return propertyElement.getName(); - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return typeSource; - } - - @Override - public String getPropertyAccessorName() { - return propertyElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return Helper.getBooleanValue( propertyElement.isInsert(), true ); - } - - @Override - public boolean isUpdatable() { - return Helper.getBooleanValue( propertyElement.isUpdate(), true ); - } - - @Override - public PropertyGeneration getGeneration() { - return PropertyGeneration.parse( propertyElement.getGenerated() ); - } - - @Override - public boolean isLazy() { - return Helper.getBooleanValue( propertyElement.isLazy(), false ); - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return Helper.getBooleanValue( propertyElement.isOptimisticLock(), true ); - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return Helper.getBooleanValue( propertyElement.isInsert(), true ); - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return Helper.getBooleanValue( propertyElement.isUpdate(), true ); - } - - @Override - public boolean areValuesNullableByDefault() { - return ! Helper.getBooleanValue( propertyElement.isNotNull(), false ); - } - - @Override - public List relationalValueSources() { - return valueSources; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( propertyElement.getMeta() ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java deleted file mode 100644 index d184a4898d0b..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntitySourceImpl.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.EntityMode; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbCacheElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.DiscriminatorSource; -import org.hibernate.metamodel.source.binder.IdentifierSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.RootEntitySource; -import org.hibernate.metamodel.source.binder.SimpleIdentifierSource; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Steve Ebersole - */ -public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements RootEntitySource { - protected RootEntitySourceImpl(MappingDocument sourceMappingDocument, JaxbHibernateMapping.JaxbClass entityElement) { - super( sourceMappingDocument, entityElement ); - } - - @Override - protected JaxbHibernateMapping.JaxbClass entityElement() { - return (JaxbHibernateMapping.JaxbClass) super.entityElement(); - } - - @Override - public IdentifierSource getIdentifierSource() { - if ( entityElement().getId() != null ) { - return new SimpleIdentifierSource() { - @Override - public SingularAttributeSource getIdentifierAttributeSource() { - return new SingularIdentifierAttributeSourceImpl( - entityElement().getId(), - sourceMappingDocument().getMappingLocalBindingContext() - ); - } - - @Override - public IdGenerator getIdentifierGeneratorDescriptor() { - if ( entityElement().getId().getGenerator() != null ) { - final String generatorName = entityElement().getId().getGenerator().getClazz(); - IdGenerator idGenerator = sourceMappingDocument().getMappingLocalBindingContext() - .getMetadataImplementor() - .getIdGenerator( generatorName ); - if ( idGenerator == null ) { - idGenerator = new IdGenerator( - getEntityName() + generatorName, - generatorName, - Helper.extractParameters( entityElement().getId().getGenerator().getParam() ) - ); - } - return idGenerator; - } - return null; - } - - @Override - public Nature getNature() { - return Nature.SIMPLE; - } - }; - } - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public SingularAttributeSource getVersioningAttributeSource() { - if ( entityElement().getVersion() != null ) { - return new VersionAttributeSourceImpl( - entityElement().getVersion(), - sourceMappingDocument().getMappingLocalBindingContext() - ); - } - else if ( entityElement().getTimestamp() != null ) { - return new TimestampAttributeSourceImpl( - entityElement().getTimestamp(), - sourceMappingDocument().getMappingLocalBindingContext() - ); - } - return null; - } - - @Override - public EntityMode getEntityMode() { - return determineEntityMode(); - } - - @Override - public boolean isMutable() { - return entityElement().isMutable(); - } - - - @Override - public boolean isExplicitPolymorphism() { - return "explicit".equals( entityElement().getPolymorphism() ); - } - - @Override - public String getWhere() { - return entityElement().getWhere(); - } - - @Override - public String getRowId() { - return entityElement().getRowid(); - } - - @Override - public OptimisticLockStyle getOptimisticLockStyle() { - final String optimisticLockModeString = Helper.getStringValue( entityElement().getOptimisticLock(), "version" ); - try { - return OptimisticLockStyle.valueOf( optimisticLockModeString.toUpperCase() ); - } - catch ( Exception e ) { - throw new MappingException( - "Unknown optimistic-lock value : " + optimisticLockModeString, - sourceMappingDocument().getOrigin() - ); - } - } - - @Override - public Caching getCaching() { - final JaxbCacheElement cache = entityElement().getCache(); - if ( cache == null ) { - return null; - } - final String region = cache.getRegion() != null ? cache.getRegion() : getEntityName(); - final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() ); - final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() ); - return new Caching( region, accessType, cacheLazyProps ); - } - - @Override - public TableSource getPrimaryTable() { - return new TableSource() { - @Override - public String getExplicitSchemaName() { - return entityElement().getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return entityElement().getCatalog(); - } - - @Override - public String getExplicitTableName() { - return entityElement().getTable(); - } - - @Override - public String getLogicalName() { - // logical name for the primary table is null - return null; - } - }; - } - - @Override - public String getDiscriminatorMatchValue() { - return entityElement().getDiscriminatorValue(); - } - - @Override - public DiscriminatorSource getDiscriminatorSource() { - final JaxbHibernateMapping.JaxbClass.JaxbDiscriminator discriminatorElement = entityElement().getDiscriminator(); - if ( discriminatorElement == null ) { - return null; - } - - return new DiscriminatorSource() { - @Override - public RelationalValueSource getDiscriminatorRelationalValueSource() { - if ( StringHelper.isNotEmpty( discriminatorElement.getColumnAttribute() ) ) { - return new ColumnAttributeSourceImpl( - null, // root table - discriminatorElement.getColumnAttribute(), - discriminatorElement.isInsert(), - discriminatorElement.isInsert() - ); - } - else if ( StringHelper.isNotEmpty( discriminatorElement.getFormulaAttribute() ) ) { - return new FormulaImpl( null, discriminatorElement.getFormulaAttribute() ); - } - else if ( discriminatorElement.getColumn() != null ) { - return new ColumnSourceImpl( - null, // root table - discriminatorElement.getColumn(), - discriminatorElement.isInsert(), - discriminatorElement.isInsert() - ); - } - else if ( StringHelper.isNotEmpty( discriminatorElement.getFormula() ) ) { - return new FormulaImpl( null, discriminatorElement.getFormula() ); - } - else { - throw new MappingException( "could not determine source of discriminator mapping", getOrigin() ); - } - } - - @Override - public String getExplicitHibernateTypeName() { - return discriminatorElement.getType(); - } - - @Override - public boolean isForced() { - return discriminatorElement.isForce(); - } - - @Override - public boolean isInserted() { - return discriminatorElement.isInsert(); - } - }; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SetAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SetAttributeSourceImpl.java deleted file mode 100644 index 64b4b6398b8f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SetAttributeSourceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSetElement; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.binder.AttributeSourceContainer; -import org.hibernate.metamodel.source.binder.Orderable; -import org.hibernate.metamodel.source.binder.PluralAttributeNature; -import org.hibernate.metamodel.source.binder.Sortable; - -/** - * @author Steve Ebersole - */ -public class SetAttributeSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable, Sortable { - public SetAttributeSourceImpl(JaxbSetElement setElement, AttributeSourceContainer container) { - super( setElement, container ); - } - - @Override - public JaxbSetElement getPluralAttributeElement() { - return (JaxbSetElement) super.getPluralAttributeElement(); - } - - @Override - public PluralAttributeNature getPluralAttributeNature() { - return PluralAttributeNature.SET; - } - - @Override - public boolean isSorted() { - return StringHelper.isNotEmpty( getComparatorName() ); - } - - @Override - public String getComparatorName() { - return getPluralAttributeElement().getSort(); - } - - @Override - public boolean isOrdered() { - return StringHelper.isNotEmpty( getOrder() ); - } - - @Override - public String getOrder() { - return getPluralAttributeElement().getOrderBy(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SingularIdentifierAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SingularIdentifierAttributeSourceImpl.java deleted file mode 100644 index 9a9731478366..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SingularIdentifierAttributeSourceImpl.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * Implementation for {@code } mappings - * - * @author Steve Ebersole - */ -class SingularIdentifierAttributeSourceImpl implements SingularAttributeSource { - private final JaxbHibernateMapping.JaxbClass.JaxbId idElement; - private final ExplicitHibernateTypeSource typeSource; - private final List valueSources; - - public SingularIdentifierAttributeSourceImpl( - final JaxbHibernateMapping.JaxbClass.JaxbId idElement, - LocalBindingContext bindingContext) { - this.idElement = idElement; - this.typeSource = new ExplicitHibernateTypeSource() { - private final String name = idElement.getTypeAttribute() != null - ? idElement.getTypeAttribute() - : idElement.getType() != null - ? idElement.getType().getName() - : null; - private final Map parameters = ( idElement.getType() != null ) - ? Helper.extractParameters( idElement.getType().getParam() ) - : null; - - @Override - public String getName() { - return name; - } - - @Override - public Map getParameters() { - return parameters; - } - }; - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getColumnAttribute() { - return idElement.getColumnAttribute(); - } - - @Override - public String getFormulaAttribute() { - return null; - } - - @Override - public List getColumnOrFormulaElements() { - return idElement.getColumn(); - } - - @Override - public String getContainingTableName() { - // by definition, the identifier should be bound to the primary table of the root entity - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return false; - } - - @Override - public boolean isForceNotNull() { - return true; - } - }, - bindingContext - ); - } - - @Override - public String getName() { - return idElement.getName() == null - ? "id" - : idElement.getName(); - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return typeSource; - } - - @Override - public String getPropertyAccessorName() { - return idElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return true; - } - - @Override - public boolean isUpdatable() { - return false; - } - - @Override - public PropertyGeneration getGeneration() { - return PropertyGeneration.INSERT; - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return false; - } - - @Override - public List relationalValueSources() { - return valueSources; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( idElement.getMeta() ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java deleted file mode 100644 index 473d8075fd3f..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/SubclassEntitySourceImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; -import org.hibernate.metamodel.source.binder.TableSource; - -/** - * @author Steve Ebersole - */ -public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implements SubclassEntitySource { - protected SubclassEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) { - super( sourceMappingDocument, entityElement ); - } - - @Override - public TableSource getPrimaryTable() { - if ( JaxbJoinedSubclassElement.class.isInstance( entityElement() ) ) { - return new TableSource() { - @Override - public String getExplicitSchemaName() { - return ( (JaxbJoinedSubclassElement) entityElement() ).getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return ( (JaxbJoinedSubclassElement) entityElement() ).getCatalog(); - } - - @Override - public String getExplicitTableName() { - return ( (JaxbJoinedSubclassElement) entityElement() ).getTable(); - } - - @Override - public String getLogicalName() { - // logical name for the primary table is null - return null; - } - }; - } - else if ( JaxbUnionSubclassElement.class.isInstance( entityElement() ) ) { - return new TableSource() { - @Override - public String getExplicitSchemaName() { - return ( (JaxbUnionSubclassElement) entityElement() ).getSchema(); - } - - @Override - public String getExplicitCatalogName() { - return ( (JaxbUnionSubclassElement) entityElement() ).getCatalog(); - } - - @Override - public String getExplicitTableName() { - return ( (JaxbUnionSubclassElement) entityElement() ).getTable(); - } - - @Override - public String getLogicalName() { - // logical name for the primary table is null - return null; - } - }; - } - return null; - } - - @Override - public String getDiscriminatorMatchValue() { - return JaxbSubclassElement.class.isInstance( entityElement() ) - ? ( (JaxbSubclassElement) entityElement() ).getDiscriminatorValue() - : null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/TimestampAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/TimestampAttributeSourceImpl.java deleted file mode 100644 index 52ef5eeab691..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/TimestampAttributeSourceImpl.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * Implementation for {@code } mappings - * - * @author Steve Ebersole - */ -class TimestampAttributeSourceImpl implements SingularAttributeSource { - private final JaxbHibernateMapping.JaxbClass.JaxbTimestamp timestampElement; - private final LocalBindingContext bindingContext; - private final List valueSources; - - TimestampAttributeSourceImpl( - final JaxbHibernateMapping.JaxbClass.JaxbTimestamp timestampElement, - LocalBindingContext bindingContext) { - this.timestampElement = timestampElement; - this.bindingContext = bindingContext; - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getColumnAttribute() { - return timestampElement.getColumn(); - } - - @Override - public String getFormulaAttribute() { - return null; - } - - @Override - public List getColumnOrFormulaElements() { - return null; - } - - @Override - public String getContainingTableName() { - // by definition the version should come from the primary table of the root entity. - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return true; - } - }, - bindingContext - ); - } - - private final ExplicitHibernateTypeSource typeSource = new ExplicitHibernateTypeSource() { - @Override - public String getName() { - return "db".equals( timestampElement.getSource() ) ? "dbtimestamp" : "timestamp"; - } - - @Override - public Map getParameters() { - return null; - } - }; - - @Override - public String getName() { - return timestampElement.getName(); - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return typeSource; - } - - @Override - public String getPropertyAccessorName() { - return timestampElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return true; - } - - @Override - public boolean isUpdatable() { - return true; - } - - private ValueHolder propertyGenerationValue = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public PropertyGeneration initialize() { - final PropertyGeneration propertyGeneration = timestampElement.getGenerated() == null - ? PropertyGeneration.NEVER - : PropertyGeneration.parse( timestampElement.getGenerated().value() ); - if ( propertyGeneration == PropertyGeneration.INSERT ) { - throw new MappingException( - "'generated' attribute cannot be 'insert' for versioning property", - bindingContext.getOrigin() - ); - } - return propertyGeneration; - } - } - ); - - @Override - public PropertyGeneration getGeneration() { - return propertyGenerationValue.getValue(); - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } - - @Override - public List relationalValueSources() { - return valueSources; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( timestampElement.getMeta() ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/VersionAttributeSourceImpl.java deleted file mode 100644 index 79dc3d42e62d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/VersionAttributeSourceImpl.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.hbm; - -import java.util.List; -import java.util.Map; - -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.binder.ExplicitHibernateTypeSource; -import org.hibernate.metamodel.source.binder.MetaAttributeSource; -import org.hibernate.metamodel.source.binder.RelationalValueSource; -import org.hibernate.metamodel.source.binder.SingularAttributeNature; -import org.hibernate.metamodel.source.binder.SingularAttributeSource; - -/** - * Implementation for {@code } mappings - * - * @author Steve Ebersole - */ -class VersionAttributeSourceImpl implements SingularAttributeSource { - private final JaxbHibernateMapping.JaxbClass.JaxbVersion versionElement; - private final LocalBindingContext bindingContext; - private final List valueSources; - - VersionAttributeSourceImpl( - final JaxbHibernateMapping.JaxbClass.JaxbVersion versionElement, - LocalBindingContext bindingContext) { - this.versionElement = versionElement; - this.bindingContext = bindingContext; - this.valueSources = Helper.buildValueSources( - new Helper.ValueSourcesAdapter() { - @Override - public String getColumnAttribute() { - return versionElement.getColumnAttribute(); - } - - @Override - public String getFormulaAttribute() { - return null; - } - - @Override - public List getColumnOrFormulaElements() { - return versionElement.getColumn(); - } - - @Override - public String getContainingTableName() { - // by definition the version should come from the primary table of the root entity. - return null; - } - - @Override - public boolean isIncludedInInsertByDefault() { - return Helper.getBooleanValue( versionElement.isInsert(), true ); - } - - @Override - public boolean isIncludedInUpdateByDefault() { - return true; - } - }, - bindingContext - ); - } - - private final ExplicitHibernateTypeSource typeSource = new ExplicitHibernateTypeSource() { - @Override - public String getName() { - return versionElement.getType() == null ? "integer" : versionElement.getType(); - } - - @Override - public Map getParameters() { - return null; - } - }; - - @Override - public String getName() { - return versionElement.getName(); - } - - @Override - public ExplicitHibernateTypeSource getTypeInformation() { - return typeSource; - } - - @Override - public String getPropertyAccessorName() { - return versionElement.getAccess(); - } - - @Override - public boolean isInsertable() { - return Helper.getBooleanValue( versionElement.isInsert(), true ); - } - - @Override - public boolean isUpdatable() { - return true; - } - - private ValueHolder propertyGenerationValue = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public PropertyGeneration initialize() { - final PropertyGeneration propertyGeneration = versionElement.getGenerated() == null - ? PropertyGeneration.NEVER - : PropertyGeneration.parse( versionElement.getGenerated().value() ); - if ( propertyGeneration == PropertyGeneration.INSERT ) { - throw new MappingException( - "'generated' attribute cannot be 'insert' for versioning property", - bindingContext.getOrigin() - ); - } - return propertyGeneration; - } - } - ); - - @Override - public PropertyGeneration getGeneration() { - return propertyGenerationValue.getValue(); - } - - @Override - public boolean isLazy() { - return false; - } - - @Override - public boolean isIncludedInOptimisticLocking() { - return false; - } - - @Override - public SingularAttributeNature getNature() { - return SingularAttributeNature.BASIC; - } - - @Override - public boolean isVirtualAttribute() { - return false; - } - - @Override - public boolean areValuesIncludedInInsertByDefault() { - return true; - } - - @Override - public boolean areValuesIncludedInUpdateByDefault() { - return true; - } - - @Override - public boolean areValuesNullableByDefault() { - return true; - } - - @Override - public List relationalValueSources() { - return valueSources; - } - - @Override - public boolean isSingular() { - return true; - } - - @Override - public Iterable metaAttributes() { - return Helper.buildMetaAttributeSources( versionElement.getMeta() ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java deleted file mode 100644 index e0af68dd4080..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AssociationResolver.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SingularAssociationAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; - -/** - * @author Gail Badner - */ -class AssociationResolver { - private final MetadataImplementor metadata; - - AssociationResolver(MetadataImplementor metadata) { - this.metadata = metadata; - } - - void resolve() { - for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { - for ( SingularAssociationAttributeBinding attributeBinding : entityBinding.getEntityReferencingAttributeBindings() ) { - resolve( attributeBinding ); - } - } - } - - private void resolve(SingularAssociationAttributeBinding attributeBinding) { - if ( attributeBinding.getReferencedEntityName() == null ) { - throw new IllegalArgumentException( - "attributeBinding has null entityName: " + attributeBinding.getAttribute().getName() - ); - } - EntityBinding entityBinding = metadata.getEntityBinding( attributeBinding.getReferencedEntityName() ); - if ( entityBinding == null ) { - throw new org.hibernate.MappingException( - String.format( - "Attribute [%s] refers to unknown entity: [%s]", - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedEntityName() - ) - ); - } - AttributeBinding referencedAttributeBinding = - attributeBinding.isPropertyReference() ? - entityBinding.locateAttributeBinding( attributeBinding.getReferencedAttributeName() ) : - entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - if ( referencedAttributeBinding == null ) { - // TODO: does attribute name include path w/ entity name? - throw new org.hibernate.MappingException( - String.format( - "Attribute [%s] refers to unknown attribute: [%s]", - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedEntityName() - ) - ); - } - attributeBinding.resolveReference( referencedAttributeBinding ); - referencedAttributeBinding.addEntityReferencingAttributeBinding( attributeBinding ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AttributeConversionInfo.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AttributeConversionInfo.java new file mode 100644 index 000000000000..33b190aa2e56 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/AttributeConversionInfo.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; + +/** + * Information about an attribute conversion + * + * @author Steve Ebersole + */ +public class AttributeConversionInfo { + private final boolean conversionEnabled; + private final ClassDescriptor converterClass; + + public AttributeConversionInfo( + boolean conversionEnabled, + ClassDescriptor converterClass) { + this.conversionEnabled = conversionEnabled; + this.converterClass = converterClass; + } + + public boolean isConversionEnabled() { + return conversionEnabled; + } + + public ClassDescriptor getConverterTypeDescriptor() { + return converterClass; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java deleted file mode 100644 index 80572f327b34..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.util.Properties; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.binding.AbstractCollectionElement; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.BasicCollectionElement; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityDiscriminator; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Value; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.type.Type; -import org.hibernate.type.TypeFactory; - -/** - * This is a TEMPORARY way to initialize Hibernate types. - * This class will be removed when types are resolved properly. - * - * @author Gail Badner - */ -class HibernateTypeResolver { - - private final MetadataImplementor metadata; - - HibernateTypeResolver(MetadataImplementor metadata) { - this.metadata = metadata; - } - - void resolve() { - for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { - if ( entityBinding.getHierarchyDetails().getEntityDiscriminator() != null ) { - resolveDiscriminatorTypeInformation( entityBinding.getHierarchyDetails().getEntityDiscriminator() ); - } - for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) { - if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { - resolveSingularAttributeTypeInformation( - SingularAttributeBinding.class.cast( attributeBinding ) - ); - } - else if ( AbstractPluralAttributeBinding.class.isInstance( attributeBinding ) ) { - resolvePluralAttributeTypeInformation( - AbstractPluralAttributeBinding.class.cast( attributeBinding ) - ); - } - else { - throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() ); - } - } - } - } - - // perform any needed type resolutions for discriminator - private void resolveDiscriminatorTypeInformation(EntityDiscriminator discriminator) { - // perform any needed type resolutions for discriminator - Type resolvedHibernateType = determineSingularTypeFromDescriptor( discriminator.getExplicitHibernateTypeDescriptor() ); - if ( resolvedHibernateType != null ) { - pushHibernateTypeInformationDownIfNeeded( - discriminator.getExplicitHibernateTypeDescriptor(), - discriminator.getBoundValue(), - resolvedHibernateType - ); - } - } - - private Type determineSingularTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) { - if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { - return hibernateTypeDescriptor.getResolvedTypeMapping(); - } - String typeName = determineTypeName( hibernateTypeDescriptor ); - Properties typeParameters = getTypeParameters( hibernateTypeDescriptor ); - return getHeuristicType( typeName, typeParameters ); - } - - private static String determineTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) { - return hibernateTypeDescriptor.getExplicitTypeName() != null - ? hibernateTypeDescriptor.getExplicitTypeName() - : hibernateTypeDescriptor.getJavaTypeName(); - } - - private static Properties getTypeParameters(HibernateTypeDescriptor hibernateTypeDescriptor) { - Properties typeParameters = new Properties( ); - if ( hibernateTypeDescriptor.getTypeParameters() != null ) { - typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() ); - } - return typeParameters; - } - - // perform any needed type resolutions for SingularAttributeBinding - private void resolveSingularAttributeTypeInformation(SingularAttributeBinding attributeBinding) { - if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) { - return; - } - // we can determine the Hibernate Type if either: - // 1) the user explicitly named a Type in a HibernateTypeDescriptor - // 2) we know the java type of the attribute - Type resolvedType; - resolvedType = determineSingularTypeFromDescriptor( attributeBinding.getHibernateTypeDescriptor() ); - if ( resolvedType == null ) { - if ( ! attributeBinding.getAttribute().isSingular() ) { - throw new AssertionFailure( "SingularAttributeBinding object has a plural attribute: " + attributeBinding.getAttribute().getName() ); - } - final SingularAttribute singularAttribute = ( SingularAttribute ) attributeBinding.getAttribute(); - if ( singularAttribute.getSingularAttributeType() != null ) { - resolvedType = getHeuristicType( - singularAttribute.getSingularAttributeType().getClassName(), new Properties() - ); - } - } - if ( resolvedType != null ) { - pushHibernateTypeInformationDownIfNeeded( attributeBinding, resolvedType ); - } - } - - // perform any needed type resolutions for PluralAttributeBinding - private void resolvePluralAttributeTypeInformation(AbstractPluralAttributeBinding attributeBinding) { - if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) { - return; - } - Type resolvedType; - // do NOT look at java type... - //String typeName = determineTypeName( attributeBinding.getHibernateTypeDescriptor() ); - String typeName = attributeBinding.getHibernateTypeDescriptor().getExplicitTypeName(); - if ( typeName != null ) { - resolvedType = - metadata.getTypeResolver() - .getTypeFactory() - .customCollection( - typeName, - getTypeParameters( attributeBinding.getHibernateTypeDescriptor() ), - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedPropertyName() - ); - } - else { - resolvedType = determineDefaultCollectionInformation( attributeBinding ); - } - if ( resolvedType != null ) { - pushHibernateTypeInformationDownIfNeeded( - attributeBinding.getHibernateTypeDescriptor(), - null, - resolvedType ); - } - resolveCollectionElementTypeInformation( attributeBinding.getCollectionElement() ); - } - - private Type determineDefaultCollectionInformation(AbstractPluralAttributeBinding attributeBinding) { - final TypeFactory typeFactory = metadata.getTypeResolver().getTypeFactory(); - switch ( attributeBinding.getAttribute().getNature() ) { - case SET: { - return typeFactory.set( - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedPropertyName() - ); - } - case BAG: { - return typeFactory.bag( - attributeBinding.getAttribute().getName(), - attributeBinding.getReferencedPropertyName() - ); - } - default: { - throw new UnsupportedOperationException( - "Collection type not supported yet:" + attributeBinding.getAttribute().getNature() - ); - } - } - } - - private void resolveCollectionElementTypeInformation(AbstractCollectionElement collectionElement) { - switch ( collectionElement.getCollectionElementNature() ) { - case BASIC: { - resolveBasicCollectionElement( BasicCollectionElement.class.cast( collectionElement ) ); - break; - } - case COMPOSITE: - case ONE_TO_MANY: - case MANY_TO_MANY: - case MANY_TO_ANY: { - throw new UnsupportedOperationException( "Collection element nature not supported yet: " + collectionElement.getCollectionElementNature() ); - } - default: { - throw new AssertionFailure( "Unknown collection element nature : " + collectionElement.getCollectionElementNature() ); - } - } - } - - private void resolveBasicCollectionElement(BasicCollectionElement basicCollectionElement) { - Type resolvedHibernateType = determineSingularTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() ); - if ( resolvedHibernateType != null ) { - pushHibernateTypeInformationDownIfNeeded( - basicCollectionElement.getHibernateTypeDescriptor(), - basicCollectionElement.getElementValue(), - resolvedHibernateType - ); - } - } - - private Type getHeuristicType(String typeName, Properties typeParameters) { - if ( typeName != null ) { - try { - return metadata.getTypeResolver().heuristicType( typeName, typeParameters ); - } - catch (Exception ignore) { - } - } - - return null; - } - - private void pushHibernateTypeInformationDownIfNeeded(SingularAttributeBinding attributeBinding, Type resolvedHibernateType) { - - final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); - final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() ); - final Value value = attributeBinding.getValue(); - if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { - singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); - } - - // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - this.pushHibernateTypeInformationDownIfNeeded( - hibernateTypeDescriptor, value, resolvedHibernateType - ); - } - - private void pushHibernateTypeInformationDownIfNeeded( - HibernateTypeDescriptor hibernateTypeDescriptor, - Value value, - Type resolvedHibernateType) { - if ( resolvedHibernateType == null ) { - return; - } - if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) { - hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType ); - } - - // java type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - if ( hibernateTypeDescriptor.getJavaTypeName() == null ) { - hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() ); - } - - // todo : this can be made a lot smarter, but for now this will suffice. currently we only handle single value bindings - - if ( SimpleValue.class.isInstance( value ) ) { - SimpleValue simpleValue = ( SimpleValue ) value; - if ( simpleValue.getDatatype() == null ) { - simpleValue.setDatatype( - new Datatype( - resolvedHibernateType.sqlTypes( metadata )[0], - resolvedHibernateType.getName(), - resolvedHibernateType.getReturnedClass() - ) - ); - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java deleted file mode 100644 index 1b6936703164..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/IdentifierGeneratorResolver.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.io.Serializable; -import java.util.Properties; - -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.cfg.ObjectNameNormalizer; -import org.hibernate.engine.config.spi.ConfigurationService; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MetadataImplementor; - -/** - * @author Gail Badner - */ -public class IdentifierGeneratorResolver { - - private final MetadataImplementor metadata; - - IdentifierGeneratorResolver(MetadataImplementor metadata) { - this.metadata = metadata; - } - - // IdentifierGeneratorResolver.resolve() must execute after AttributeTypeResolver.resolve() - // to ensure that identifier type is resolved. - @SuppressWarnings( {"unchecked"} ) - void resolve() { - for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { - if ( entityBinding.isRoot() ) { - Properties properties = new Properties( ); - properties.putAll( - metadata.getServiceRegistry() - .getService( ConfigurationService.class ) - .getSettings() - ); - //TODO: where should these be added??? - if ( ! properties.contains( AvailableSettings.PREFER_POOLED_VALUES_LO ) ) { - properties.put( AvailableSettings.PREFER_POOLED_VALUES_LO, "false" ); - } - if ( ! properties.contains( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER ) ) { - properties.put( - PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, - new ObjectNameNormalizerImpl( metadata ) - ); - } - entityBinding.getHierarchyDetails().getEntityIdentifier().createIdentifierGenerator( - metadata.getIdentifierGeneratorFactory(), - properties - ); - } - } - } - - private static class ObjectNameNormalizerImpl extends ObjectNameNormalizer implements Serializable { - private final boolean useQuotedIdentifiersGlobally; - private final NamingStrategy namingStrategy; - - private ObjectNameNormalizerImpl(MetadataImplementor metadata ) { - this.useQuotedIdentifiersGlobally = metadata.isGloballyQuotedIdentifiers(); - this.namingStrategy = metadata.getNamingStrategy(); - } - - @Override - protected boolean isUseQuotedIdentifiersGlobally() { - return useQuotedIdentifiersGlobally; - } - - @Override - protected NamingStrategy getNamingStrategy() { - return namingStrategy; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java deleted file mode 100644 index 44f9874fcd8d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/JaxbHelper.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.internal; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.ValidationEvent; -import javax.xml.bind.ValidationEventHandler; -import javax.xml.bind.ValidationEventLocator; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.XMLEvent; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.XsdException; - -import org.jboss.logging.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -/** - * Helper class for unmarshalling xml configuration using StAX and JAXB. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - */ -public class JaxbHelper { - private static final Logger log = Logger.getLogger( JaxbHelper.class ); - - public static final String ASSUMED_ORM_XSD_VERSION = "2.0"; - - private final MetadataSources metadataSources; - - public JaxbHelper(MetadataSources metadataSources) { - this.metadataSources = metadataSources; - } - - public JaxbRoot unmarshal(InputStream stream, Origin origin) { - try { - XMLEventReader staxReader = staxFactory().createXMLEventReader( stream ); - try { - return unmarshal( staxReader, origin ); - } - finally { - try { - staxReader.close(); - } - catch ( Exception ignore ) { - } - } - } - catch ( XMLStreamException e ) { - throw new MappingException( "Unable to create stax reader", e, origin ); - } - } - - private XMLInputFactory staxFactory; - - private XMLInputFactory staxFactory() { - if ( staxFactory == null ) { - staxFactory = buildStaxFactory(); - } - return staxFactory; - } - - @SuppressWarnings( { "UnnecessaryLocalVariable" }) - private XMLInputFactory buildStaxFactory() { - XMLInputFactory staxFactory = XMLInputFactory.newInstance(); - return staxFactory; - } - - private static final QName ORM_VERSION_ATTRIBUTE_QNAME = new QName( "version" ); - - @SuppressWarnings( { "unchecked" }) - private JaxbRoot unmarshal(XMLEventReader staxEventReader, final Origin origin) { - XMLEvent event; - try { - event = staxEventReader.peek(); - while ( event != null && !event.isStartElement() ) { - staxEventReader.nextEvent(); - event = staxEventReader.peek(); - } - } - catch ( Exception e ) { - throw new MappingException( "Error accessing stax stream", e, origin ); - } - - if ( event == null ) { - throw new MappingException( "Could not locate root element", origin ); - } - - final Schema validationSchema; - final Class jaxbTarget; - - final String elementName = event.asStartElement().getName().getLocalPart(); - - if ( "entity-mappings".equals( elementName ) ) { - final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME ); - final String explicitVersion = attribute == null ? null : attribute.getValue(); - validationSchema = resolveSupportedOrmXsd( explicitVersion ); - jaxbTarget = JaxbEntityMappings.class; - } - else { - validationSchema = hbmSchema(); - jaxbTarget = JaxbHibernateMapping.class; - } - - final Object target; - final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler(); - try { - JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema( validationSchema ); - unmarshaller.setEventHandler( handler ); - target = unmarshaller.unmarshal( staxEventReader ); - } - - catch ( JAXBException e ) { - StringBuilder builder = new StringBuilder(); - builder.append( "Unable to perform unmarshalling at line number " ); - builder.append( handler.getLineNumber() ); - builder.append( " and column " ); - builder.append( handler.getColumnNumber() ); - builder.append( ". Message: " ); - builder.append( handler.getMessage() ); - throw new MappingException( builder.toString(), e, origin ); - } - - return new JaxbRoot( target, origin ); - } - - @SuppressWarnings( { "unchecked" }) - public JaxbRoot unmarshal(Document document, Origin origin) { - Element rootElement = document.getDocumentElement(); - if ( rootElement == null ) { - throw new MappingException( "No root element found", origin ); - } - - final Schema validationSchema; - final Class jaxbTarget; - - if ( "entity-mappings".equals( rootElement.getNodeName() ) ) { - final String explicitVersion = rootElement.getAttribute( "version" ); - validationSchema = resolveSupportedOrmXsd( explicitVersion ); - jaxbTarget = JaxbEntityMappings.class; - } - else { - validationSchema = hbmSchema(); - jaxbTarget = JaxbHibernateMapping.class; - } - - final Object target; - try { - JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema( validationSchema ); - target = unmarshaller.unmarshal( new DOMSource( document ) ); - } - catch ( JAXBException e ) { - throw new MappingException( "Unable to perform unmarshalling", e, origin ); - } - - return new JaxbRoot( target, origin ); - } - - private Schema resolveSupportedOrmXsd(String explicitVersion) { - final String xsdVersionString = explicitVersion == null ? ASSUMED_ORM_XSD_VERSION : explicitVersion; - if ( "1.0".equals( xsdVersionString ) ) { - return orm1Schema(); - } - else if ( "2.0".equals( xsdVersionString ) ) { - return orm2Schema(); - } - throw new IllegalArgumentException( "Unsupported orm.xml XSD version encountered [" + xsdVersionString + "]" ); - } - - public static final String HBM_SCHEMA_NAME = "org/hibernate/hibernate-mapping-4.0.xsd"; - public static final String ORM_1_SCHEMA_NAME = "org/hibernate/jpa/orm_1_0.xsd"; - public static final String ORM_2_SCHEMA_NAME = "org/hibernate/jpa/orm_2_0.xsd"; - - private Schema hbmSchema; - - private Schema hbmSchema() { - if ( hbmSchema == null ) { - hbmSchema = resolveLocalSchema( HBM_SCHEMA_NAME ); - } - return hbmSchema; - } - - private Schema orm1Schema; - - private Schema orm1Schema() { - if ( orm1Schema == null ) { - orm1Schema = resolveLocalSchema( ORM_1_SCHEMA_NAME ); - } - return orm1Schema; - } - - private Schema orm2Schema; - - private Schema orm2Schema() { - if ( orm2Schema == null ) { - orm2Schema = resolveLocalSchema( ORM_2_SCHEMA_NAME ); - } - return orm2Schema; - } - - private Schema resolveLocalSchema(String schemaName) { - return resolveLocalSchema( schemaName, XMLConstants.W3C_XML_SCHEMA_NS_URI ); - } - - private Schema resolveLocalSchema(String schemaName, String schemaLanguage) { - URL url = metadataSources.getServiceRegistry() - .getService( ClassLoaderService.class ) - .locateResource( schemaName ); - if ( url == null ) { - throw new XsdException( "Unable to locate schema [" + schemaName + "] via classpath", schemaName ); - } - try { - InputStream schemaStream = url.openStream(); - try { - StreamSource source = new StreamSource( url.openStream() ); - SchemaFactory schemaFactory = SchemaFactory.newInstance( schemaLanguage ); - return schemaFactory.newSchema( source ); - } - catch ( SAXException e ) { - throw new XsdException( "Unable to load schema [" + schemaName + "]", e, schemaName ); - } - catch ( IOException e ) { - throw new XsdException( "Unable to load schema [" + schemaName + "]", e, schemaName ); - } - finally { - try { - schemaStream.close(); - } - catch ( IOException e ) { - log.debugf( "Problem closing schema stream [%s]", e.toString() ); - } - } - } - catch ( IOException e ) { - throw new XsdException( "Stream error handling schema url [" + url.toExternalForm() + "]", schemaName ); - } - } - - static class ContextProvidingValidationEventHandler implements ValidationEventHandler { - private int lineNumber; - private int columnNumber; - private String message; - - @Override - public boolean handleEvent(ValidationEvent validationEvent) { - ValidationEventLocator locator = validationEvent.getLocator(); - lineNumber = locator.getLineNumber(); - columnNumber = locator.getColumnNumber(); - message = validationEvent.getMessage(); - return false; - } - - public int getLineNumber() { - return lineNumber; - } - - public int getColumnNumber() { - return columnNumber; - } - - public String getMessage() { - return message; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataBuilderImpl.java deleted file mode 100644 index ae7818fe1ed5..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataBuilderImpl.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import javax.persistence.SharedCacheMode; - -import org.hibernate.HibernateException; -import org.hibernate.boot.registry.BootstrapServiceRegistry; -import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.EJB3NamingStrategy; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.engine.config.spi.ConfigurationService; -import org.hibernate.metamodel.Metadata; -import org.hibernate.metamodel.MetadataBuilder; -import org.hibernate.metamodel.MetadataSourceProcessingOrder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.service.ServiceRegistry; - -import org.jboss.logging.Logger; - -/** - * @author Steve Ebersole - */ -public class MetadataBuilderImpl implements MetadataBuilder { - private static final Logger log = Logger.getLogger( MetadataBuilderImpl.class ); - - private final MetadataSources sources; - private final OptionsImpl options; - - public MetadataBuilderImpl(MetadataSources sources) { - this( - sources, - getStandardServiceRegistry( sources.getServiceRegistry() ) - ); - } - - private static StandardServiceRegistry getStandardServiceRegistry(ServiceRegistry serviceRegistry) { - if ( serviceRegistry == null ) { - throw new HibernateException( "ServiceRegistry passed to MetadataBuilder cannot be null" ); - } - - if ( StandardServiceRegistry.class.isInstance( serviceRegistry ) ) { - return ( StandardServiceRegistry ) serviceRegistry; - } - else if ( BootstrapServiceRegistry.class.isInstance( serviceRegistry ) ) { - log.debugf( - "ServiceRegistry passed to MetadataBuilder was a BootstrapServiceRegistry; this likely wont end well" + - "if attempt is made to build SessionFactory" - ); - return new StandardServiceRegistryBuilder( (BootstrapServiceRegistry) serviceRegistry ).build(); - } - else { - throw new HibernateException( - String.format( - "Unexpected type of ServiceRegistry [%s] encountered in attempt to build MetadataBuilder", - serviceRegistry.getClass().getName() - ) - ); - } - } - - public MetadataBuilderImpl(MetadataSources sources, StandardServiceRegistry serviceRegistry) { - this.sources = sources; - this.options = new OptionsImpl( serviceRegistry ); - } - - @Override - public MetadataBuilder with(NamingStrategy namingStrategy) { - this.options.namingStrategy = namingStrategy; - return this; - } - - @Override - public MetadataBuilder with(MetadataSourceProcessingOrder metadataSourceProcessingOrder) { - this.options.metadataSourceProcessingOrder = metadataSourceProcessingOrder; - return this; - } - - @Override - public MetadataBuilder with(SharedCacheMode sharedCacheMode) { - this.options.sharedCacheMode = sharedCacheMode; - return this; - } - - @Override - public MetadataBuilder with(AccessType accessType) { - this.options.defaultCacheAccessType = accessType; - return this; - } - - @Override - public MetadataBuilder withNewIdentifierGeneratorsEnabled(boolean enabled) { - this.options.useNewIdentifierGenerators = enabled; - return this; - } - - @Override - public Metadata build() { - return new MetadataImpl( sources, options ); - } - - public static class OptionsImpl implements Metadata.Options { - private final StandardServiceRegistry serviceRegistry; - - private MetadataSourceProcessingOrder metadataSourceProcessingOrder = MetadataSourceProcessingOrder.HBM_FIRST; - private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE; - private SharedCacheMode sharedCacheMode = SharedCacheMode.ENABLE_SELECTIVE; - private AccessType defaultCacheAccessType; - private boolean useNewIdentifierGenerators; - private boolean globallyQuotedIdentifiers; - private String defaultSchemaName; - private String defaultCatalogName; - - public OptionsImpl(StandardServiceRegistry serviceRegistry) { - this.serviceRegistry = serviceRegistry; - - ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class ); - - // cache access type - defaultCacheAccessType = configService.getSetting( - AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY, - new ConfigurationService.Converter() { - @Override - public AccessType convert(Object value) { - return AccessType.fromExternalName( value.toString() ); - } - } - ); - - useNewIdentifierGenerators = configService.getSetting( - AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, - new ConfigurationService.Converter() { - @Override - public Boolean convert(Object value) { - return Boolean.parseBoolean( value.toString() ); - } - }, - false - ); - - defaultSchemaName = configService.getSetting( - AvailableSettings.DEFAULT_SCHEMA, - new ConfigurationService.Converter() { - @Override - public String convert(Object value) { - return value.toString(); - } - }, - null - ); - - defaultCatalogName = configService.getSetting( - AvailableSettings.DEFAULT_CATALOG, - new ConfigurationService.Converter() { - @Override - public String convert(Object value) { - return value.toString(); - } - }, - null - ); - - globallyQuotedIdentifiers = configService.getSetting( - AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, - new ConfigurationService.Converter() { - @Override - public Boolean convert(Object value) { - return Boolean.parseBoolean( value.toString() ); - } - }, - false - ); - } - - @Override - public StandardServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - @Override - public MetadataSourceProcessingOrder getMetadataSourceProcessingOrder() { - return metadataSourceProcessingOrder; - } - - @Override - public NamingStrategy getNamingStrategy() { - return namingStrategy; - } - - @Override - public AccessType getDefaultAccessType() { - return defaultCacheAccessType; - } - - @Override - public SharedCacheMode getSharedCacheMode() { - return sharedCacheMode; - } - - @Override - public boolean useNewIdentifierGenerators() { - return useNewIdentifierGenerators; - } - - @Override - public boolean isGloballyQuotedIdentifiers() { - return globallyQuotedIdentifiers; - } - - @Override - public String getDefaultSchemaName() { - return defaultSchemaName; - } - - @Override - public String getDefaultCatalogName() { - return defaultCatalogName; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java deleted file mode 100644 index 8de41ed46534..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/MetadataImpl.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.AssertionFailure; -import org.hibernate.DuplicateMappingException; -import org.hibernate.MappingException; -import org.hibernate.SessionFactory; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cache.spi.RegionFactory; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.NamedQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.MetadataSourceProcessingOrder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.SessionFactoryBuilder; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.FetchProfile; -import org.hibernate.metamodel.binding.IdGenerator; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.binding.TypeDef; -import org.hibernate.metamodel.domain.BasicType; -import org.hibernate.metamodel.domain.Type; -import org.hibernate.metamodel.relational.Database; -import org.hibernate.metamodel.source.MappingDefaults; -import org.hibernate.metamodel.source.MetaAttributeContext; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.MetadataSourceProcessor; -import org.hibernate.metamodel.source.annotations.AnnotationMetadataSourceProcessorImpl; -import org.hibernate.metamodel.source.hbm.HbmMetadataSourceProcessorImpl; -import org.hibernate.persister.spi.PersisterClassResolver; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.type.TypeResolver; - -import org.jboss.logging.Logger; - -/** - * Container for configuration data collected during binding the metamodel. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - * @author Gail Badner - */ -public class MetadataImpl implements MetadataImplementor, Serializable { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - MetadataImpl.class.getName() - ); - - private final ServiceRegistry serviceRegistry; - private final Options options; - - private final ValueHolder classLoaderService; - private final ValueHolder persisterClassResolverService; - - private TypeResolver typeResolver = new TypeResolver(); - - private final MutableIdentifierGeneratorFactory identifierGeneratorFactory; - - private final Database database; - - private final MappingDefaults mappingDefaults; - - /** - * Maps the fully qualified class name of an entity to its entity binding - */ - private Map entityBindingMap = new HashMap(); - - private Map collectionBindingMap = new HashMap(); - private Map fetchProfiles = new HashMap(); - private Map imports = new HashMap(); - private Map typeDefs = new HashMap(); - private Map idGenerators = new HashMap(); - private Map namedQueryDefs = new HashMap(); - private Map namedNativeQueryDefs = new HashMap(); - private Map resultSetMappings = new HashMap(); - private Map filterDefs = new HashMap(); - - private boolean globallyQuotedIdentifiers = false; - - public MetadataImpl(MetadataSources metadataSources, Options options) { - this.serviceRegistry = options.getServiceRegistry(); - this.options = options; - this.identifierGeneratorFactory = serviceRegistry.getService( MutableIdentifierGeneratorFactory.class ); - //new DefaultIdentifierGeneratorFactory( dialect ); - this.database = new Database( options ); - - this.mappingDefaults = new MappingDefaultsImpl(); - - final MetadataSourceProcessor[] metadataSourceProcessors; - if ( options.getMetadataSourceProcessingOrder() == MetadataSourceProcessingOrder.HBM_FIRST ) { - metadataSourceProcessors = new MetadataSourceProcessor[] { - new HbmMetadataSourceProcessorImpl( this ), - new AnnotationMetadataSourceProcessorImpl( this ) - }; - } - else { - metadataSourceProcessors = new MetadataSourceProcessor[] { - new AnnotationMetadataSourceProcessorImpl( this ), - new HbmMetadataSourceProcessorImpl( this ) - }; - } - - this.classLoaderService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public ClassLoaderService initialize() { - return serviceRegistry.getService( ClassLoaderService.class ); - } - } - ); - this.persisterClassResolverService = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public PersisterClassResolver initialize() { - return serviceRegistry.getService( PersisterClassResolver.class ); - } - } - ); - - - final ArrayList processedEntityNames = new ArrayList(); - - prepare( metadataSourceProcessors, metadataSources ); - bindIndependentMetadata( metadataSourceProcessors, metadataSources ); - bindTypeDependentMetadata( metadataSourceProcessors, metadataSources ); - bindMappingMetadata( metadataSourceProcessors, metadataSources, processedEntityNames ); - bindMappingDependentMetadata( metadataSourceProcessors, metadataSources ); - - // todo : remove this by coordinated ordering of entity processing - new AssociationResolver( this ).resolve(); - new HibernateTypeResolver( this ).resolve(); - // IdentifierGeneratorResolver.resolve() must execute after AttributeTypeResolver.resolve() - new IdentifierGeneratorResolver( this ).resolve(); - } - - private void prepare(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.prepare( metadataSources ); - } - } - - private void bindIndependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processIndependentMetadata( metadataSources ); - } - } - - private void bindTypeDependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processTypeDependentMetadata( metadataSources ); - } - } - - private void bindMappingMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources, List processedEntityNames) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processMappingMetadata( metadataSources, processedEntityNames ); - } - } - - private void bindMappingDependentMetadata(MetadataSourceProcessor[] metadataSourceProcessors, MetadataSources metadataSources) { - for ( MetadataSourceProcessor metadataSourceProcessor : metadataSourceProcessors ) { - metadataSourceProcessor.processMappingDependentMetadata( metadataSources ); - } - } - - @Override - public void addFetchProfile(FetchProfile profile) { - if ( profile == null || profile.getName() == null ) { - throw new IllegalArgumentException( "Fetch profile object or name is null: " + profile ); - } - fetchProfiles.put( profile.getName(), profile ); - } - - @Override - public void addFilterDefinition(FilterDefinition def) { - if ( def == null || def.getFilterName() == null ) { - throw new IllegalArgumentException( "Filter definition object or name is null: " + def ); - } - filterDefs.put( def.getFilterName(), def ); - } - - public Iterable getFilterDefinitions() { - return filterDefs.values(); - } - - @Override - public void addIdGenerator(IdGenerator generator) { - if ( generator == null || generator.getName() == null ) { - throw new IllegalArgumentException( "ID generator object or name is null." ); - } - idGenerators.put( generator.getName(), generator ); - } - - @Override - public IdGenerator getIdGenerator(String name) { - if ( name == null ) { - throw new IllegalArgumentException( "null is not a valid generator name" ); - } - return idGenerators.get( name ); - } - @Override - public void registerIdentifierGenerator(String name, String generatorClassName) { - identifierGeneratorFactory.register( name, classLoaderService().classForName( generatorClassName ) ); - } - - @Override - public void addNamedNativeQuery(NamedSQLQueryDefinition def) { - if ( def == null || def.getName() == null ) { - throw new IllegalArgumentException( "Named native query definition object or name is null: " + def.getQueryString() ); - } - namedNativeQueryDefs.put( def.getName(), def ); - } - - public NamedSQLQueryDefinition getNamedNativeQuery(String name) { - if ( name == null ) { - throw new IllegalArgumentException( "null is not a valid native query name" ); - } - return namedNativeQueryDefs.get( name ); - } - - @Override - public Iterable getNamedNativeQueryDefinitions() { - return namedNativeQueryDefs.values(); - } - - @Override - public void addNamedQuery(NamedQueryDefinition def) { - if ( def == null ) { - throw new IllegalArgumentException( "Named query definition is null" ); - } - else if ( def.getName() == null ) { - throw new IllegalArgumentException( "Named query definition name is null: " + def.getQueryString() ); - } - namedQueryDefs.put( def.getName(), def ); - } - - public NamedQueryDefinition getNamedQuery(String name) { - if ( name == null ) { - throw new IllegalArgumentException( "null is not a valid query name" ); - } - return namedQueryDefs.get( name ); - } - - @Override - public Iterable getNamedQueryDefinitions() { - return namedQueryDefs.values(); - } - - @Override - public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition) { - if ( resultSetMappingDefinition == null || resultSetMappingDefinition.getName() == null ) { - throw new IllegalArgumentException( "Result-set mapping object or name is null: " + resultSetMappingDefinition ); - } - resultSetMappings.put( resultSetMappingDefinition.getName(), resultSetMappingDefinition ); - } - - @Override - public Iterable getResultSetMappingDefinitions() { - return resultSetMappings.values(); - } - - @Override - public void addTypeDefinition(TypeDef typeDef) { - if ( typeDef == null ) { - throw new IllegalArgumentException( "Type definition is null" ); - } - else if ( typeDef.getName() == null ) { - throw new IllegalArgumentException( "Type definition name is null: " + typeDef.getTypeClass() ); - } - final TypeDef previous = typeDefs.put( typeDef.getName(), typeDef ); - if ( previous != null ) { - LOG.debugf( "Duplicate typedef name [%s] now -> %s", typeDef.getName(), typeDef.getTypeClass() ); - } - } - - @Override - public Iterable getTypeDefinitions() { - return typeDefs.values(); - } - - @Override - public TypeDef getTypeDefinition(String name) { - return typeDefs.get( name ); - } - - private ClassLoaderService classLoaderService() { - return classLoaderService.getValue(); - } - - private PersisterClassResolver persisterClassResolverService() { - return persisterClassResolverService.getValue(); - } - - @Override - public Options getOptions() { - return options; - } - - @Override - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - @Override - @SuppressWarnings( {"unchecked"}) - public Class locateClassByName(String name) { - return classLoaderService().classForName( name ); - } - - @Override - public Type makeJavaType(String className) { - // todo : have this perform some analysis of the incoming type name to determine appropriate return - return new BasicType( className, makeClassReference( className ) ); - } - - @Override - public ValueHolder> makeClassReference(final String className) { - return new ValueHolder>( - new ValueHolder.DeferredInitializer>() { - @Override - public Class initialize() { - return classLoaderService.getValue().classForName( className ); - } - } - ); - } - - @Override - public String qualifyClassName(String name) { - return name; - } - - @Override - public Database getDatabase() { - return database; - } - - public EntityBinding getEntityBinding(String entityName) { - return entityBindingMap.get( entityName ); - } - - @Override - public EntityBinding getRootEntityBinding(String entityName) { - EntityBinding binding = entityBindingMap.get( entityName ); - if ( binding == null ) { - throw new IllegalStateException( "Unknown entity binding: " + entityName ); - } - - do { - if ( binding.isRoot() ) { - return binding; - } - binding = binding.getSuperEntityBinding(); - } while ( binding != null ); - - throw new AssertionFailure( "Entity binding has no root: " + entityName ); - } - - public Iterable getEntityBindings() { - return entityBindingMap.values(); - } - - public void addEntity(EntityBinding entityBinding) { - final String entityName = entityBinding.getEntity().getName(); - if ( entityBindingMap.containsKey( entityName ) ) { - throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, entityName ); - } - entityBindingMap.put( entityName, entityBinding ); - } - - public PluralAttributeBinding getCollection(String collectionRole) { - return collectionBindingMap.get( collectionRole ); - } - - @Override - public Iterable getCollectionBindings() { - return collectionBindingMap.values(); - } - - public void addCollection(PluralAttributeBinding pluralAttributeBinding) { - final String owningEntityName = pluralAttributeBinding.getContainer().getPathBase(); - final String attributeName = pluralAttributeBinding.getAttribute().getName(); - final String collectionRole = owningEntityName + '.' + attributeName; - if ( collectionBindingMap.containsKey( collectionRole ) ) { - throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, collectionRole ); - } - collectionBindingMap.put( collectionRole, pluralAttributeBinding ); - } - - public void addImport(String importName, String entityName) { - if ( importName == null || entityName == null ) { - throw new IllegalArgumentException( "Import name or entity name is null" ); - } - LOG.tracev( "Import: {0} -> {1}", importName, entityName ); - String old = imports.put( importName, entityName ); - if ( old != null ) { - LOG.debug( "import name [" + importName + "] overrode previous [{" + old + "}]" ); - } - } - - @Override - public Iterable> getImports() { - return imports.entrySet(); - } - - @Override - public Iterable getFetchProfiles() { - return fetchProfiles.values(); - } - - public TypeResolver getTypeResolver() { - return typeResolver; - } - - @Override - public SessionFactoryBuilder getSessionFactoryBuilder() { - return new SessionFactoryBuilderImpl( this ); - } - - @Override - public SessionFactory buildSessionFactory() { - return getSessionFactoryBuilder().build(); - } - - @Override - public NamingStrategy getNamingStrategy() { - return options.getNamingStrategy(); - } - - @Override - public boolean isGloballyQuotedIdentifiers() { - return globallyQuotedIdentifiers || getOptions().isGloballyQuotedIdentifiers(); - } - - public void setGloballyQuotedIdentifiers(boolean globallyQuotedIdentifiers){ - this.globallyQuotedIdentifiers = globallyQuotedIdentifiers; - } - - @Override - public MappingDefaults getMappingDefaults() { - return mappingDefaults; - } - - private final MetaAttributeContext globalMetaAttributeContext = new MetaAttributeContext(); - - @Override - public MetaAttributeContext getGlobalMetaAttributeContext() { - return globalMetaAttributeContext; - } - - @Override - public MetadataImplementor getMetadataImplementor() { - return this; - } - - private static final String DEFAULT_IDENTIFIER_COLUMN_NAME = "id"; - private static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class"; - private static final String DEFAULT_CASCADE = "none"; - private static final String DEFAULT_PROPERTY_ACCESS = "property"; - - @Override - public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return identifierGeneratorFactory; - } - - @Override - public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { - EntityBinding entityBinding = getEntityBinding( entityName ); - if ( entityBinding == null ) { - throw new MappingException( "Entity binding not known: " + entityName ); - } - return entityBinding - .getHierarchyDetails() - .getEntityIdentifier() - .getValueBinding() - .getHibernateTypeDescriptor() - .getResolvedTypeMapping(); - } - - @Override - public String getIdentifierPropertyName(String entityName) throws MappingException { - EntityBinding entityBinding = getEntityBinding( entityName ); - if ( entityBinding == null ) { - throw new MappingException( "Entity binding not known: " + entityName ); - } - AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - return idBinding == null ? null : idBinding.getAttribute().getName(); - } - - @Override - public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { - EntityBinding entityBinding = getEntityBinding( entityName ); - if ( entityBinding == null ) { - throw new MappingException( "Entity binding not known: " + entityName ); - } - // TODO: should this call EntityBinding.getReferencedAttributeBindingString), which does not exist yet? - AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( propertyName ); - if ( attributeBinding == null ) { - throw new MappingException( "unknown property: " + entityName + '.' + propertyName ); - } - return attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); - } - - private class MappingDefaultsImpl implements MappingDefaults { - - @Override - public String getPackageName() { - return null; - } - - @Override - public String getSchemaName() { - return options.getDefaultSchemaName(); - } - - @Override - public String getCatalogName() { - return options.getDefaultCatalogName(); - } - - @Override - public String getIdColumnName() { - return DEFAULT_IDENTIFIER_COLUMN_NAME; - } - - @Override - public String getDiscriminatorColumnName() { - return DEFAULT_DISCRIMINATOR_COLUMN_NAME; - } - - @Override - public String getCascadeStyle() { - return DEFAULT_CASCADE; - } - - @Override - public String getPropertyAccessorName() { - return DEFAULT_PROPERTY_ACCESS; - } - - @Override - public boolean areAssociationsLazy() { - return true; - } - - private final ValueHolder regionFactorySpecifiedDefaultAccessType = new ValueHolder( - new ValueHolder.DeferredInitializer() { - @Override - public AccessType initialize() { - final RegionFactory regionFactory = getServiceRegistry().getService( RegionFactory.class ); - return regionFactory.getDefaultAccessType(); - } - } - ); - - @Override - public AccessType getCacheAccessType() { - return options.getDefaultAccessType() != null - ? options.getDefaultAccessType() - : regionFactorySpecifiedDefaultAccessType.getValue(); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java index 170361272c50..41548e325e52 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/OverriddenMappingDefaults.java @@ -24,7 +24,7 @@ package org.hibernate.metamodel.source.internal; import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.metamodel.source.MappingDefaults; +import org.hibernate.metamodel.source.spi.MappingDefaults; /** * Represents a "nested level" in the mapping defaults stack. @@ -38,6 +38,7 @@ public class OverriddenMappingDefaults implements MappingDefaults { private final String schemaName; private final String catalogName; private final String idColumnName; + private final String tenantIdColumnName; private final String discriminatorColumnName; private final String cascade; private final String propertyAccess; @@ -49,6 +50,7 @@ public OverriddenMappingDefaults( String schemaName, String catalogName, String idColumnName, + String tenantIdColumnName, String discriminatorColumnName, String cascade, String propertyAccess, @@ -61,6 +63,7 @@ public OverriddenMappingDefaults( this.schemaName = schemaName; this.catalogName = catalogName; this.idColumnName = idColumnName; + this.tenantIdColumnName = tenantIdColumnName; this.discriminatorColumnName = discriminatorColumnName; this.cascade = cascade; this.propertyAccess = propertyAccess; @@ -87,6 +90,11 @@ public String getIdColumnName() { return idColumnName == null ? overriddenValues.getIdColumnName() : idColumnName; } + @Override + public String getTenantIdColumnName() { + return tenantIdColumnName == null ? overriddenValues.getTenantIdColumnName() : tenantIdColumnName; + } + @Override public String getDiscriminatorColumnName() { return discriminatorColumnName == null ? overriddenValues.getDiscriminatorColumnName() : discriminatorColumnName; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java deleted file mode 100644 index 85a700a8af43..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import java.io.Serializable; - -import org.hibernate.EmptyInterceptor; -import org.hibernate.Interceptor; -import org.hibernate.ObjectNotFoundException; -import org.hibernate.SessionFactory; -import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.internal.SessionFactoryImpl; -import org.hibernate.metamodel.SessionFactoryBuilder; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.proxy.EntityNotFoundDelegate; - -/** - * @author Gail Badner - */ -public class SessionFactoryBuilderImpl implements SessionFactoryBuilder { - SessionFactoryOptionsImpl options; - - private final MetadataImplementor metadata; - - /* package-protected */ - SessionFactoryBuilderImpl(MetadataImplementor metadata) { - this.metadata = metadata; - options = new SessionFactoryOptionsImpl( metadata.getOptions().getServiceRegistry() ); - } - - @Override - public SessionFactoryBuilder with(Interceptor interceptor) { - this.options.interceptor = interceptor; - return this; - } - - @Override - public SessionFactoryBuilder with(EntityNotFoundDelegate entityNotFoundDelegate) { - this.options.entityNotFoundDelegate = entityNotFoundDelegate; - return this; - } - - @Override - public SessionFactory build() { - return new SessionFactoryImpl(metadata, options, null ); - } - - private static class SessionFactoryOptionsImpl implements SessionFactory.SessionFactoryOptions { - private final StandardServiceRegistry serviceRegistry; - private Interceptor interceptor = EmptyInterceptor.INSTANCE; - - public SessionFactoryOptionsImpl(StandardServiceRegistry serviceRegistry) { - this.serviceRegistry = serviceRegistry; - } - - // TODO: should there be a DefaultEntityNotFoundDelegate.INSTANCE? - private EntityNotFoundDelegate entityNotFoundDelegate = new EntityNotFoundDelegate() { - public void handleEntityNotFound(String entityName, Serializable id) { - throw new ObjectNotFoundException( id, entityName ); - } - }; - - @Override - public StandardServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - @Override - public Interceptor getInterceptor() { - return interceptor; - } - - @Override - public EntityNotFoundDelegate getEntityNotFoundDelegate() { - return entityNotFoundDelegate; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractConstraintSource.java new file mode 100644 index 000000000000..9632825c0377 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractConstraintSource.java @@ -0,0 +1,102 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.metamodel.source.spi.ConstraintSource; + +/** + * @author Hardy Ferentschik + */ +class AbstractConstraintSource implements ConstraintSource { + protected final String name; + protected final String tableName; + protected final List columnNames; + protected final List orderings; + + protected AbstractConstraintSource(String name, String tableName, List columnNames, List orderings) { + this.name = name; + this.tableName = tableName; + this.columnNames = columnNames; + this.orderings = orderings; + } + + @Override + public String name() { + return name; + } + + @Override + public String getTableName() { + return tableName; + } + + @Override + public List columnNames() { + return columnNames; + } + + public List orderings() { + return orderings; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + AbstractConstraintSource that = (AbstractConstraintSource) o; + + if ( columnNames != null ? !columnNames.equals( that.columnNames ) : that.columnNames != null ) { + return false; + } + if ( orderings != null ? !orderings.equals( that.orderings ) : that.orderings != null ) { + return false; + } + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( tableName != null ? !tableName.equals( that.tableName ) : that.tableName != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); + result = 31 * result + ( columnNames != null ? columnNames.hashCode() : 0 ); + result = 31 * result + ( orderings != null ? orderings.hashCode() : 0 ); + return result; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractIdentifierSource.java new file mode 100644 index 000000000000..6ea1ed631805 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractIdentifierSource.java @@ -0,0 +1,87 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; +import java.util.Collections; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractIdentifierSource implements IdentifierSource { + private final RootEntitySourceImpl rootEntitySource; + private final Class lookupIdClass; + + protected AbstractIdentifierSource(RootEntitySourceImpl rootEntitySource) { + this.rootEntitySource = rootEntitySource; + + this.lookupIdClass = resolveLookupIdClass( rootEntitySource ); + } + + private Class resolveLookupIdClass(RootEntitySourceImpl rootEntitySource) { + final AnnotationInstance idClassAnnotation = rootEntitySource.getEntityClass() + .getJavaTypeDescriptor() + .findTypeAnnotation( JPADotNames.ID_CLASS ); + if ( idClassAnnotation == null ) { + return null; + } + + final AnnotationValue idClassValue = idClassAnnotation.value(); + if ( idClassValue == null ) { + return null; + } + + final String idClassName = StringHelper.nullIfEmpty( idClassValue.asString() ); + if ( idClassName == null ) { + return null; + } + + return rootEntitySource.getLocalBindingContext().getServiceRegistry() + .getService( ClassLoaderService.class ) + .classForName( idClassName ); + } + + protected RootEntitySourceImpl rootEntitySource() { + return rootEntitySource; + } + + @Override + public Class getLookupIdClass() { + return lookupIdClass; + } + + @Override + public Collection getToolingHintSources() { + return Collections.emptySet(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeElementSourceAssociationManyToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeElementSourceAssociationManyToManyImpl.java new file mode 100644 index 000000000000..0143d5615af0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeElementSourceAssociationManyToManyImpl.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.engine.FetchTiming; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Gail Badner + */ +public abstract class AbstractPluralAttributeElementSourceAssociationManyToManyImpl + extends AbstractPluralElementSourceAssociationImpl + implements PluralAttributeElementSourceManyToMany { + + + public AbstractPluralAttributeElementSourceAssociationManyToManyImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + } + + @Override + public boolean isUnique() { + return pluralAssociationAttribute().getNature() == AbstractPersistentAttribute.Nature.ONE_TO_MANY; + } + + @Override + public String getReferencedEntityAttributeName() { + // HBM only + return null; + } + + @Override + public FilterSource[] getFilterSources() { + return new FilterSource[0]; //todo + } + + @Override + public String getWhere() { + return pluralAssociationAttribute().getWhereClause(); + } + + @Override + public FetchTiming getFetchTiming() { + return FetchTiming.IMMEDIATE; + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.MANY_TO_MANY; + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( pluralAssociationAttribute().getOrderBy() ); + } + + @Override + public String getOrder() { + return pluralAssociationAttribute().getOrderBy(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeElementSourceImpl.java new file mode 100644 index 000000000000..091c1732e662 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeElementSourceImpl.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; + +/** + * @author Steve Ebersole + * @author Strong Liu + */ +public abstract class AbstractPluralAttributeElementSourceImpl { + private final PluralAttributeSourceImpl pluralAttributeSource; + private final PluralAttribute pluralAttribute; + + public AbstractPluralAttributeElementSourceImpl(PluralAttributeSourceImpl pluralAttributeSource) { + this.pluralAttributeSource = pluralAttributeSource; + this.pluralAttribute = pluralAttributeSource.getPluralAttribute(); + } + + protected PluralAttributeSourceImpl getPluralAttributeSource() { + return pluralAttributeSource; + } + + protected PluralAttribute getPluralAttribute() { + return pluralAttribute; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeIndexSourceImpl.java new file mode 100644 index 000000000000..2842d18b5e11 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralAttributeIndexSourceImpl.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; + +/** + * @author Gail Badner + */ +public abstract class AbstractPluralAttributeIndexSourceImpl implements PluralAttributeIndexSource { + private final PluralAttribute attribute; + + public AbstractPluralAttributeIndexSourceImpl(PluralAttribute attribute) { + this.attribute = attribute; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return new HibernateTypeSource() { + @Override + public String getName() { + return attribute.getIndexDetails().getTypeResolver().getExplicitHibernateTypeName(); + } + + @Override + public Map getParameters() { + return attribute.getIndexDetails().getTypeResolver().getExplicitHibernateTypeParameters(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return attribute.getIndexDetails().getJavaType(); + } + }; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return false; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + protected PluralAttribute pluralAttribute() { + return attribute; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralElementSourceAssociationImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralElementSourceAssociationImpl.java new file mode 100644 index 000000000000..139282228859 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractPluralElementSourceAssociationImpl.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceAssociation; + +/** + * @author Gail Badner + */ +public abstract class AbstractPluralElementSourceAssociationImpl + extends AbstractPluralAttributeElementSourceImpl + implements PluralAttributeElementSourceAssociation { + + private final Set ownedAssociationSources = new HashSet( ); + + public AbstractPluralElementSourceAssociationImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + } + + @Override + public String getReferencedEntityName() { + return pluralAssociationAttribute().getElementDetails().getJavaType().getName().toString(); + } + + @Override + public boolean isIgnoreNotFound() { + return pluralAssociationAttribute().isIgnoreNotFound(); + } + + public AttributeSource getAttributeSource() { + return getPluralAttributeSource(); + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + if ( attributeSource == null ) { + throw new IllegalArgumentException( "attributeSource must be non-null." ); + } + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + return false; + } + + @Override + public Set getCascadeStyles() { + return getPluralAttributeSource().getUnifiedCascadeStyles(); + } + + protected PluralAttribute pluralAssociationAttribute() { + return getPluralAttribute(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractToOneAttributeSourceImpl.java new file mode 100644 index 000000000000..57ad3b4cda23 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AbstractToOneAttributeSourceImpl.java @@ -0,0 +1,147 @@ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.source.internal.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.type.ForeignKeyDirection; + +public abstract class AbstractToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource{ + private final SingularAssociationAttribute associationAttribute; + private final Set unifiedCascadeStyles; + + private SingularAttributeNature singularAttributeNature; + private final Set ownedAssociationSources = new HashSet(); + + public AbstractToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute) { + super( associationAttribute ); + this.associationAttribute = associationAttribute; + this.unifiedCascadeStyles = determineCascadeStyles( associationAttribute ); + } + + private static Set determineCascadeStyles(SingularAssociationAttribute associationAttribute) { + final Set cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( + associationAttribute.getJpaCascadeTypes(), + associationAttribute.getHibernateCascadeTypes(), + associationAttribute.getContext() + ); + if ( associationAttribute.isOrphanRemoval() ) { + cascadeStyles.add( CascadeStyles.DELETE_ORPHAN ); + } + return cascadeStyles; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return singularAttributeNature; + } + + protected SingularAssociationAttribute associationAttribute() { + return associationAttribute; + } + + protected void setSingularAttributeNature(SingularAttributeNature singularAttributeNature) { + if ( this.singularAttributeNature != null ) { + throw new IllegalStateException( "nature is already initialized." ); + } + this.singularAttributeNature = singularAttributeNature; + } + + @Override + public AttributeSource getAttributeSource() { + return this; + } + + @Override + public String getReferencedEntityName() { + return associationAttribute.getTargetTypeName(); + } + + @Override + public boolean isUnique() { + return AbstractPersistentAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() ); + } + + @Override + public boolean isIgnoreNotFound() { + return associationAttribute.isIgnoreNotFound(); + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + if ( attributeSource == null ) { + throw new IllegalArgumentException( "attributeSource must be non-null." ); + } + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + return false; + } + + @Override + public Set getCascadeStyles() { + return unifiedCascadeStyles; + } + + @Override + public FetchTiming getFetchTiming() { + return associationAttribute.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE; + } + + @Override + public FetchStyle getFetchStyle() { + if ( associationAttribute.getFetchStyle() != null ) { + return associationAttribute.getFetchStyle(); + } + else { + return associationAttribute.isLazy() ? FetchStyle.SELECT : FetchStyle.JOIN; + } + } + + @Override + public boolean isUnWrapProxy() { + return associationAttribute.isUnWrapProxy(); + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return singularAttributeNature == SingularAttributeNature.ONE_TO_ONE && !associationAttribute.isOptional() + ? ForeignKeyDirection.FROM_PARENT + : ForeignKeyDirection.TO_PARENT; + } + + @Override + public String toString() { + return "ToOneAttributeSourceImpl{role=" + associationAttribute.getRole().getFullPath() + '}'; + } + + + @Override + public AttributePath getAttributePath() { + return associationAttribute.getPath(); + } + + @Override + public AttributeRole getAttributeRole() { + return associationAttribute.getRole(); + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AggregatedCompositeIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AggregatedCompositeIdentifierSourceImpl.java new file mode 100644 index 000000000000..ca3b9e1e03bd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AggregatedCompositeIdentifierSourceImpl.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; +import java.util.Collections; + +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * @author Hardy Ferentschik + * @author Steve Ebersole + * @author Brett Meyer + */ +class AggregatedCompositeIdentifierSourceImpl + extends AbstractIdentifierSource + implements AggregatedCompositeIdentifierSource { + + private final EmbeddedAttributeSourceImpl componentAttributeSource; + + public AggregatedCompositeIdentifierSourceImpl( + RootEntitySourceImpl rootEntitySource, + EmbeddedAttributeSourceImpl componentAttributeSource) { + super( rootEntitySource ); + this.componentAttributeSource = componentAttributeSource; + } + + @Override + public EmbeddedAttributeSource getIdentifierAttributeSource() { + return componentAttributeSource; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + // annotations do not currently allow generators to be attached to composite identifiers as a whole + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public String getIdClassPropertyAccessorName() { + return componentAttributeSource.getPropertyAccessorName(); + } + + @Override + public Collection getToolingHintSources() { + // not relevant for annotations + return Collections.emptySet(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationAttributeSource.java new file mode 100644 index 000000000000..6a645cc3195f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationAttributeSource.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; + +/** + * @author Steve Ebersole + * @author Strong Liu + */ +public interface AnnotationAttributeSource { + public PersistentAttribute getAnnotatedAttribute(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationBindingContext.java new file mode 100644 index 000000000000..a4930992dddd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationBindingContext.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * Defines an interface for providing additional annotation related context information. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Strong Liu + */ +public interface AnnotationBindingContext extends BindingContext { + IdentifierGeneratorDefinition findIdGenerator(String name); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationBindingContextImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationBindingContextImpl.java new file mode 100644 index 000000000000..2b55c5bcdf8b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationBindingContextImpl.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.spi.BaseDelegatingBindingContext; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * Default implementation of {@code AnnotationBindingContext} + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class AnnotationBindingContextImpl + extends BaseDelegatingBindingContext + implements AnnotationBindingContext { + + public AnnotationBindingContextImpl(BindingContext rootBindingContext) { + super( rootBindingContext ); + } + + @Override + public IdentifierGeneratorDefinition findIdGenerator(String name) { + return getMetadataCollector().getIdGenerator( name ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationMetadataSourceProcessorImpl.java new file mode 100644 index 000000000000..f8f6e0f06a85 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/AnnotationMetadataSourceProcessorImpl.java @@ -0,0 +1,123 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.global.FetchProfileProcessor; +import org.hibernate.metamodel.source.internal.annotations.global.IdGeneratorProcessor; +import org.hibernate.metamodel.source.internal.annotations.global.QueryProcessor; +import org.hibernate.metamodel.source.internal.annotations.global.SqlResultSetProcessor; +import org.hibernate.metamodel.source.internal.annotations.global.TableProcessor; +import org.hibernate.metamodel.source.internal.annotations.util.EntityHierarchyBuilder; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.internal.jandex.PseudoJpaDotNames; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.IndexView; + +/** + * Main class responsible to creating and binding the Hibernate meta-model from annotations. + * This binder only has to deal with the (jandex) annotation index/repository. XML configuration is already processed + * and pseudo annotations are created. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProcessor { + private final AnnotationBindingContext bindingContext; + + public AnnotationMetadataSourceProcessorImpl(BindingContext bindingContext, IndexView jandexView) { + + if ( !jandexView.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ).isEmpty() ) { + // todo : this needs to move to AnnotationBindingContext + // what happens right now is that specifying this in an orm.xml causes it to effect all orm.xmls + bindingContext.getMetadataCollector().setGloballyQuotedIdentifiers( true ); + } + + this.bindingContext = new AnnotationBindingContextImpl( bindingContext ); + } + + @Override + public Iterable extractTypeDefinitionSources() { + List typeDescriptorSources = new ArrayList(); + Collection annotations = JandexHelper.getAnnotations( + bindingContext.getJandexAccess().getIndex(), + HibernateDotNames.TYPE_DEF, + HibernateDotNames.TYPE_DEFS, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance typeDef : annotations ) { + typeDescriptorSources.add( new TypeDescriptorSourceImpl( typeDef, bindingContext ) ); + } + return typeDescriptorSources; + } + + @Override + public Iterable extractFilterDefinitionSources() { + List filterDefinitionSources = new ArrayList(); + Collection annotations = JandexHelper.getAnnotations( + bindingContext.getJandexAccess().getIndex(), + HibernateDotNames.FILTER_DEF, + HibernateDotNames.FILTER_DEFS, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance filterDef : annotations ) { + filterDefinitionSources.add( new FilterDefinitionSourceImpl( filterDef, bindingContext ) ); + } + return filterDefinitionSources; + } + + @Override + public Iterable extractGlobalIdentifierGeneratorSources() { + return IdGeneratorProcessor.extractGlobalIdentifierGeneratorSources( bindingContext ); + } + + @Override + public Collection extractEntityHierarchies() { + // need to order our annotated entities into an order we can process + return EntityHierarchyBuilder.createEntityHierarchies( bindingContext ); + } + + @Override + public void processMappingDependentMetadata() { + TableProcessor.bind( bindingContext ); + FetchProfileProcessor.bind( bindingContext ); + SqlResultSetProcessor.bind( bindingContext ); + QueryProcessor.bind( bindingContext ); + + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/BasicAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/BasicAttributeSourceImpl.java new file mode 100644 index 000000000000..815e913a6bdd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/BasicAttributeSourceImpl.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * @author Steve Ebersole + */ +public class BasicAttributeSourceImpl extends SingularAttributeSourceImpl { + private final List relationalValueSources; + + public BasicAttributeSourceImpl( + BasicAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( attribute ); + + final AttributeOverride override = overrideAndConverterCollector.locateAttributeOverride( + attribute.getPath() + ); + validateAttributeOverride( override ); + + this.relationalValueSources = buildRelationalValueSources( attribute, override ); + } + + protected void validateAttributeOverride(AttributeOverride override) { + + } + + @Override + public BasicAttribute getAnnotatedAttribute() { + return (BasicAttribute) super.getAnnotatedAttribute(); + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.BASIC; + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + + private List buildRelationalValueSources( + BasicAttribute attribute, + AttributeOverride attributeOverride) { + final List relationalValueSources = new ArrayList(); + if ( attribute.getFormulaValue() != null ) { + relationalValueSources.add( new DerivedValueSourceImpl( attribute.getFormulaValue() ) ); + } + else { + final int explicitColumnCount = attribute.getColumnValues().size(); + + if ( explicitColumnCount == 0 ) { + Column overrideColumn = attributeOverride == null ? null : attributeOverride.getImpliedColumn(); + if ( overrideColumn != null + || attribute.getCustomReadFragment() != null + || attribute.getCustomWriteFragment() != null + || attribute.getCheckCondition() != null ) { + relationalValueSources.add( + new ColumnSourceImpl( + overrideColumn, + null, + attribute.getCustomReadFragment(), + attribute.getCustomWriteFragment(), + attribute.getCheckCondition() + ) + ); + } + } + else if ( explicitColumnCount == 1 ) { + Column column = attribute.getColumnValues().get( 0 ); + if ( attributeOverride != null ) { + column.applyColumnValues( attributeOverride.getOverriddenColumnInfo() ); + } + relationalValueSources.add( + new ColumnSourceImpl( + column, + null, + attribute.getCustomReadFragment(), + attribute.getCustomWriteFragment(), + attribute.getCheckCondition() + ) + ); + } + else { + if ( attributeOverride != null ) { + throw attribute.getContainer().getLocalBindingContext().makeMappingException( + "Cannot apply AttributeOverride to attribute mapped to more than one column : " + + attribute.getBackingMember().toString() + ); + } + + for ( Column column : attribute.getColumnValues() ) { + relationalValueSources.add( new ColumnSourceImpl( column, null ) ); + } + } + } + + return relationalValueSources; + } + + @Override + public AttributePath getAttributePath() { + return getAnnotatedAttribute().getPath(); + } + + @Override + public AttributeRole getAttributeRole() { + return getAnnotatedAttribute().getRole(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ColumnSourceImpl.java new file mode 100644 index 000000000000..dc3799fc057a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ColumnSourceImpl.java @@ -0,0 +1,181 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.relational.JdbcDataType; + +/** + * @author Hardy Ferentschik + */ +public class ColumnSourceImpl implements ColumnSource { + private final Column columnValues; + private final String defaultTableName; + private final String readFragment; + private final String writeFragment; + private final String checkCondition; + + public ColumnSourceImpl(Column columnValues) { + this( columnValues, null ); + } + + public ColumnSourceImpl(Column columnValues, String defaultTableName) { + this( columnValues, defaultTableName, null, null, null ); + } + + public ColumnSourceImpl( + Column columnValues, + String defaultTableName, + String readFragment, + String writeFragment, + String checkCondition) { + this.columnValues = columnValues; + this.defaultTableName = defaultTableName; + this.readFragment = readFragment; + this.writeFragment = writeFragment; + this.checkCondition = checkCondition; + } + + public ColumnSourceImpl(AbstractPersistentAttribute attribute, Column columnValues) { + this( attribute, columnValues, null ); + } + + public ColumnSourceImpl(AbstractPersistentAttribute attribute, Column columnValues, String defaultTableName) { + boolean isBasicAttribute = attribute != null && attribute.getNature() == AbstractPersistentAttribute.Nature.BASIC; + this.readFragment = attribute != null && isBasicAttribute ? ( (BasicAttribute) attribute ).getCustomReadFragment() : null; + this.writeFragment = attribute != null && isBasicAttribute ? ( (BasicAttribute) attribute ).getCustomWriteFragment() : null; + this.checkCondition = attribute != null ? attribute.getCheckCondition() : null; + this.columnValues = columnValues; + this.defaultTableName = defaultTableName; + } + + @Override + public Nature getNature() { + return Nature.COLUMN; + } + + @Override + public String getName() { + return columnValues == null ? null : columnValues.getName(); + } + + @Override + public TruthValue isNullable() { + if ( columnValues == null || columnValues.isNullable() == null ) { + return null; + } + return columnValues.isNullable() ? TruthValue.TRUE : TruthValue.FALSE; + } + + @Override + public String getDefaultValue() { + return null; + } + + @Override + public String getSqlType() { + if ( columnValues == null ) { + return null; + } + return columnValues.getColumnDefinition(); + } + + @Override + public JdbcDataType getDatatype() { + return null; + } + + @Override + public SizeSource getSizeSource() { + if ( columnValues == null ) { + return null; + } + return new SizeSourceImpl( + columnValues.getPrecision(), columnValues.getScale(), columnValues.getLength() + ); + } + + @Override + public boolean isUnique() { + return columnValues != null && columnValues.isUnique() != null && columnValues.isUnique(); + } + + @Override + public String getComment() { + return null; + } + + @Override + public TruthValue isIncludedInInsert() { + if ( columnValues == null || columnValues.isInsertable() == null) { + return null; + } + return columnValues.isInsertable() ? TruthValue.TRUE : TruthValue.FALSE; + } + + @Override + public TruthValue isIncludedInUpdate() { + if ( columnValues == null || columnValues.isUpdatable() == null) { + return null; + } + return columnValues.isUpdatable() ? TruthValue.TRUE : TruthValue.FALSE; + } + + @Override + public String getContainingTableName() { + if ( columnValues == null ) { + return defaultTableName; + } + else if ( columnValues.getTable() == null ) { + return defaultTableName; + } + else { + return columnValues.getTable(); + } + } + + // these come from attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public String getReadFragment() { + return readFragment; + } + + @Override + public String getWriteFragment() { + return writeFragment; + } + + @Override + public String getCheckCondition() { + return checkCondition; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DerivedValueSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DerivedValueSourceImpl.java new file mode 100644 index 000000000000..daa22332a409 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DerivedValueSourceImpl.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.attribute.FormulaValue; +import org.hibernate.metamodel.source.spi.DerivedValueSource; + +/** + * @author Strong Liu + * @author Steve Ebersole + */ +public class DerivedValueSourceImpl implements DerivedValueSource { + private final String expression; + private final String containingTableName; + + public DerivedValueSourceImpl(FormulaValue formulaValue) { + this.expression = formulaValue.getExpression(); + this.containingTableName = formulaValue.getContainingTableName(); + } + + public DerivedValueSourceImpl(String expression, String containingTableName) { + this.expression = expression; + this.containingTableName = containingTableName; + } + + @Override + public Nature getNature() { + return Nature.DERIVED; + } + + @Override + public String getExpression() { + return expression; + } + + @Override + public String getContainingTableName() { + return containingTableName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DiscriminatorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DiscriminatorSourceImpl.java new file mode 100644 index 000000000000..cd7518f0e3b2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DiscriminatorSourceImpl.java @@ -0,0 +1,162 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import javax.persistence.DiscriminatorType; + +import org.hibernate.AnnotationException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.DiscriminatorSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class DiscriminatorSourceImpl + extends DiscriminatorSourceSupport + implements DiscriminatorSource { + private final String entityName; + private final Class javaType; + private final RelationalValueSource relationalValueSource; + + private final boolean isFormula; + + public DiscriminatorSourceImpl(EntityTypeMetadata entityTypeMetadata) { + super( entityTypeMetadata ); + this.entityName = entityTypeMetadata.getJavaTypeDescriptor().getName().toString(); + + final ClassLoaderService cls = entityTypeMetadata.getLocalBindingContext() + .getServiceRegistry() + .getService( ClassLoaderService.class ); + + final AnnotationInstance discriminatorColumn = entityTypeMetadata.getJavaTypeDescriptor() + .findTypeAnnotation( JPADotNames.DISCRIMINATOR_COLUMN ); + final AnnotationInstance discriminatorFormula = entityTypeMetadata.getJavaTypeDescriptor() + .findTypeAnnotation( HibernateDotNames.DISCRIMINATOR_FORMULA ); + + DiscriminatorType discriminatorType = DiscriminatorType.STRING; + if ( discriminatorColumn != null && discriminatorFormula != null ) { + // while it is obviously illegal to request both a column and a formula + // as the discriminator, there is a feature here where we allow the + // @DiscriminatorColumn to be used to specify the DiscriminatorType + // for a @DiscriminatorFormula. So the combo is valid as long as + // the @DiscriminatorColumn does not name a column + final AnnotationValue columnNameValue = discriminatorColumn.value( "name" ); + // NOTE : Jandex presents values that have not been specified as null, rather + // than returning the default value. That's actually great for cases like this :) + if ( columnNameValue != null ) { + throw entityTypeMetadata.getLocalBindingContext().makeMappingException( + "Entity hierarchy [" + entityTypeMetadata.getJavaTypeDescriptor().getName().toString() + + "] declared both a @DiscriminatorColumn and a @DiscriminatorFormula " + + "which are mutually exclusive" + ); + } + } + + this.isFormula = discriminatorFormula != null; + if ( isFormula ) { + final String expression = entityTypeMetadata.getLocalBindingContext() + .getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( discriminatorFormula, "value" ); + this.relationalValueSource = new DerivedValueSourceImpl( expression, null ); + } + else { + discriminatorType = entityTypeMetadata.getLocalBindingContext() + .getJandexAccess() + .getTypedValueExtractor( DiscriminatorType.class ) + .extract( discriminatorColumn, "discriminatorType" ); + + final Column column = new Column( null ); + column.setNullable( false ); + column.setName( + entityTypeMetadata.getLocalBindingContext() + .getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( discriminatorColumn, "name" ) + ); + column.setLength( + entityTypeMetadata.getLocalBindingContext() + .getJandexAccess() + .getTypedValueExtractor( Integer.class ) + .extract( discriminatorColumn, "length" ) + ); + column.setColumnDefinition( + entityTypeMetadata.getLocalBindingContext() + .getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( discriminatorColumn, "columnDefinition" ) + ); + + this.relationalValueSource = new ColumnSourceImpl( column ); + } + + switch ( discriminatorType ) { + case STRING: { + javaType = String.class; + break; + } + case CHAR: { + javaType = Character.class; + break; + } + case INTEGER: { + javaType = Integer.class; + break; + } + default: { + throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType ); + } + } + } + + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + return relationalValueSource; + } + + @Override + public String getExplicitHibernateTypeName() { + return javaType.getName(); + } + + @Override + public boolean isInserted() { + return !isFormula && super.isInserted(); + } + + @Override + public String toString() { + return "DiscriminatorSourceImpl{entity=" + entityName + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DiscriminatorSourceSupport.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DiscriminatorSourceSupport.java new file mode 100644 index 000000000000..8f074489a348 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/DiscriminatorSourceSupport.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.spi.DiscriminatorSource; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.DISCRIMINATOR_OPTIONS; + +/** + * @author Steve Ebersole + */ +public abstract class DiscriminatorSourceSupport implements DiscriminatorSource { + private final boolean forced; + private final boolean includedInInsert; + + public DiscriminatorSourceSupport(EntityTypeMetadata entityTypeMetadata) { + final AnnotationInstance discriminatorOptions = entityTypeMetadata.getJavaTypeDescriptor() + .findTypeAnnotation( DISCRIMINATOR_OPTIONS ); + + this.forced = determineWhetherForced( discriminatorOptions ); + this.includedInInsert = determineWhetherToIncludeInInsert( discriminatorOptions ); + } + + @SuppressWarnings("SimplifiableIfStatement") + private static boolean determineWhetherForced(AnnotationInstance discriminatorOptions) { + if ( discriminatorOptions == null ) { + return false; + } + + final AnnotationValue forcedValue = discriminatorOptions.value( "force" ); + if ( forcedValue == null ) { + return false; + } + + return forcedValue.asBoolean(); + } + + @SuppressWarnings("SimplifiableIfStatement") + private static boolean determineWhetherToIncludeInInsert(AnnotationInstance discriminatorOptions) { + if ( discriminatorOptions == null ) { + return true; + } + + final AnnotationValue insertValue = discriminatorOptions.value( "insert" ); + if ( insertValue == null ) { + return true; + } + + return insertValue.asBoolean(); + } + + @Override + public boolean isForced() { + return forced; + } + + @Override + public boolean isInserted() { + return includedInInsert; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EmbeddableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EmbeddableSourceImpl.java new file mode 100644 index 000000000000..bcf776eaae7a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EmbeddableSourceImpl.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.entity.EmbeddableTypeMetadata; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.LocalBindingContext; + +/** + * @author Steve Ebersole + */ +public class EmbeddableSourceImpl implements EmbeddableSource { + private final EmbeddableTypeMetadata embeddableTypeMetadata; + + private final List attributeSources; + + public EmbeddableSourceImpl( + EmbeddableTypeMetadata embeddableTypeMetadata, + SourceHelper.AttributeBuilder attributeBuilder) { + this.embeddableTypeMetadata = embeddableTypeMetadata; + this.attributeSources = SourceHelper.buildAttributeSources( embeddableTypeMetadata, attributeBuilder ); + } + + protected EmbeddableTypeMetadata getEmbeddableTypeMetadata() { + return embeddableTypeMetadata; + } + + @Override + public AttributePath getAttributePathBase() { + return embeddableTypeMetadata.getAttributePathBase(); + } + + @Override + public AttributeRole getAttributeRoleBase() { + return embeddableTypeMetadata.getAttributeRoleBase(); + } + + @Override + public List attributeSources() { + return attributeSources; + } + + @Override + public JavaTypeDescriptor getTypeDescriptor() { + return embeddableTypeMetadata.getJavaTypeDescriptor(); + } + + @Override + public String getParentReferenceAttributeName() { + return embeddableTypeMetadata.getParentReferencingAttributeName(); + } + + @Override + public String getExplicitTuplizerClassName() { + return embeddableTypeMetadata.getCustomTuplizerClassName(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return embeddableTypeMetadata.getLocalBindingContext(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EmbeddedAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EmbeddedAttributeSourceImpl.java new file mode 100644 index 000000000000..9e0effa0be2b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EmbeddedAttributeSourceImpl.java @@ -0,0 +1,194 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.internal.annotations.attribute.EmbeddedAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Annotation backed implementation of {@code EmbeddedAttributeSource}. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class EmbeddedAttributeSourceImpl implements EmbeddedAttributeSource, AnnotationAttributeSource { + private final EmbeddedAttribute attribute; + + private final EmbeddableSource embeddableSource; + + public EmbeddedAttributeSourceImpl( + EmbeddedAttribute attribute, + boolean partOfIdentifier, + boolean partOfPersistentCollection) { + + final SourceHelper.AttributeBuilder attributeBuilder; + if ( partOfIdentifier ) { + attributeBuilder = SourceHelper.IdentifierPathAttributeBuilder.INSTANCE; + } + else if ( partOfPersistentCollection ) { + attributeBuilder = SourceHelper.PluralAttributesDisallowedAttributeBuilder.INSTANCE; + } + else { + attributeBuilder = SourceHelper.StandardAttributeBuilder.INSTANCE; + } + + this.embeddableSource = new EmbeddableSourceImpl( + attribute.getEmbeddableTypeMetadata(), + attributeBuilder + ); + + this.attribute = attribute; + } + + @Override + public EmbeddableSource getEmbeddableSource() { + return embeddableSource; + } + + @Override + public PersistentAttribute getAnnotatedAttribute() { + return attribute; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.COMPOSITE; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public String getName() { + return attribute.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attribute.getPath(); + } + + @Override + public AttributeRole getAttributeRole() { + return attribute.getRole(); + } + + + @Override + public String getPropertyAccessorName() { + // todo : would really rather have binder decipher this... + return StringHelper.isEmpty( attribute.getAccessorStrategy() ) + ? attribute.getAccessType().name().toLowerCase( Locale.ENGLISH ) + : attribute.getAccessorStrategy(); + } + + @Override + public Collection getToolingHintSources() { + // not relevant for annotations + return Collections.emptySet(); + } + + @Override + public String getContainingTableName() { + // none, it is defined on the sub-attributes + return null; + } + + @Override + public List relationalValueSources() { + // none, they are defined on the sub-attributes + return null; + } + + @Override + public HibernateTypeSource getTypeInformation() { + // probably need to check for @Target in EmbeddableTypeMetadata (HF) + return null; + } + + @Override + public PropertyGeneration getGeneration() { + return null; + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return attribute.getNaturalIdMutability(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return true; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public String toString() { + return "EmbeddedAttributeSourceImpl{role=" + attribute.getRole().getFullPath() + + ", embeddable=" + embeddableSource.getTypeDescriptor().getName().toString() + "}"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EntityHierarchySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EntityHierarchySourceImpl.java new file mode 100644 index 000000000000..fa48b878de9a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EntityHierarchySourceImpl.java @@ -0,0 +1,404 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.EntityMode; +import org.hibernate.TruthValue; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.PolymorphismType; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.IdType; +import org.hibernate.metamodel.source.internal.annotations.entity.RootEntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.DiscriminatorSource; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.MultiTenancySource; +import org.hibernate.metamodel.source.spi.VersionAttributeSource; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; + +/** + * Adapt the built ManagedTypeMetadata hierarchy to the "source" hierarchy + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class EntityHierarchySourceImpl implements EntityHierarchySource { + private final InheritanceType inheritanceType; + private final RootEntitySourceImpl rootEntitySource; + + private final IdentifierSource identifierSource; + private final OptimisticLockStyle optimisticLockStyle; + private final VersionAttributeSource versionAttributeSource; + private final DiscriminatorSource discriminatorSource; + + private final Caching caching; + private final Caching naturalIdCaching; + + private final MultiTenancySource multiTenancySource; + + private final String whereClause; + private final String rowId; + private final boolean mutable; + private final boolean useExplicitPolymorphism; + + + public EntityHierarchySourceImpl(RootEntityTypeMetadata root, InheritanceType inheritanceType) { + this.inheritanceType = inheritanceType; + + // this starts the "choreographed" creation of the Entity and MappedSuperclass + // objects making up the hierarchy. See the discussion on + // the RootEntitySourceImpl ctor for details... + this.rootEntitySource = new RootEntitySourceImpl( root, this ); + + this.identifierSource = determineIdentifierSource( root, rootEntitySource ); + + this.optimisticLockStyle = determineOptimisticLockStyle( root ); + this.versionAttributeSource = determineVersionAttributeSource( root ); + this.discriminatorSource = determineDiscriminatorSource( root ); + + this.caching = determineCachingSettings( root ); + this.naturalIdCaching = determineNaturalIdCachingSettings( root ); + + this.multiTenancySource = determineMultiTenancySource( root ); + + // (im)mutability + final AnnotationInstance hibernateImmutableAnnotation = root.getJavaTypeDescriptor() + .findTypeAnnotation( HibernateDotNames.IMMUTABLE ); + this.mutable = ( hibernateImmutableAnnotation == null ); + + // implicit/explicit polymorphism (see HHH-6400) + PolymorphismType polymorphism = PolymorphismType.IMPLICIT; + final AnnotationInstance polymorphismAnnotation = root.getJavaTypeDescriptor() + .findTypeAnnotation( HibernateDotNames.POLYMORPHISM ); + if ( polymorphismAnnotation != null && polymorphismAnnotation.value( "type" ) != null ) { + polymorphism = PolymorphismType.valueOf( polymorphismAnnotation.value( "type" ).asEnum() ); + } + this.useExplicitPolymorphism = ( polymorphism == PolymorphismType.EXPLICIT ); + + // where restriction + final AnnotationInstance whereAnnotation = root.getJavaTypeDescriptor() + .findTypeAnnotation( HibernateDotNames.WHERE ); + this.whereClause = whereAnnotation != null && whereAnnotation.value( "clause" ) != null + ? whereAnnotation.value( "clause" ).asString() + : null; + + this.rowId = root.getRowId(); + } + + private IdentifierSource determineIdentifierSource(RootEntityTypeMetadata root, RootEntitySourceImpl rootSource) { + final IdType idType = root.getIdType(); + + switch ( idType ) { + case SIMPLE: { + return new SimpleIdentifierSourceImpl( + rootSource, + (SingularAttributeSourceImpl) rootSource.getIdentifierAttributes().get( 0 ) + ); + } + case AGGREGATED: { + return new AggregatedCompositeIdentifierSourceImpl( + rootSource, + (EmbeddedAttributeSourceImpl) rootSource.getIdentifierAttributes().get( 0 ) + ); + } + case NON_AGGREGATED: { + return new NonAggregatedCompositeIdentifierSourceImpl( rootSource ); + } + default: { + throw root.getLocalBindingContext().makeMappingException( + "Entity did not define an identifier" + ); + } + } + } + + private Caching determineCachingSettings(EntityTypeMetadata root) { + // I am not so sure that we should be interpreting SharedCacheMode here. + // Caching accepts a TruthValue value for this purpose. Might be better + // to unify this in Binder or in SessionFactoryImpl + + Caching caching = new Caching( TruthValue.UNKNOWN ); + + final AnnotationInstance hibernateCacheAnnotation = root.getJavaTypeDescriptor().findTypeAnnotation( HibernateDotNames.CACHE ); + if ( hibernateCacheAnnotation != null ) { + applyRequestedHibernateCachingValues( caching, hibernateCacheAnnotation ); + return caching; + } + + applyJpaCachingValues( + root.getLocalBindingContext(), + caching, + root.getJavaTypeDescriptor().findTypeAnnotation( JPADotNames.CACHEABLE ) + ); + + return caching; + } + + private void applyRequestedHibernateCachingValues(Caching caching, AnnotationInstance hibernateCacheAnnotation) { + caching.setRequested( TruthValue.TRUE ); + + if ( hibernateCacheAnnotation.value( "usage" ) != null ) { + caching.setAccessType( + CacheConcurrencyStrategy.parse( hibernateCacheAnnotation.value( "usage" ).asEnum() ).toAccessType() + ); + } + + if ( hibernateCacheAnnotation.value( "region" ) != null ) { + caching.setRegion( hibernateCacheAnnotation.value( "region" ).asString() ); + } + + caching.setCacheLazyProperties( + hibernateCacheAnnotation.value( "include" ) != null + && "all".equals( hibernateCacheAnnotation.value( "include" ).asString() ) + ); + } + + private void applyJpaCachingValues( + EntityBindingContext localBindingContext, + Caching caching, + AnnotationInstance jpaCacheableAnnotation) { + // todo : note a fan of applying SharedCacheMode here. + // imo this should be handled by Binder + switch ( localBindingContext.getBuildingOptions().getSharedCacheMode() ) { + case ALL: { + caching.setRequested( TruthValue.TRUE ); + break; + } + case ENABLE_SELECTIVE: { + // In the ENABLE_SELECTIVE case, the @Cacheable annotation must be present + // and its value must be true + if ( jpaCacheableAnnotation == null ) { + // No annotation present, so we do not enable caching + caching.setRequested( TruthValue.FALSE ); + } + else { + boolean value = JandexHelper.getValue( + jpaCacheableAnnotation, + "value", + Boolean.class, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + // we enable caching if the value was true + caching.setRequested( value ? TruthValue.TRUE : TruthValue.FALSE ); + } + break; + } + case DISABLE_SELECTIVE: { + // In the DISABLE_SELECTIVE case we enable caching for all entities + // unless it explicitly says to not too + if ( jpaCacheableAnnotation == null ) { + // No annotation present, so the entity did not explicitly opt out + // of caching + caching.setRequested( TruthValue.TRUE ); + } + else { + boolean value = JandexHelper.getValue( + jpaCacheableAnnotation, + "value", + Boolean.class, + localBindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + // we enable caching if the value was true + caching.setRequested( value ? TruthValue.TRUE : TruthValue.FALSE ); + } + break; + } + default: { + // treat both NONE and UNSPECIFIED the same + caching.setRequested( TruthValue.FALSE ); + break; + } + } + + if ( caching.getRequested() != TruthValue.FALSE ) { + caching.setCacheLazyProperties( true ); + } + } + + private Caching determineNaturalIdCachingSettings(EntityTypeMetadata root) { + Caching naturalIdCaching = new Caching( TruthValue.FALSE ); + + final AnnotationInstance naturalIdCacheAnnotation = root.getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.NATURAL_ID_CACHE + ); + if ( naturalIdCacheAnnotation != null ) { + if ( naturalIdCacheAnnotation.value( "region" ) != null ) { + String region = naturalIdCacheAnnotation.value( "region" ).asString(); + if ( StringHelper.isNotEmpty( region ) ) { + naturalIdCaching.setRegion( region ); + } + } + naturalIdCaching.setRequested( TruthValue.TRUE ); + } + + return naturalIdCaching; + } + + private OptimisticLockStyle determineOptimisticLockStyle(EntityTypeMetadata root) { + OptimisticLockStyle style = OptimisticLockStyle.VERSION; + final AnnotationInstance optimisticLocking = JandexHelper.getSingleAnnotation( + root.getJavaTypeDescriptor().getJandexClassInfo(), + HibernateDotNames.OPTIMISTIC_LOCKING, + ClassInfo.class + ); + if ( optimisticLocking != null && optimisticLocking.value( "type" ) != null ) { + style = OptimisticLockStyle.valueOf( optimisticLocking.value( "type" ).asEnum() ); + } + return style; + } + + private VersionAttributeSource determineVersionAttributeSource(RootEntityTypeMetadata root) { + if ( root.getVersionAttribute() == null ) { + return null; + } + return new VersionAttributeSourceImpl( root.getVersionAttribute(), root ); + } + + private DiscriminatorSource determineDiscriminatorSource(EntityTypeMetadata root) { + switch ( inheritanceType ) { + case JOINED: { + if ( root.containsDiscriminator() ) { + return root.getLocalBindingContext().getBuildingOptions().ignoreExplicitDiscriminatorsForJoinedInheritance() + ? null + : new DiscriminatorSourceImpl( root ); + } + else { + return root.getLocalBindingContext().getBuildingOptions().createImplicitDiscriminatorsForJoinedInheritance() + ? new ImplicitDiscriminatorSourceImpl( root ) + : null; + } + } + case SINGLE_TABLE: { + return root.containsDiscriminator() + ? new DiscriminatorSourceImpl( root ) + : new ImplicitDiscriminatorSourceImpl( root ); + } + case TABLE_PER_CLASS: { + return null; + } + case NO_INHERITANCE: { + return null; + } + default: { + return null; + } + } + } + + private MultiTenancySource determineMultiTenancySource(EntityTypeMetadata root) { + return root.hasMultiTenancySourceInformation() + ? new MutliTenancySourceImpl( root ) + : null; + } + + @Override + public EntitySource getRoot() { + return rootEntitySource; + } + + @Override + public InheritanceType getHierarchyInheritanceType() { + return inheritanceType; + } + + @Override + public IdentifierSource getIdentifierSource() { + return identifierSource; + } + + @Override + public VersionAttributeSource getVersionAttributeSource() { + return versionAttributeSource; + } + + @Override + public DiscriminatorSource getDiscriminatorSource() { + return discriminatorSource; + } + + @Override + public MultiTenancySource getMultiTenancySource() { + return multiTenancySource; + } + + @Override + public EntityMode getEntityMode() { + return EntityMode.POJO; + } + + @Override + public boolean isMutable() { + return mutable; + } + + @Override + public boolean isExplicitPolymorphism() { + return useExplicitPolymorphism; + } + + @Override + public String getWhere() { + return whereClause; + } + + @Override + public String getRowId() { + return rowId; + } + + @Override + public OptimisticLockStyle getOptimisticLockStyle() { + return optimisticLockStyle; + } + + @Override + public Caching getCaching() { + return caching; + } + + @Override + public Caching getNaturalIdCaching() { + return naturalIdCaching; + } + + @Override + public String toString() { + return "EntityHierarchySourceImpl{rootEntitySource=" + rootEntitySource.getEntityName() + + ", inheritanceType=" + inheritanceType + '}'; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EntitySourceImpl.java new file mode 100644 index 000000000000..0f9684a1dd4a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/EntitySourceImpl.java @@ -0,0 +1,596 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; + +import org.hibernate.AnnotationException; +import org.hibernate.MappingException; +import org.hibernate.TruthValue; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.ConstraintSource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.SecondaryTableSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.xml.spi.Origin; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * Common base class for adapting Entity classes to the metamodel source structure. + *

      + * NOTE : defined as abstract because we classify entity mappings more concretely as:

        + *
      • the root of an entity hierarchy
      • + *
      • an entity subclass in an entity hierarchy
      • + *
      + * + * @see MappedSuperclassSourceImpl + * + * @author Hardy Ferentschik + * @author Gail Badner + * @author Steve Ebersole + */ +public abstract class EntitySourceImpl extends IdentifiableTypeSourceAdapter implements EntitySource { + private final String jpaEntityName; + private final FilterSource[] filterSources; + private final TableSpecificationSource primaryTable; + private final EntityBindingContext bindingContext; + private final ClassLoaderService classLoaderService; + + /** + * This is the form for building the root entity. FWIW, the `rootEntity` + * argument is not really needed here + * + * @param entityTypeMetadata The root entity + * @param hierarchy The hierarchy the entity is the root of + * @param rootEntity Whether the entity is a root (it always is here). + */ + public EntitySourceImpl( + EntityTypeMetadata entityTypeMetadata, + EntityHierarchySourceImpl hierarchy, + boolean rootEntity) { + super( entityTypeMetadata, hierarchy, rootEntity ); + + this.jpaEntityName = interpretJpaEntityName( entityTypeMetadata ); + + this.bindingContext = entityTypeMetadata.getLocalBindingContext(); + this.classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + + addImports(); + this.filterSources = buildFilterSources(); + this.primaryTable = resolvePrimaryTable(); + } + + private String interpretJpaEntityName(ManagedTypeMetadata managedTypeMetadata) { + if ( EntityTypeMetadata.class.isInstance( managedTypeMetadata ) ) { + final EntityTypeMetadata entityTypeMetadata = (EntityTypeMetadata) managedTypeMetadata; + if ( StringHelper.isNotEmpty( entityTypeMetadata.getExplicitEntityName() ) ) { + return entityTypeMetadata.getExplicitEntityName(); + } + } + + return StringHelper.unqualify( managedTypeMetadata.getName() ); + } + + /** + * Here is the form for persistent subclasses. + * + * @param managedTypeMetadata + * @param hierarchy + * @param superTypeSource + */ + protected EntitySourceImpl( + EntityTypeMetadata managedTypeMetadata, + EntityHierarchySourceImpl hierarchy, + IdentifiableTypeSourceAdapter superTypeSource) { + super( managedTypeMetadata, hierarchy, superTypeSource ); + + this.jpaEntityName = interpretJpaEntityName( managedTypeMetadata ); + + this.bindingContext = managedTypeMetadata.getLocalBindingContext(); + this.classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + + addImports(); + this.filterSources = buildFilterSources(); + this.primaryTable = resolvePrimaryTable(); + } + + private void addImports() { + try { + final InFlightMetadataCollector metadataImplementor = getEntityClass().getLocalBindingContext() + .getMetadataCollector(); + metadataImplementor.addImport( getJpaEntityName(), getEntityName() ); + if ( !getEntityName().equals( getJpaEntityName() ) ) { + metadataImplementor.addImport( getEntityName(), getEntityName() ); + } + } + catch ( MappingException e ) { + throw new AnnotationException( "Use of the same entity name twice: " + getJpaEntityName(), e ); + } + } + + private FilterSource[] buildFilterSources() { + AnnotationInstance filtersAnnotation = getEntityClass().getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.FILTERS + ); + List filterSourceList = new ArrayList(); + if ( filtersAnnotation != null ) { + AnnotationInstance[] annotationInstances = filtersAnnotation.value().asNestedArray(); + for ( AnnotationInstance filterAnnotation : annotationInstances ) { + FilterSource filterSource = new FilterSourceImpl( filterAnnotation ); + filterSourceList.add( filterSource ); + } + + } + + AnnotationInstance filterAnnotation = getEntityClass().getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.FILTER + ); + if ( filterAnnotation != null ) { + FilterSource filterSource = new FilterSourceImpl( filterAnnotation ); + filterSourceList.add( filterSource ); + } + if ( filterSourceList.isEmpty() ) { + return null; + } + else { + return filterSourceList.toArray( new FilterSource[filterSourceList.size()] ); + } + } + + protected boolean isRootEntity() { + return false; + } + + protected boolean definesItsOwnTable() { + return !InheritanceType.SINGLE_TABLE.equals( getHierarchy().getHierarchyInheritanceType() ) + || isRootEntity(); + } + + private TableSpecificationSource resolvePrimaryTable() { + if ( !definesItsOwnTable() ) { + return null; + } + + // see if we have an inline view + if ( getEntityClass().getJavaTypeDescriptor().findLocalTypeAnnotation( HibernateDotNames.SUB_SELECT ) != null ) { + return new InLineViewSourceImpl( getEntityClass() ); + } + else { + AnnotationInstance tableAnnotation = getEntityClass().getJavaTypeDescriptor().findLocalTypeAnnotation( + JPADotNames.TABLE + ); + return buildPrimaryTable( tableAnnotation, bindingContext ); + } + } + + protected TableSpecificationSource buildPrimaryTable( + AnnotationInstance tableAnnotation, + EntityBindingContext bindingContext) { + return TableSourceImpl.build( tableAnnotation, bindingContext ); + } + + public EntityTypeMetadata getEntityClass() { + return (EntityTypeMetadata) getManagedTypeMetadata(); + } + + @Override + public Origin getOrigin() { + return getEntityClass().getLocalBindingContext().getOrigin(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return getEntityClass().getLocalBindingContext(); + } + + @Override + public String getEntityName() { + return getClassName(); + } + + @Override + public String getClassName() { + return getEntityClass().getName(); + } + + @Override + public String getJpaEntityName() { + return jpaEntityName; + } + + @Override + public TableSpecificationSource getPrimaryTable() { + return primaryTable; + } + + @Override + public boolean isAbstract() { + return getEntityClass().isAbstract(); + } + + @Override + public boolean isLazy() { + return getEntityClass().isLazy(); + } + + @Override + public String getProxy() { + return getEntityClass().getProxy(); + } + + @Override + public int getBatchSize() { + return getEntityClass().getBatchSize(); + } + + @Override + public boolean isDynamicInsert() { + return getEntityClass().isDynamicInsert(); + } + + @Override + public boolean isDynamicUpdate() { + return getEntityClass().isDynamicUpdate(); + } + + @Override + public boolean isSelectBeforeUpdate() { + return getEntityClass().isSelectBeforeUpdate(); + } + + @Override + public String getCustomTuplizerClassName() { + return getEntityClass().getCustomTuplizerClassName(); + } + + @Override + public String getCustomPersisterClassName() { + return getEntityClass().getCustomPersister(); + } + + @Override + public String getCustomLoaderName() { + return getEntityClass().getCustomLoaderQueryName(); + } + + @Override + public CustomSQL getCustomSqlInsert() { + return getEntityClass().getCustomInsert(); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return getEntityClass().getCustomUpdate(); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return getEntityClass().getCustomDelete(); + } + + @Override + public String[] getSynchronizedTableNames() { + return getEntityClass().getSynchronizedTableNames(); + } + + @Override + public Collection getToolingHintSources() { + // not relevant for annotations + return Collections.emptySet(); + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + + @Override + public String getDiscriminatorMatchValue() { + return getEntityClass().getDiscriminatorMatchValue(); + } + + @Override + public Iterable getConstraints() { + Set constraintSources = new HashSet(); + + // primary table + { + final AnnotationInstance table = getEntityClass().getJavaTypeDescriptor().findTypeAnnotation( + JPADotNames.TABLE + ); + if ( table != null ) { + addUniqueConstraints( constraintSources, table, null ); + addIndexConstraints( constraintSources, table, null ); + } + } + + // secondary table + { + final AnnotationInstance secondaryTable = getEntityClass().getJavaTypeDescriptor().findTypeAnnotation( + JPADotNames.SECONDARY_TABLE + ); + if ( secondaryTable != null ) { + String tableName = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( secondaryTable, "name" ); + addUniqueConstraints( constraintSources, secondaryTable, tableName ); + addIndexConstraints( constraintSources, secondaryTable, tableName ); + + } + } + + + // secondary tables + { + final AnnotationInstance secondaryTables = getEntityClass().getJavaTypeDescriptor().findTypeAnnotation( + JPADotNames.SECONDARY_TABLES + ); + if ( secondaryTables != null ) { + final AnnotationInstance[] secondaryTableArray = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( AnnotationInstance[].class ) + .extract( secondaryTables, "value" ); + for ( AnnotationInstance secondaryTable : secondaryTableArray ) { + String tableName = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( secondaryTable, "name" ); + addUniqueConstraints( constraintSources, secondaryTable, tableName ); + addIndexConstraints( constraintSources, secondaryTable, tableName ); + } + } + } + + // collection tables + { + final Collection collectionTables = getEntityClass().getJavaTypeDescriptor().findLocalAnnotations( + JPADotNames.COLLECTION_TABLE + ); + + if ( collectionTables != null ) { + for ( AnnotationInstance collectionTable : collectionTables ) { + String tableName = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( collectionTable, "name" ); + addUniqueConstraints( constraintSources, collectionTable, tableName ); + addIndexConstraints( constraintSources, collectionTable, tableName ); + } + } + } + + // join tables + { + final Collection joinTables = getEntityClass().getJavaTypeDescriptor().findLocalAnnotations( + JPADotNames.JOIN_TABLE + ); + if ( joinTables != null ) { + for (AnnotationInstance joinTable : joinTables) { + String tableName = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( joinTable, "name" ); + addUniqueConstraints( constraintSources, joinTable, tableName ); + addIndexConstraints( constraintSources, joinTable, tableName ); + } + } + } + + // table generators + { + final Collection tableGenerators = getEntityClass().getJavaTypeDescriptor().findLocalAnnotations( + JPADotNames.TABLE_GENERATOR + ); + if ( tableGenerators != null ) { + for (AnnotationInstance tableGenerator : tableGenerators) { + String tableName = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( String.class ) + .extract( tableGenerator, "table" ); + addUniqueConstraints( constraintSources, tableGenerator, tableName ); + addIndexConstraints( constraintSources, tableGenerator, tableName ); + } + } + } + + return constraintSources; + } + + @Override + public Set getSecondaryTables() { + Set secondaryTableSources = new HashSet(); + + // todo : should we walk MappedSuperclasses (if any) too? + + // process a singular @SecondaryTable annotation + { + final AnnotationInstance secondaryTable = getEntityClass().getJavaTypeDescriptor().findLocalTypeAnnotation( + JPADotNames.SECONDARY_TABLE + ); + if ( secondaryTable != null ) { + secondaryTableSources.add( createSecondaryTableSource( secondaryTable, true ) ); + } + } + + // process any @SecondaryTables grouping + { + final AnnotationInstance secondaryTables = getEntityClass().getJavaTypeDescriptor().findLocalTypeAnnotation( + JPADotNames.SECONDARY_TABLES + ); + if ( secondaryTables != null ) { + AnnotationInstance[] tableAnnotations = getLocalBindingContext().getJandexAccess() + .getTypedValueExtractor( AnnotationInstance[].class ) + .extract( secondaryTables, "value" ); + for ( AnnotationInstance secondaryTable : tableAnnotations ) { + secondaryTableSources.add( createSecondaryTableSource( secondaryTable, true ) ); + } + } + } + + for ( PersistentAttribute attribute : getEntityClass().getPersistentAttributeMap().values() ) { + if ( attribute.getNature() == PersistentAttribute.Nature.MANY_TO_ONE + || attribute.getNature() == PersistentAttribute.Nature.ONE_TO_ONE ) { + AnnotationInstance joinTableAnnotation = attribute.getBackingMember() + .getAnnotations() + .get( JPADotNames.JOIN_TABLE ); + if ( joinTableAnnotation != null ) { + secondaryTableSources.add( createSecondaryTableSource( joinTableAnnotation, false ) ); + } + } + } + + return secondaryTableSources; + } + + @Override + public String toString() { + return "EntitySourceImpl{entityClass=" + getEntityClass().getName() + "}"; + } + + private void addUniqueConstraints(Set constraintSources, AnnotationInstance tableAnnotation, String tableName) { + final AnnotationValue value = tableAnnotation.value( "uniqueConstraints" ); + if ( value == null ) { + return; + } + + final AnnotationInstance[] uniqueConstraints = value.asNestedArray(); + for ( final AnnotationInstance unique : uniqueConstraints ) { + final String name = unique.value( "name" ) == null ? null : unique.value( "name" ).asString(); + final String[] columnNames = unique.value( "columnNames" ).asStringArray(); + final UniqueConstraintSourceImpl uniqueConstraintSource = + new UniqueConstraintSourceImpl( + name, tableName, Arrays.asList( columnNames ) + ); + constraintSources.add( uniqueConstraintSource ); + } + } + + private void addIndexConstraints(Set constraintSources, AnnotationInstance tableAnnotation, String tableName) { + final AnnotationValue value = tableAnnotation.value( "indexes" ); + if ( value == null ) { + return; + } + + final AnnotationInstance[] indexConstraints = value.asNestedArray(); + for ( final AnnotationInstance index : indexConstraints ) { + final String name = index.value( "name" ) == null ? null : index.value( "name" ).asString(); + final String columnList = index.value( "columnList" ).asString(); + final boolean isUnique = index.value( "unique" ) == null ? false : index.value( "unique" ).asBoolean(); + + // Taken from JPAIndexHolder. + // TODO: Move elsewhere? + final StringTokenizer tokenizer = new StringTokenizer( columnList, "," ); + final List tmp = new ArrayList(); + while ( tokenizer.hasMoreElements() ) { + tmp.add( tokenizer.nextToken().trim() ); + } + final List columnNames = new ArrayList(); + final List orderings = new ArrayList(); + for ( String indexColumn : tmp ) { + indexColumn = indexColumn.toLowerCase(); + if ( indexColumn.endsWith( " desc" ) ) { + columnNames.add( indexColumn.substring( 0, indexColumn.length() - 5 ) ); + orderings.add( "desc" ); + } + else if ( indexColumn.endsWith( " asc" ) ) { + columnNames.add( indexColumn.substring( 0, indexColumn.length() - 4 ) ); + orderings.add( "asc" ); + } + else { + columnNames.add( indexColumn ); + orderings.add( null ); + } + } + + ConstraintSource constraintSource = new IndexConstraintSourceImpl( + name, tableName, columnNames, orderings, isUnique ); + constraintSources.add( constraintSource ); + } + } + + private SecondaryTableSource createSecondaryTableSource( + AnnotationInstance tableAnnotation, + boolean isPrimaryKeyJoinColumn) { + final List keys = collectSecondaryTableKeys( tableAnnotation, isPrimaryKeyJoinColumn ); + return new SecondaryTableSourceImpl( TableSourceImpl.build( tableAnnotation, bindingContext ), keys ); + } + + private List collectSecondaryTableKeys( + final AnnotationInstance tableAnnotation, + final boolean isPrimaryKeyJoinColumn) { + final AnnotationInstance[] joinColumnAnnotations = getLocalBindingContext() + .getJandexAccess() + .getTypedValueExtractor( AnnotationInstance[].class ) + .extract( tableAnnotation, isPrimaryKeyJoinColumn ? "pkJoinColumns" : "joinColumns" ); + + if ( joinColumnAnnotations == null ) { + return Collections.emptyList(); + } + final List keys = new ArrayList(); + for ( final AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) { + final Column joinColumn; + if ( isPrimaryKeyJoinColumn ) { + joinColumn = new PrimaryKeyJoinColumn( joinColumnAnnotation ); + } + else { + joinColumn = new Column( joinColumnAnnotation ); + } + keys.add( joinColumn ); + } + return keys; + } + + @Override + public String getTypeName() { + return getEntityClass().getName(); + } + + @Override + public TruthValue quoteIdentifiersLocalToEntity() { + // not exposed atm + return TruthValue.UNKNOWN; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FetchProfileSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FetchProfileSourceImpl.java new file mode 100644 index 000000000000..3569f3da9c49 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FetchProfileSourceImpl.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.annotations.FetchMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.FetchProfileSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class FetchProfileSourceImpl implements FetchProfileSource { + private final String name; + private final List associationOverrideSources; + private final ClassLoaderService classLoaderService; + + public FetchProfileSourceImpl(AnnotationInstance fetchProfileAnnotation, AnnotationBindingContext bindingContext) { + this.classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + this.name = JandexHelper.getValue( fetchProfileAnnotation, "name", String.class, classLoaderService ); + this.associationOverrideSources = buildAssociationOverrideSources( fetchProfileAnnotation ); + } + + @Override + public String getName() { + return name; + } + + @Override + public Iterable getAssociationOverrides() { + return associationOverrideSources; + } + + private List buildAssociationOverrideSources(AnnotationInstance fetchProfileAnnotation) { + final List associationOverrideSources = new ArrayList(); + AnnotationInstance[] overrideAnnotations = JandexHelper.getValue( + fetchProfileAnnotation, + "fetchOverrides", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance overrideAnnotation : overrideAnnotations ) { + associationOverrideSources.add( new AssociationOverrideSourceImpl( overrideAnnotation ) ); + } + return associationOverrideSources; + } + + private class AssociationOverrideSourceImpl implements AssociationOverrideSource { + private final String entityName; + private final String attributeName; + private final String fetchMode; + + private AssociationOverrideSourceImpl(AnnotationInstance overrideAnnotation) { + this.entityName = JandexHelper.getValue( overrideAnnotation, "entity", String.class, classLoaderService ); + this.attributeName = JandexHelper.getValue( overrideAnnotation, "association", String.class, classLoaderService ); + FetchMode fetchMode = JandexHelper.getEnumValue( overrideAnnotation, "mode", FetchMode.class, classLoaderService ); + if ( !fetchMode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) { + throw new MappingException( "Only FetchMode.JOIN is currently supported" ); + } + this.fetchMode = "join"; + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + public String getAttributeName() { + return attributeName; + } + + @Override + public String getFetchModeName() { + return fetchMode; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FilterDefinitionSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FilterDefinitionSourceImpl.java new file mode 100644 index 000000000000..5296ed23de5d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FilterDefinitionSourceImpl.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.FilterParameterSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class FilterDefinitionSourceImpl implements FilterDefinitionSource { + private final String name; + private final String condition; + private final ClassLoaderService classLoaderService; + private List parameterSources; + + public FilterDefinitionSourceImpl(AnnotationInstance filterDefAnnotation, AnnotationBindingContext bindingContext) { + this.classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + this.name = JandexHelper.getValue( filterDefAnnotation, "name", String.class, classLoaderService ); + this.condition = JandexHelper.getValue( filterDefAnnotation, "defaultCondition", String.class, classLoaderService ); + this.parameterSources = buildParameterSources( filterDefAnnotation ); + } + + private List buildParameterSources(AnnotationInstance filterDefAnnotation) { + final List parameterSources = new ArrayList(); + for ( AnnotationInstance paramAnnotation : JandexHelper.getValue( filterDefAnnotation, "parameters", + AnnotationInstance[].class, classLoaderService ) ) { + parameterSources.add( new FilterParameterSourceImpl( paramAnnotation ) ); + } + return parameterSources; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public Iterable getParameterSources() { + return parameterSources; + } + + private class FilterParameterSourceImpl implements FilterParameterSource { + private final String name; + private final String type; + + public FilterParameterSourceImpl(AnnotationInstance paramAnnotation) { + this.name = JandexHelper.getValue( paramAnnotation, "name", String.class, classLoaderService ); + this.type = JandexHelper.getValue( paramAnnotation, "type", String.class, classLoaderService ); + } + + @Override + public String getParameterName() { + return name; + } + + @Override + public String getParameterValueTypeName() { + return type; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FilterSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FilterSourceImpl.java new file mode 100644 index 000000000000..4329ee7749d7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/FilterSourceImpl.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.FilterSource; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class FilterSourceImpl implements FilterSource { + private final String name; + private final String condition; + private final boolean autoAliasInjection; + private final Map aliasTableMap = new HashMap(); + private final Map aliasEntityMap = new HashMap(); + + public FilterSourceImpl(AnnotationInstance filterAnnotation) { + this.name = extractString( filterAnnotation, "name" ); + this.condition = extractString( filterAnnotation, "condition" ); + this.autoAliasInjection = extractBoolean( filterAnnotation, "deduceAliasInjectionPoints", true ); + + final AnnotationInstance[] aliasAnnotations = JandexHelper.extractAnnotationsValue( filterAnnotation, "aliases" ); + for ( AnnotationInstance aliasAnnotation : aliasAnnotations ) { + final String alias = extractString( aliasAnnotation, "alias" ); + final String table = extractString( aliasAnnotation, "table" ); + final String entity = extractString( aliasAnnotation, "entity" ); + + assert StringHelper.isNotEmpty( alias ); + + if ( StringHelper.isNotEmpty( table ) ) { + aliasTableMap.put( alias, table ); + } + else if ( StringHelper.isNotEmpty( entity ) ) { + aliasEntityMap.put( alias, entity ); + } + else { + // todo : throw a mapping exception + } + } + } + + private static String extractString(AnnotationInstance annotation, String name) { + final AnnotationValue value = annotation.value( name ); + if ( value == null ) { + return null; + } + return StringHelper.nullIfEmpty( value.asString() ); + } + + private static boolean extractBoolean(AnnotationInstance annotation, String name, boolean defaultValue) { + final AnnotationValue value = annotation.value( name ); + if ( value == null ) { + return defaultValue; + } + return value.asBoolean(); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public boolean shouldAutoInjectAliases() { + return autoAliasInjection; + } + + @Override + public Map getAliasToTableMap() { + return aliasTableMap; + } + + @Override + public Map getAliasToEntityMap() { + return aliasEntityMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/HibernateTypeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/HibernateTypeSourceImpl.java new file mode 100644 index 000000000000..48621c37bf7a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/HibernateTypeSourceImpl.java @@ -0,0 +1,78 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Map; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; + +/** + * @author Hardy Ferentschik + * @author Strong Liu + */ +public class HibernateTypeSourceImpl implements HibernateTypeSource { + private final ValueHolder nameHolder; + private final ValueHolder> parameterHolder; + private final JavaTypeDescriptor javaType; + + public HibernateTypeSourceImpl(final PersistentAttribute attribute) { + this.nameHolder = new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public String initialize() { + return attribute.getHibernateTypeResolver().getExplicitHibernateTypeName(); + } + } + ); + this.parameterHolder = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Map initialize() { + return attribute.getHibernateTypeResolver().getExplicitHibernateTypeParameters(); + } + } + ); + this.javaType = attribute.getBackingMember().getType().getErasedType(); + } + + @Override + public String getName() { + return nameHolder.getValue(); + } + + @Override + public Map getParameters() { + return parameterHolder.getValue(); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return javaType; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifiableTypeSourceAdapter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifiableTypeSourceAdapter.java new file mode 100644 index 000000000000..eb40606d6f58 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifiableTypeSourceAdapter.java @@ -0,0 +1,228 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.IdentifiableTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.MappedSuperclassTypeMetadata; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.JpaCallbackSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.xml.spi.Origin; + +/** + * Base class adapting "identifiable types" (entities and mapped-superclasses) + * from annotation (plus XML overrides) representation to the source + * representation consumed by the metamodel binder. + * + * @author Steve Ebersole + */ +public abstract class IdentifiableTypeSourceAdapter implements IdentifiableTypeSource { + private final IdentifiableTypeMetadata identifiableTypeMetadata; + private final EntityHierarchySourceImpl hierarchy; + private final IdentifiableTypeSourceAdapter superTypeSource; + + private Collection subclassSources; + private List attributes; + + /** + * This form is intended for the root of a hierarchy + * + * @param identifiableTypeMetadata Metadata about the "identifiable type" + * @param hierarchy The hierarchy flyweight + */ + protected IdentifiableTypeSourceAdapter( + IdentifiableTypeMetadata identifiableTypeMetadata, + EntityHierarchySourceImpl hierarchy, + boolean isRootEntity) { + this.identifiableTypeMetadata = identifiableTypeMetadata; + this.hierarchy = hierarchy; + + // walk up + this.superTypeSource = walkRootSuperclasses( identifiableTypeMetadata.getSuperType(), hierarchy ); + if ( superTypeSource != null ) { + superTypeSource.addSubclass( this ); + } + + if ( isRootEntity ) { + // walk down + walkSubclasses( identifiableTypeMetadata, this ); + } + } + + private void addSubclass(IdentifiableTypeSourceAdapter subclassSource) { + assert subclassSource.identifiableTypeMetadata.getSuperType() == this.identifiableTypeMetadata; + if ( subclassSources == null ) { + subclassSources = new ArrayList(); + } + subclassSources.add( subclassSource ); + } + + private static IdentifiableTypeSourceAdapter walkRootSuperclasses( + ManagedTypeMetadata clazz, + EntityHierarchySourceImpl hierarchy) { + if ( clazz == null ) { + return null; + } + + if ( MappedSuperclassTypeMetadata.class.isInstance( clazz ) ) { + // IMPORTANT : routing through the root constructor! + return new MappedSuperclassSourceImpl( (MappedSuperclassTypeMetadata) clazz, hierarchy ); + } + else { + throw new UnsupportedOperationException( + String.format( + Locale.ENGLISH, + "Unexpected @Entity [%s] as MappedSuperclass of entity hierarchy", + clazz.getName() + ) + ); + } + } + + private void walkSubclasses( + IdentifiableTypeMetadata classMetadata, + IdentifiableTypeSourceAdapter classSource) { + for ( ManagedTypeMetadata subclass : classMetadata.getSubclasses() ) { + final IdentifiableTypeSourceAdapter subclassSource; + if ( MappedSuperclassTypeMetadata.class.isInstance( subclass ) ) { + subclassSource = new MappedSuperclassSourceImpl( + (MappedSuperclassTypeMetadata) subclass, + this.hierarchy, + classSource + ); + } + else if ( this.hierarchy.getHierarchyInheritanceType() == InheritanceType.JOINED ) { + subclassSource = new JoinedSubclassEntitySourceImpl( + (EntityTypeMetadata) subclass, + this.hierarchy, + classSource + ); + } + else { + subclassSource = new SubclassEntitySourceImpl( + (EntityTypeMetadata) subclass, + this.hierarchy, + classSource + ); + } + classSource.addSubclass( subclassSource ); + + walkSubclasses( (IdentifiableTypeMetadata) subclass, subclassSource ); + } + } + + + /** + * This form is intended for creating subclasses + * + * @param identifiableTypeMetadata + * @param hierarchy + * @param superTypeSource + */ + protected IdentifiableTypeSourceAdapter( + IdentifiableTypeMetadata identifiableTypeMetadata, + EntityHierarchySourceImpl hierarchy, + IdentifiableTypeSourceAdapter superTypeSource) { + this.identifiableTypeMetadata = identifiableTypeMetadata; + this.hierarchy = hierarchy; + this.superTypeSource = superTypeSource; + } + + public IdentifiableTypeMetadata getIdentifiableTypeMetadata() { + return identifiableTypeMetadata; + } + + public ManagedTypeMetadata getManagedTypeMetadata() { + return identifiableTypeMetadata; + } + + @Override + public Origin getOrigin() { + return identifiableTypeMetadata.getLocalBindingContext().getOrigin(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return identifiableTypeMetadata.getLocalBindingContext(); + } + + @Override + public EntityHierarchySource getHierarchy() { + return hierarchy; + } + + @Override + public String getTypeName() { + return identifiableTypeMetadata.getName(); + } + + @Override + public IdentifiableTypeSourceAdapter getSuperType() { + return superTypeSource; + } + + @Override + public Collection getSubTypes() { + return subclassSources == null ? Collections.emptyList() : subclassSources; + } + + @Override + public List getJpaCallbackClasses() { + return identifiableTypeMetadata.getJpaCallbacks(); + } + + @Override + public AttributePath getAttributePathBase() { + return identifiableTypeMetadata.getAttributePathBase(); + } + + @Override + public AttributeRole getAttributeRoleBase() { + return identifiableTypeMetadata.getAttributeRoleBase(); + } + + @Override + public List attributeSources() { + if ( attributes == null ) { + attributes = SourceHelper.buildAttributeSources( + identifiableTypeMetadata, + SourceHelper.StandardAttributeBuilder.INSTANCE + ); + } + return attributes; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifierGeneratorSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifierGeneratorSourceContainer.java new file mode 100644 index 000000000000..405069765749 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifierGeneratorSourceContainer.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Basically defines a source of identifier generator sources. Used to abstract where the identifier generator + * specifications come from so that we can share the process code. + * + * @author Steve Ebersole + */ +public interface IdentifierGeneratorSourceContainer { + public Collection getSequenceGeneratorSources(); + + public Collection getTableGeneratorSources(); + + public Collection getGenericGeneratorSources(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifierGeneratorSourceContainerImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifierGeneratorSourceContainerImpl.java new file mode 100644 index 000000000000..8128b520e5bc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IdentifierGeneratorSourceContainerImpl.java @@ -0,0 +1,113 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class IdentifierGeneratorSourceContainerImpl implements IdentifierGeneratorSourceContainer { + + private final ClassLoaderService classLoaderService; + + public IdentifierGeneratorSourceContainerImpl(AnnotationBindingContext bindingContext) { + this.classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + } + + private Collection resolveOrEmpty(DotName name) { + Collection generatorSources = getAnnotations( name ); + return generatorSources == null ? Collections.emptyList() : generatorSources; + } + + private final ValueHolder> sequenceGeneratorSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Collection initialize() { + return resolveOrEmpty( JPADotNames.SEQUENCE_GENERATOR ); + } + } + ); + + @Override + public Collection getSequenceGeneratorSources() { + return sequenceGeneratorSources.getValue(); + } + + private final ValueHolder> tableGeneratorSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Collection initialize() { + return resolveOrEmpty( JPADotNames.TABLE_GENERATOR ); + } + } + ); + + @Override + public Collection getTableGeneratorSources() { + return tableGeneratorSources.getValue(); + } + + private final ValueHolder> genericGeneratorSources = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Collection initialize() { + List annotations = new ArrayList(); + annotations.addAll( resolveOrEmpty( HibernateDotNames.GENERIC_GENERATOR ) ); + for ( AnnotationInstance generatorsAnnotation : resolveOrEmpty( HibernateDotNames.GENERIC_GENERATORS ) ) { + Collections.addAll( + annotations, + JandexHelper.getValue( + generatorsAnnotation, + "value", + AnnotationInstance[].class, + classLoaderService + ) + ); + } + return annotations; + } + } + ); + + + @Override + public Collection getGenericGeneratorSources() { + return genericGeneratorSources.getValue(); + } + + protected abstract Collection getAnnotations(DotName name); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ImplicitDiscriminatorColumnSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ImplicitDiscriminatorColumnSource.java new file mode 100644 index 000000000000..20a86a7440a7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ImplicitDiscriminatorColumnSource.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.sql.Types; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.relational.JdbcDataType; + +/** + * @author Steve Ebersole + */ +public class ImplicitDiscriminatorColumnSource implements ColumnSource { + // The implicit column name per JPA spec + private static final String IMPLICIT_COLUMN_NAME = "DTYPE"; + + // The implicit column type per JPA spec + private final JdbcDataType IMPLICIT_DATA_TYPE = new JdbcDataType( + Types.VARCHAR, + "varchar", + String.class + ); + + private final String comment; + + public ImplicitDiscriminatorColumnSource(EntityTypeMetadata entityTypeMetadata) { + this.comment = "Discriminator value for " + entityTypeMetadata.getName(); + } + + @Override + public String getContainingTableName() { + // null indicates primary table + return null; + } + + @Override + public Nature getNature() { + return Nature.COLUMN; + } + + @Override + public String getName() { + // The default/implicit column name per JPA spec + return IMPLICIT_COLUMN_NAME; + } + + @Override + public String getReadFragment() { + return null; + } + + @Override + public String getWriteFragment() { + return null; + } + + @Override + public TruthValue isNullable() { + // discriminators should not be nullable + return TruthValue.FALSE; + } + + @Override + public String getDefaultValue() { + return null; + } + + @Override + public String getSqlType() { + return null; + } + + @Override + public JdbcDataType getDatatype() { + return IMPLICIT_DATA_TYPE; + } + + @Override + public SizeSource getSizeSource() { + return null; + } + + @Override + public boolean isUnique() { + return false; + } + + @Override + public String getCheckCondition() { + return null; + } + + @Override + public String getComment() { + return comment; + } + + @Override + public TruthValue isIncludedInInsert() { + return null; + } + + @Override + public TruthValue isIncludedInUpdate() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ImplicitDiscriminatorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ImplicitDiscriminatorSourceImpl.java new file mode 100644 index 000000000000..992e59e6282f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ImplicitDiscriminatorSourceImpl.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.spi.DiscriminatorSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.type.StandardBasicTypes; + +/** + * @author Steve Ebersole + */ +public class ImplicitDiscriminatorSourceImpl + extends DiscriminatorSourceSupport + implements DiscriminatorSource { + + private final RelationalValueSource relationalValueSource; + + public ImplicitDiscriminatorSourceImpl(EntityTypeMetadata entityTypeMetadata) { + super( entityTypeMetadata ); + + this.relationalValueSource = new ImplicitDiscriminatorColumnSource( entityTypeMetadata ); + } + + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + return relationalValueSource; + } + + @Override + public String getExplicitHibernateTypeName() { + return StandardBasicTypes.STRING.getName(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/InLineViewSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/InLineViewSourceImpl.java new file mode 100644 index 000000000000..ef68a4463e72 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/InLineViewSourceImpl.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.spi.InLineViewSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class InLineViewSourceImpl implements InLineViewSource { + private final InlineViewInfo inlineViewInfo; + + public InLineViewSourceImpl(EntityTypeMetadata entityTypeMetadata) { + this.inlineViewInfo = createInlineViewInfo( entityTypeMetadata ); + } + + @Override + public String getSelectStatement() { + return inlineViewInfo.getSelectStatement(); + } + + @Override + public String getExplicitSchemaName() { + return null; + } + + @Override + public String getExplicitCatalogName() { + return null; + } + + @Override + public String getLogicalName() { + return inlineViewInfo.getLogicalName(); + } + + private InlineViewInfo createInlineViewInfo(EntityTypeMetadata entityTypeMetadata) { + final AnnotationInstance subselectAnnotation = entityTypeMetadata.getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.SUB_SELECT + ); + + return new InlineViewInfo( subselectAnnotation.value().asString(), entityTypeMetadata.getEntityName() ); + } + + private static class InlineViewInfo { + private final String selectStatement; + private final String logicalName; + + private InlineViewInfo(String selectStatement, String logicalName) { + this.selectStatement = selectStatement; + this.logicalName = logicalName; + } + + public String getSelectStatement() { + return selectStatement; + } + + public String getLogicalName() { + return logicalName; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + InlineViewInfo that = ( InlineViewInfo ) o; + + if ( logicalName != null ? !logicalName.equals( that.logicalName ) : that.logicalName != null ) { + return false; + } + if ( selectStatement != null ? !selectStatement.equals( that.selectStatement ) : that.selectStatement != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = selectStatement != null ? selectStatement.hashCode() : 0; + result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 ); + return result; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IndexConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IndexConstraintSourceImpl.java new file mode 100644 index 000000000000..348e88304061 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/IndexConstraintSourceImpl.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.metamodel.source.spi.IndexConstraintSource; + +/** + * @author Brett Meyer + */ +class IndexConstraintSourceImpl extends AbstractConstraintSource implements IndexConstraintSource { + + private final boolean unique; + + public IndexConstraintSourceImpl(String name, String tableName, List columnNames, List orderings, + boolean unique) { + super( name, tableName, columnNames, orderings ); + this.unique = unique; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "IndexConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean isUnique() { + return unique; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JandexAccess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JandexAccess.java new file mode 100644 index 000000000000..9a98faca2a8f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JandexAccess.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.IndexView; + +/** + * @author Steve Ebersole + */ +public interface JandexAccess { + /** + * The annotation repository that this context know about. + * + * @return The {@link org.jboss.jandex.IndexView} that this context know about. + */ + IndexView getIndex(); + + /** + * Gets the class (or interface, or annotation) that was scanned during the + * indexing phase. + * + * @param className the name of the class + * @return information about the class or null if it is not known + */ + ClassInfo getClassInfo(String className); + + /** + * Get a type-specific extractor for extracting attribute values from Jandex + * AnnotationInstances. + * + * @param type The type of extractor we want + * @param The generic type of the extractor + * + * @return The typed extractor + */ + TypedValueExtractor getTypedValueExtractor(Class type); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JandexAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JandexAccessImpl.java new file mode 100644 index 000000000000..016953321f3e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JandexAccessImpl.java @@ -0,0 +1,598 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.ClassLoaderAccess; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Type; + +/** + * @author Steve Ebersole + */ +public class JandexAccessImpl implements JandexAccess { + private final IndexView index; + private final ClassLoaderAccess classLoaderAccess; + + public JandexAccessImpl( + IndexView index, + ClassLoaderAccess classLoaderAccess) { + this.index = index; + this.classLoaderAccess = classLoaderAccess; + } + + @Override + public IndexView getIndex() { + return index; + } + + @Override + public ClassInfo getClassInfo(String className) { + DotName dotName = DotName.createSimple( className ); + return index.getClassByName( dotName ); + } + + @Override + @SuppressWarnings("unchecked") + public TypedValueExtractor getTypedValueExtractor(Class type) { + if ( boolean.class.equals( type ) || Boolean.class.equals( type ) ) { + return (TypedValueExtractor) booleanExtractor; + } + else if ( byte.class.equals( type ) || Byte.class.equals( type ) ) { + return (TypedValueExtractor) byteExtractor; + } + else if ( char.class.equals( type ) || Character.class.equals( type ) ) { + return (TypedValueExtractor) characterExtractor; + } + else if ( short.class.equals( type ) || Short.class.equals( type ) ) { + return (TypedValueExtractor) shortExtractor; + } + else if ( int.class.equals( type ) || Integer.class.equals( type ) ) { + return (TypedValueExtractor) integerExtractor; + } + else if ( long.class.equals( type ) || Long.class.equals( type ) ) { + return (TypedValueExtractor) longExtractor; + } + else if ( float.class.equals( type ) || Float.class.equals( type ) ) { + return (TypedValueExtractor) floatExtractor; + } + else if ( double.class.equals( type ) || Double.class.equals( type ) ) { + return (TypedValueExtractor) doubleExtractor; + } + else if ( String.class.equals( type ) ) { + return (TypedValueExtractor) stringExtractor; + } + else if ( String[].class.equals( type ) ) { + return (TypedValueExtractor) stringArrayExtractor; + } + else if ( type.isEnum() ) { + return new EnumExtractor( type ); + } + else if ( type.isArray() && type.getComponentType().isEnum() ) { + return new EnumArrayExtractor( type ); + } + else if ( Type.class.equals( type ) ) { + return (TypedValueExtractor) classTypeExtractor; + } + else if ( type.isArray() && Type.class.equals( type.getComponentType() ) ) { + return (TypedValueExtractor) classTypeArrayExtractor; + } + else if ( AnnotationInstance.class.equals( type ) ) { + return (TypedValueExtractor) nestedExtractor; + } + else if ( type.isArray() && AnnotationInstance.class.equals( type.getComponentType() ) ) { + return (TypedValueExtractor) nestedArrayExtractor; + } + + // checks for some specific unsupported types + if ( Class.class.equals( type ) || Class[].class.equals( type ) ) { + throw new IllegalArgumentException( + "Class and Class[] typed annotation attributes should be extracted" + + "by FQN or by org.jboss.jandex.Type" + ); + } + + throw new IllegalArgumentException( + "Unsupported extraction type [" + type.getName() + "] requested" + ); + } + + + private abstract class AbstractTypedValueExtractor implements TypedValueExtractor { + @Override + public T extract(AnnotationInstance annotationInstance, String name) { + final AnnotationValue attributeInstance = annotationInstance.value( name ); + if ( attributeInstance == null ) { + return interpretDefaultValue( getDefaultValue( annotationInstance, name ) ); + } + else { + return extract( attributeInstance ); + } + } + + protected abstract T interpretDefaultValue(Object defaultValue); + + protected abstract T extract(AnnotationValue attributeInstance); + + @Override + public T extract(AnnotationInstance annotationInstance, String name, T defaultValue) { + final AnnotationValue attributeInstance = annotationInstance.value( name ); + if ( attributeInstance == null ) { + return defaultValue; + } + else { + return extract( attributeInstance ); + } + } + } + + + public final TypedValueExtractor booleanExtractor = new AbstractTypedValueExtractor() { + @Override + public Boolean extract(AnnotationValue value) { + return value.asBoolean(); + } + + @Override + public Boolean interpretDefaultValue(Object value) { + if ( boolean.class.isInstance( value ) || Boolean.class.isInstance( value ) ) { + return (Boolean) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Boolean" ); + } + }; + + public final TypedValueExtractor byteExtractor = new AbstractTypedValueExtractor() { + @Override + public Byte extract(AnnotationValue value) { + return value.asByte(); + } + + @Override + public Byte interpretDefaultValue(Object value) { + if ( byte.class.isInstance( value ) || Byte.class.isInstance( value ) ) { + return (Byte) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Byte" ); + } + }; + + public final TypedValueExtractor characterExtractor = new AbstractTypedValueExtractor() { + @Override + public Character extract(AnnotationValue value) { + return value.asChar(); + } + + @Override + public Character interpretDefaultValue(Object value) { + if ( char.class.isInstance( value ) || Character.class.isInstance( value ) ) { + return (Character) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Character" ); + } + }; + + public final TypedValueExtractor shortExtractor = new AbstractTypedValueExtractor() { + @Override + public Short extract(AnnotationValue value) { + return value.asShort(); + } + + @Override + public Short interpretDefaultValue(Object value) { + if ( short.class.isInstance( value ) || Short.class.isInstance( value ) ) { + return (Short) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Short" ); + } + }; + + public final TypedValueExtractor integerExtractor = new AbstractTypedValueExtractor() { + @Override + public Integer extract(AnnotationValue value) { + return value.asInt(); + } + + @Override + public Integer interpretDefaultValue(Object value) { + if ( int.class.isInstance( value ) || Integer.class.isInstance( value ) ) { + return (Integer) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Integer" ); + } + }; + + public final TypedValueExtractor longExtractor = new AbstractTypedValueExtractor() { + @Override + public Long extract(AnnotationValue value) { + return value.asLong(); + } + + @Override + public Long interpretDefaultValue(Object value) { + if ( long.class.isInstance( value ) || Long.class.isInstance( value ) ) { + return (Long) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Long" ); + } + }; + + public final TypedValueExtractor doubleExtractor = new AbstractTypedValueExtractor() { + @Override + public Double extract(AnnotationValue value) { + return value.asDouble(); + } + + @Override + public Double interpretDefaultValue(Object value) { + if ( double.class.isInstance( value ) || Double.class.isInstance( value ) ) { + return (Double) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Double" ); + } + }; + + public final TypedValueExtractor floatExtractor = new AbstractTypedValueExtractor() { + @Override + public Float extract(AnnotationValue value) { + return value.asFloat(); + } + + @Override + public Float interpretDefaultValue(Object value) { + if ( float.class.isInstance( value ) || Float.class.isInstance( value ) ) { + return (Float) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Float" ); + } + }; + + public final TypedValueExtractor stringExtractor = new AbstractTypedValueExtractor() { + @Override + public String extract(AnnotationValue value) { + return value.asString(); + } + + @Override + public String interpretDefaultValue(Object value) { + if ( value == null ) { + return null; + } + if ( String.class.isInstance( value ) ) { + return (String) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to String" ); + } + }; + + public final TypedValueExtractor stringArrayExtractor = new AbstractTypedValueExtractor() { + @Override + public String[] extract(AnnotationValue value) { + return value.asStringArray(); + } + + @Override + public String[] interpretDefaultValue(Object value) { + if ( value == null ) { + return null; + } + if ( String[].class.isInstance( value ) ) { + return (String[]) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to String[]" ); + } + }; + + public final TypedValueExtractor enumNameExtractor = new AbstractTypedValueExtractor() { + @Override + public String extract(AnnotationValue value) { + return value.asEnum(); + } + + @Override + public String interpretDefaultValue(Object value) { + if ( Enum.class.isInstance( value ) ) { + return ( (Enum) value ).name(); + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Enum (to extract name)" ); + } + }; + + public final TypedValueExtractor enumNameArrayExtractor = new AbstractTypedValueExtractor() { + @Override + public String[] extract(AnnotationValue value) { + return value.asEnumArray(); + } + + @Override + public String[] interpretDefaultValue(Object value) { + if ( Enum[].class.isInstance( value ) ) { + final Enum[] enums = (Enum[]) value; + final String[] names = new String[enums.length]; + for ( int i = 0, length = enums.length; i < length; i++ ) { + names[i] = enums[i].name(); + } + return names; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Enum[] (to extract names)" ); + } + }; + + public final AbstractTypedValueExtractor classNameExtractor = new AbstractTypedValueExtractor() { + @Override + public String extract(AnnotationValue value) { + return ( (AbstractTypedValueExtractor) stringExtractor ).extract( value ); + } + + @Override + public String interpretDefaultValue(Object value) { + if ( value == null ) { + return null; + } + if ( Class.class.isInstance( value ) ) { + return ( (Class) value ).getName(); + } + else if ( String.class.isInstance( value ) ) { + return (String) value; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Class (to extract name)" ); + } + }; + + public final TypedValueExtractor classNameArrayExtractor = new AbstractTypedValueExtractor() { + @Override + public String[] extract(AnnotationValue value) { + return value.asStringArray(); + } + + @Override + public String[] interpretDefaultValue(Object value) { + if ( Class[].class.isInstance( value ) ) { + final Class[] types = (Class[]) value; + final String[] names = new String[types.length]; + for ( int i = 0, length = types.length; i < length; i++ ) { + names[i] = types[i].getName(); + } + return names; + } + throw new IllegalArgumentException( "Cannot convert given value [" + value + "] to Class[] (to extract names)" ); + } + }; + + public final TypedValueExtractor classTypeExtractor = new AbstractTypedValueExtractor() { + @Override + public Type extract(AnnotationValue value) { + return value.asClass(); + } + + @Override + public Type interpretDefaultValue(Object value) { + // What is the relationship between Type and ClassInfo? is there one? + // How does one get a Type reference from the index? + return null; + } + }; + + public final TypedValueExtractor classTypeArrayExtractor = new AbstractTypedValueExtractor() { + @Override + public Type[] extract(AnnotationValue value) { + return value.asClassArray(); + } + + @Override + public Type[] interpretDefaultValue(Object value) { + throw new IllegalStateException( + "Cannot interpret default Class values as Jandex Types atm, " + + "as this class does not have access to the Jandex Index" + ); + } + }; + + public final TypedValueExtractor nestedExtractor = new AbstractTypedValueExtractor() { + @Override + public AnnotationInstance extract(AnnotationValue value) { + return value.asNested(); + } + + @Override + public AnnotationInstance interpretDefaultValue(Object value) { + return null; + } + }; + + public final TypedValueExtractor nestedArrayExtractor = new AbstractTypedValueExtractor() { + @Override + public AnnotationInstance[] extract(AnnotationValue value) { + return value.asNestedArray(); + } + + @Override + public AnnotationInstance[] interpretDefaultValue(Object value) { + return new AnnotationInstance[0]; + } + }; + + private class EnumExtractor> extends AbstractTypedValueExtractor { + private final Class enumType; + + private EnumExtractor(Class enumType) { + this.enumType = enumType; + } + + @Override + @SuppressWarnings("unchecked") + protected T interpretDefaultValue(Object defaultValue) { + // defaultValue should be an enum already.. + if ( enumType.isInstance( defaultValue ) ) { + return (T) defaultValue; + } + else if ( defaultValue instanceof String ) { + return (T) Enum.valueOf( enumType, (String) defaultValue ); + } + throw new IllegalArgumentException( + "Do not know how to convert given value [" + defaultValue + + "] to specified enum [" + enumType.getName() + "]" + ); + } + + @Override + protected T extract(AnnotationValue attributeInstance) { + return Enum.valueOf( + enumType, + ( (AbstractTypedValueExtractor) enumNameExtractor ).extract( attributeInstance ) + ); + } + } + + private class EnumArrayExtractor> extends AbstractTypedValueExtractor { + private final Class enumType; + + private EnumArrayExtractor(Class enumType) { + this.enumType = enumType; + } + + @Override + @SuppressWarnings("unchecked") + protected T[] interpretDefaultValue(Object defaultValue) { + // defaultValue should be an enum array already.. + if ( defaultValue == null ) { + return (T[]) Array.newInstance( enumType, 0 ); + } + else if ( defaultValue.getClass().isArray() + && defaultValue.getClass().getComponentType().equals( enumType ) ) { + return (T[]) defaultValue; + } + else if ( defaultValue.getClass().isArray() + && defaultValue.getClass().getComponentType().equals( String.class ) ) { + final String[] strings = (String[]) defaultValue; + final T[] result = (T[]) Array.newInstance( enumType, strings.length ); + for ( int i = 0; i < strings.length; i++ ) { + result[i] = Enum.valueOf( enumType, strings[i] ); + } + return result; + } + throw new IllegalArgumentException( + "Do not know how to convert given value [" + defaultValue + + "] to specified enum array [" + enumType.getName() + "]" + ); + } + + @Override + @SuppressWarnings("unchecked") + protected T[] extract(AnnotationValue attributeInstance) { + final String[] enumValues = ( (AbstractTypedValueExtractor) enumNameArrayExtractor ).extract( attributeInstance ); + final T[] result = (T[]) Array.newInstance( enumType, enumValues.length ); + for ( int i = 0; i < enumValues.length; i++ ) { + result[i] = Enum.valueOf( enumType, enumValues[i] ); + } + return result; + } + } + + private static final Map> DEFAULT_VALUES_MAP = new HashMap>(); + + private Object getDefaultValue(AnnotationInstance annotation, String attributeName) { + final String annotationFqn = annotation.name().toString(); + Map annotationValueMap = DEFAULT_VALUES_MAP.get( annotation.name() ); + if ( annotationValueMap == null ) { + // we have not processed this annotation yet + final Class annotationClass = classLoaderAccess.classForName( annotationFqn ); + annotationValueMap = parseAttributeDefaults( annotationClass ); + DEFAULT_VALUES_MAP.put( annotation.name(), annotationValueMap ); + } + + final Object value = annotationValueMap.get( attributeName ); + if ( value == null ) { + if ( !annotationValueMap.containsKey( attributeName ) ) { + throw new IllegalArgumentException( + String.format( + "Annotation [%s] does not define an attribute named '%s'", + annotationFqn, + attributeName + ) + ); + } + } + return value; + } + + private Map parseAttributeDefaults(Class annotationClass) { + final Map results = new HashMap(); + + final Method[] methods = annotationClass.getDeclaredMethods(); + if ( methods != null ) { + for ( Method method : methods ) { + Object defaultValue = method.getDefaultValue(); + if ( defaultValue != null ) { + if ( defaultValue instanceof String ) { + if ( "".equals( defaultValue ) ) { + defaultValue = null; + } + } + else if ( defaultValue instanceof Class ) { + final Class clazz = (Class) defaultValue; + if ( void.class.equals( clazz ) ) { + defaultValue = null; + } + else { + // use its FQN (ideally we'd use the jandex Type) + defaultValue = ( (Class) defaultValue ).getName(); + } + } + else if ( defaultValue instanceof Class[] ) { + // use its FQN (ideally we'd use the jandex Type) + final Class[] types = (Class[]) defaultValue; + final String[] fqns = new String[ types.length ]; + for ( int i = 0; i < types.length; i++ ) { + fqns[i] = types[i].getName(); + } + defaultValue = fqns; + } + else if ( defaultValue.getClass().isAnnotation() ) { + // I can't think of a single instance where the + // default for a nested annotation attribute is + // anything other than an empty annotation instance + defaultValue = null; + } + else if ( defaultValue.getClass().isArray() + && defaultValue.getClass().getComponentType().isAnnotation() ) { + defaultValue = null; + } + } + results.put( method.getName(), defaultValue ); + } + } + + return results; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JoinedSubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JoinedSubclassEntitySourceImpl.java new file mode 100644 index 000000000000..ebd3ab8c79b8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JoinedSubclassEntitySourceImpl.java @@ -0,0 +1,130 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.JoinedSubclassEntitySource; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Strong Liu + */ +public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl implements JoinedSubclassEntitySource { + private final List columnSources; + private final JoinColumnResolutionDelegate fkColumnResolutionDelegate; + + public JoinedSubclassEntitySourceImpl( + EntityTypeMetadata metadata, + EntityHierarchySourceImpl hierarchy, + IdentifiableTypeSourceAdapter superTypeSource) { + super( metadata, hierarchy, superTypeSource ); + + // todo : following normal annotation idiom for source, we probably want to move this stuff up to EntityClass... + // todo : actually following the new paradigm we really want to move the interpretation of the join specific annotations here + + boolean hadNamedTargetColumnReferences = false; + this.columnSources = new ArrayList(); + final List targetColumnNames = new ArrayList(); + if ( CollectionHelper.isNotEmpty( metadata.getJoinedSubclassPrimaryKeyJoinColumnSources() ) ) { + for ( PrimaryKeyJoinColumn primaryKeyJoinColumnSource : metadata.getJoinedSubclassPrimaryKeyJoinColumnSources() ) { + columnSources.add( + new ColumnSourceImpl( primaryKeyJoinColumnSource ) + ); + targetColumnNames.add( primaryKeyJoinColumnSource.getReferencedColumnName() ); + if ( primaryKeyJoinColumnSource.getReferencedColumnName() != null ) { + hadNamedTargetColumnReferences = true; + } + } + } + + this.fkColumnResolutionDelegate = !hadNamedTargetColumnReferences + ? null + : new JoinColumnResolutionDelegateImpl( targetColumnNames ); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return getEntityClass().getOnDeleteAction() != null && getEntityClass().getOnDeleteAction() == OnDeleteAction.CASCADE; + } + + @Override + public String getExplicitForeignKeyName() { + return getEntityClass().getExplicitForeignKeyName(); + } + + @Override + public boolean createForeignKeyConstraint() { + return getEntityClass().createForeignKeyConstraint(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return fkColumnResolutionDelegate; + } + + @Override + public List getPrimaryKeyColumnSources() { + return columnSources; + } + + private static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final List targetColumnNames; + + private JoinColumnResolutionDelegateImpl(List targetColumnNames) { + this.targetColumnNames = targetColumnNames; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + List columns = new ArrayList(); + for ( String name : targetColumnNames ) { + // the nulls represent table, schema and catalog name which are ignored anyway... + columns.add( context.resolveColumn( name, null, null, null ) ); + } + return columns; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + + @Override + public String getReferencedAttributeName() { + return null; + } + + } + + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JpaCallbackSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JpaCallbackSourceImpl.java new file mode 100644 index 000000000000..a963c646a7d5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/JpaCallbackSourceImpl.java @@ -0,0 +1,117 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.lang.annotation.Annotation; +import javax.persistence.PostLoad; +import javax.persistence.PostPersist; +import javax.persistence.PostRemove; +import javax.persistence.PostUpdate; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.spi.JpaCallbackSource; + +/** + * @author Hardy Ferentschik + */ +public class JpaCallbackSourceImpl implements JpaCallbackSource { + private final JavaTypeDescriptor callbackTarget; + private final boolean isEntityListener; + private final String prePersistCallback; + private final String preRemoveCallback; + private final String preUpdateCallback; + private final String postLoadCallback; + private final String postPersistCallback; + private final String postRemoveCallback; + private final String postUpdateCallback; + + public JpaCallbackSourceImpl( + JavaTypeDescriptor callbackTarget, + boolean isEntityListener, + String prePersistCallback, + String preRemoveCallback, + String preUpdateCallback, + String postLoadCallback, + String postPersistCallback, + String postRemoveCallback, + String postUpdateCallback) { + this.callbackTarget = callbackTarget; + this.isEntityListener = isEntityListener; + this.prePersistCallback = prePersistCallback; + this.preRemoveCallback = preRemoveCallback; + this.preUpdateCallback = preUpdateCallback; + this.postLoadCallback = postLoadCallback; + this.postPersistCallback = postPersistCallback; + this.postRemoveCallback = postRemoveCallback; + this.postUpdateCallback = postUpdateCallback; + } + + @Override + public String getName() { + return callbackTarget.getName().toString(); + } + + @Override + public boolean isListener() { + return isEntityListener; + } + + @Override + public String getCallbackMethod(Class callbackType) { + if ( PrePersist.class.equals( callbackType ) ) { + return prePersistCallback; + } + else if ( PreRemove.class.equals( callbackType ) ) { + return preRemoveCallback; + } + else if ( PreUpdate.class.equals( callbackType ) ) { + return preUpdateCallback; + } + else if ( PostLoad.class.equals( callbackType ) ) { + return postLoadCallback; + } + else if ( PostPersist.class.equals( callbackType ) ) { + return postPersistCallback; + } + else if ( PostRemove.class.equals( callbackType ) ) { + return postRemoveCallback; + } + else if ( PostUpdate.class.equals( callbackType ) ) { + return postUpdateCallback; + } + + throw new IllegalArgumentException( "Unknown callback type requested : " + callbackType.getName() ); + } + + @Override + public String toString() { + return "JpaCallbackSourceImpl{callbackTarget=" + callbackTarget + + ", isEntityListener=" + isEntityListener + '}'; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedByPluralAttributeElementSourceAssociationManyToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedByPluralAttributeElementSourceAssociationManyToManyImpl.java new file mode 100644 index 000000000000..56f04a53538a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedByPluralAttributeElementSourceAssociationManyToManyImpl.java @@ -0,0 +1,67 @@ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; + +/** + * @author Gail Badner + */ +public class MappedByPluralAttributeElementSourceAssociationManyToManyImpl + extends AbstractPluralAttributeElementSourceAssociationManyToManyImpl + implements MappedByAssociationSource { + + public MappedByPluralAttributeElementSourceAssociationManyToManyImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + if ( pluralAssociationAttribute().getMappedByAttributeName() == null ) { + throw new AssertionFailure( "pluralAssociationAttribute().getMappedByAttributeName() must be non-null." ); + } + } + + @Override + public String getExplicitForeignKeyName() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); + } + + @Override + public boolean createForeignKeyConstraint() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean areValuesNullableByDefault() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } + + @Override + public boolean isMappedBy() { + return true; + } + + @Override + public String getMappedBy() { + return pluralAssociationAttribute().getMappedByAttributeName(); + } + + @Override + public List relationalValueSources() { + throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedByPluralAttributeElementSourceAssociationOneToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedByPluralAttributeElementSourceAssociationOneToManyImpl.java new file mode 100644 index 000000000000..6b54205503ee --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedByPluralAttributeElementSourceAssociationOneToManyImpl.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; + +/** + * @author Gail Badner + */ +public class MappedByPluralAttributeElementSourceAssociationOneToManyImpl + extends PluralAttributeElementSourceAssociationOneToManyImpl implements MappedByAssociationSource { + + public MappedByPluralAttributeElementSourceAssociationOneToManyImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + if ( pluralAttributeSource.pluralAssociationAttribute().getMappedByAttributeName() == null ) { + throw new AssertionFailure( "pluralAssociationAttribute().getMappedByAttributeName() must be non-null." ); + } + } + + @Override + public boolean isMappedBy() { + return true; + } + + @Override + public String getMappedBy() { + return pluralAssociationAttribute().getMappedByAttributeName(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedSuperclassSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedSuperclassSourceImpl.java new file mode 100644 index 000000000000..519e782d6e26 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MappedSuperclassSourceImpl.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.entity.MappedSuperclassTypeMetadata; +import org.hibernate.metamodel.source.spi.MappedSuperclassSource; + +/** + * Adapter for a MappedSuperclass + * + * @author Steve Ebersole + */ +public class MappedSuperclassSourceImpl extends IdentifiableTypeSourceAdapter implements MappedSuperclassSource { + /** + * Form for use in creating MappedSuperclassSource that are the supers of the root entity + * + * @param mappedSuperclassTypeMetadata Metadata about the MappedSuperclass + * @param hierarchy The hierarchy + */ + protected MappedSuperclassSourceImpl( + MappedSuperclassTypeMetadata mappedSuperclassTypeMetadata, + EntityHierarchySourceImpl hierarchy) { + // false here indicates that this is not the root entity of a hierarchy + super( mappedSuperclassTypeMetadata, hierarchy, false ); + } + + /** + * Form for use in creating MappedSuperclassSource that are part of the subclass tree of the root entity + * + * @param mappedSuperclassTypeMetadata Metadata about the MappedSuperclass + * @param hierarchy The hierarchy + * @param superTypeSource The source object for the super type. + */ + protected MappedSuperclassSourceImpl( + MappedSuperclassTypeMetadata mappedSuperclassTypeMetadata, + EntityHierarchySourceImpl hierarchy, + IdentifiableTypeSourceAdapter superTypeSource) { + super( mappedSuperclassTypeMetadata, hierarchy, superTypeSource ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MutliTenancySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MutliTenancySourceImpl.java new file mode 100644 index 000000000000..664287131226 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/MutliTenancySourceImpl.java @@ -0,0 +1,107 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.FormulaValue; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.MultiTenancySource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class MutliTenancySourceImpl implements MultiTenancySource { + private final RelationalValueSource relationalValueSource; + private final boolean shared; + private final boolean bindAsParameter; + + public MutliTenancySourceImpl(EntityTypeMetadata entityTypeMetadata) { + final ClassLoaderService classLoaderService = entityTypeMetadata.getLocalBindingContext() + .getBuildingOptions() + .getServiceRegistry() + .getService( ClassLoaderService.class ); + + final AnnotationInstance columnAnnotation = entityTypeMetadata.getJavaTypeDescriptor().findTypeAnnotation( HibernateDotNames.TENANT_COLUMN + ); + if ( columnAnnotation != null ) { + final Column column = new Column( null ); + column.setName( JandexHelper.getValue( columnAnnotation, "column", String.class, classLoaderService ) ); + column.setTable( null ); // primary table + column.setLength( JandexHelper.getValue( columnAnnotation, "length", int.class, classLoaderService ) ); + column.setPrecision( JandexHelper.getValue( columnAnnotation, "precision", int.class, classLoaderService ) ); + column.setScale( JandexHelper.getValue( columnAnnotation, "scale", int.class, classLoaderService ) ); + // todo : type + relationalValueSource = new ColumnSourceImpl( column ); + } + else { + final AnnotationInstance formulaAnnotation = entityTypeMetadata.getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.TENANT_FORMULA + ); + if ( formulaAnnotation != null ) { + relationalValueSource = new DerivedValueSourceImpl( + new FormulaValue( + null, // primary table + JandexHelper.getValue( formulaAnnotation, "value", String.class, classLoaderService ) + ) + ); + } + else { + relationalValueSource = null; + } + } + + final AnnotationInstance multiTenantAnnotation = entityTypeMetadata.getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.MULTI_TENANT + ); + if ( multiTenantAnnotation == null ) { + shared = true; + bindAsParameter = true; + } + else { + shared = JandexHelper.getValue( multiTenantAnnotation, "shared", Boolean.class, classLoaderService ); + bindAsParameter = JandexHelper.getValue( multiTenantAnnotation, "useParameterBinding", Boolean.class, classLoaderService ); + } + } + + @Override + public RelationalValueSource getRelationalValueSource() { + return relationalValueSource; + } + + @Override + public boolean isShared() { + return shared; + } + + @Override + public boolean bindAsParameter() { + return bindAsParameter; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/NonAggregatedCompositeIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/NonAggregatedCompositeIdentifierSourceImpl.java new file mode 100644 index 000000000000..2e5efb738d84 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/NonAggregatedCompositeIdentifierSourceImpl.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** +* @author Steve Ebersole +*/ +class NonAggregatedCompositeIdentifierSourceImpl + extends AbstractIdentifierSource + implements NonAggregatedCompositeIdentifierSource { + + private final List idAttributes; + private final Class lookupIdClass; + + public NonAggregatedCompositeIdentifierSourceImpl(RootEntitySourceImpl rootEntitySource) { + super( rootEntitySource ); + + this.idAttributes = rootEntitySource.getIdentifierAttributes(); + + final JavaTypeDescriptor idClassDescriptor = resolveIdClassDescriptor(); + if ( idClassDescriptor == null ) { + // probably this is an error... + this.lookupIdClass = null; + } + else { + final ClassLoaderService cls = rootEntitySource.getLocalBindingContext() + .getServiceRegistry() + .getService( ClassLoaderService.class ); + this.lookupIdClass = cls.classForName( idClassDescriptor.getName().toString() ); + } + } + + private JavaTypeDescriptor resolveIdClassDescriptor() { + final AnnotationInstance idClassAnnotation = rootEntitySource().getEntityClass() + .getJavaTypeDescriptor() + .findTypeAnnotation( JPADotNames.ID_CLASS ); + + if ( idClassAnnotation == null ) { + return null; + } + + if ( idClassAnnotation.value() == null ) { + return null; + } + + return rootEntitySource().getLocalBindingContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( idClassAnnotation.value().asString() ) + ); + } + + @Override + public Class getLookupIdClass() { + return lookupIdClass; + } + + @Override + public String getIdClassPropertyAccessorName() { + return idAttributes.get( 0 ).getPropertyAccessorName(); + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + // annotations do not currently allow generators to be attached to composite identifiers as a whole + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public Collection getToolingHintSources() { + // not relevant for annotations + // todo : however, it is relevant for mocked annotations comeing from XML!!! + return Collections.emptySet(); + } + + @Override + public List getAttributeSourcesMakingUpIdentifier() { + return idAttributes; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationManyToAnyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationManyToAnyImpl.java new file mode 100644 index 000000000000..01467b39208d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationManyToAnyImpl.java @@ -0,0 +1,22 @@ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToAny; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Hardy Ferentschik + */ +public class PluralAttributeElementSourceAssociationManyToAnyImpl + extends AbstractPluralElementSourceAssociationImpl + implements PluralAttributeElementSourceManyToAny { + + public PluralAttributeElementSourceAssociationManyToAnyImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.MANY_TO_ANY; + } +} + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationManyToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationManyToManyImpl.java new file mode 100644 index 000000000000..a9de8f83f69b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationManyToManyImpl.java @@ -0,0 +1,165 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Hardy Ferentschik + * @author Brett Meyer + * @author Gail Badner + */ +public class PluralAttributeElementSourceAssociationManyToManyImpl + extends AbstractPluralAttributeElementSourceAssociationManyToManyImpl + implements PluralAttributeElementSourceManyToMany { + + private final List relationalValueSources = new ArrayList(); + + public PluralAttributeElementSourceAssociationManyToManyImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + if ( pluralAttributeSource.getMappedBy() != null ) { + throw new AssertionFailure( "pluralAttributeSource.getMappedByAttributeName() must be null." ); + } + for ( Column column : pluralAttributeSource.pluralAssociationAttribute().getInverseJoinColumnValues() ) { + relationalValueSources.add( new ColumnSourceImpl( column ) ); + } + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + + @Override + public String getExplicitForeignKeyName() { + return pluralAssociationAttribute().getInverseForeignKeyName(); + } + + @Override + public boolean createForeignKeyConstraint() { + return pluralAssociationAttribute().createForeignKeyConstraint(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + boolean hasReferencedColumn = false; + for ( Column joinColumn : pluralAssociationAttribute().getInverseJoinColumnValues() ) { + if ( joinColumn.getReferencedColumnName() != null ) { + hasReferencedColumn = true; + break; + } + } + return hasReferencedColumn ? + new AnnotationJoinColumnResolutionDelegate() : + null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + // TODO: This needs reworked. + public class AnnotationJoinColumnResolutionDelegate + implements ForeignKeyContributingSource.JoinColumnResolutionDelegate { + private final String logicalJoinTableName; + + public AnnotationJoinColumnResolutionDelegate() { + logicalJoinTableName = resolveLogicalJoinTableName(); + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + final List values = new ArrayList(); + for ( Column column : pluralAssociationAttribute().getInverseJoinColumnValues() ) { + org.hibernate.metamodel.spi.relational.Column resolvedColumn = context.resolveColumn( + column.getReferencedColumnName(), + null, + null, + null + ); + values.add( resolvedColumn ); + } + return values; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + + @Override + public String getReferencedAttributeName() { + // HBM only + return null; + } + + private String resolveLogicalJoinTableName() { + final AnnotationInstance joinTableAnnotation = getPluralAttribute().getBackingMember() + .getAnnotations() + .get( JPADotNames.JOIN_TABLE ); + + if ( joinTableAnnotation != null ) { + final AnnotationValue nameValue = joinTableAnnotation.value( "name" ); + if ( nameValue != null ) { + return StringHelper.nullIfEmpty( nameValue.asString() ); + } + } + + // todo : this ties into the discussion about naming strategies. This would be part of a logical naming strategy... + return null; + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationOneToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationOneToManyImpl.java new file mode 100644 index 000000000000..a8a56253df1c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceAssociationOneToManyImpl.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceOneToMany; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Hardy Ferentschik + */ +public class PluralAttributeElementSourceAssociationOneToManyImpl + extends AbstractPluralElementSourceAssociationImpl + implements PluralAttributeElementSourceOneToMany { + + public PluralAttributeElementSourceAssociationOneToManyImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.ONE_TO_MANY; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceBasicImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceBasicImpl.java new file mode 100644 index 000000000000..da9cc350839a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceBasicImpl.java @@ -0,0 +1,80 @@ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceBasic; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Hardy Ferentschik + */ +public class PluralAttributeElementSourceBasicImpl + extends AbstractPluralAttributeElementSourceImpl + implements PluralAttributeElementSourceBasic { + private final PluralAttributeElementNature nature; + + public PluralAttributeElementSourceBasicImpl(PluralAttributeSourceImpl pluralAttributeSource) { + super( pluralAttributeSource ); + this.nature = resolveNature( getPluralAttribute() ); + } + + @Override + public HibernateTypeSource getExplicitHibernateTypeSource() { + return new HibernateTypeSourceImpl( getPluralAttribute() ); + } + + @Override + public PluralAttributeElementNature getNature() { + return nature; + } + + private static PluralAttributeElementNature resolveNature(PluralAttribute attribute){ + switch ( attribute.getNature() ) { + case ELEMENT_COLLECTION_BASIC: { + return PluralAttributeElementNature.BASIC; + } + case ELEMENT_COLLECTION_EMBEDDABLE: { + return PluralAttributeElementNature.AGGREGATE; + } + default: { + throw new AssertionError( + "Wrong attribute nature for a element collection attribute: " + attribute.getNature() + ); + } + } + } + + @Override + public List relationalValueSources() { + List valueSources = new ArrayList(); + if ( !getPluralAttribute().getColumnValues().isEmpty() ) { + for ( Column columnValues : getPluralAttribute().getColumnValues() ) { + valueSources.add( new ColumnSourceImpl( columnValues ) ); + } + } + return valueSources; + } + + // TODO - these values are also hard coded in the hbm version of this source implementation. Do we really need them? (HF) + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceEmbeddedImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceEmbeddedImpl.java new file mode 100644 index 000000000000..4c858aa0f158 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeElementSourceEmbeddedImpl.java @@ -0,0 +1,78 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeElementDetailsEmbedded; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceEmbedded; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Brett Meyer + */ +public class PluralAttributeElementSourceEmbeddedImpl + implements PluralAttributeElementSourceEmbedded { + private final PluralAttribute pluralAttribute; + private final Set unifiedCascadeStyles; + private final PluralAttributeElementDetailsEmbedded elementDescriptor; + + private final EmbeddableSourceImpl embeddableSource; + + public PluralAttributeElementSourceEmbeddedImpl(PluralAttributeSourceImpl pluralAttributeSource) { + this.pluralAttribute = pluralAttributeSource.getPluralAttribute(); + this.unifiedCascadeStyles = pluralAttributeSource.getUnifiedCascadeStyles(); + + this.elementDescriptor = (PluralAttributeElementDetailsEmbedded) pluralAttribute.getElementDetails(); + this.embeddableSource = new EmbeddableSourceImpl( + elementDescriptor.getEmbeddableTypeMetadata(), + SourceHelper.PluralAttributesDisallowedAttributeBuilder.INSTANCE + ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.AGGREGATE; + } + + + @Override + public EmbeddableSource getEmbeddableSource() { + return embeddableSource; + } + + @Override + public Set getCascadeStyles() { + return unifiedCascadeStyles; + } + + @Override + public Collection getToolingHintSources() { + // HBM only + return Collections.emptyList(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeIdBagSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeIdBagSourceImpl.java new file mode 100644 index 000000000000..783e5397a94d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeIdBagSourceImpl.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeIdBagSourceImpl extends PluralAttributeSourceImpl { + public PluralAttributeIdBagSourceImpl( + PluralAttribute pluralAttribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( pluralAttribute, overrideAndConverterCollector ); + } + + // todo : source contracts still need a notion of id-bag +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeIndexedSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeIndexedSourceImpl.java new file mode 100644 index 000000000000..b9dbf99c5283 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeIndexedSourceImpl.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.EnumSet; + +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * @author Strong Liu + * @author Steve Ebersole + */ +public class PluralAttributeIndexedSourceImpl + extends PluralAttributeSourceImpl + implements IndexedPluralAttributeSource { + + private final static EnumSet VALID_NATURES = EnumSet.of( + AbstractPersistentAttribute.Nature.MANY_TO_MANY, + AbstractPersistentAttribute.Nature.ONE_TO_MANY, + AbstractPersistentAttribute.Nature.ELEMENT_COLLECTION_BASIC, + AbstractPersistentAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE + ); + + private PluralAttributeIndexSource indexSource; + + public PluralAttributeIndexedSourceImpl( + PluralAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( attribute, overrideAndConverterCollector ); + if ( !VALID_NATURES.contains( attribute.getNature() ) ) { + throw new MappingException( + "Indexed column could be only mapped on the MANY side", + attribute.getContext().getOrigin() + ); + } + + if ( attribute.getPluralAttributeNature() == PluralAttributeNature.ARRAY + && !attribute.getBackingMember().getAnnotations().containsKey( JPADotNames.ORDER_COLUMN ) ) { + throw attribute.getContext().makeMappingException( + "Persistent arrays must be annotated with @OrderColumn : " + attribute.getRole() + ); + } + + this.indexSource = new PluralAttributeSequentialIndexSourceImpl( attribute ); + } + + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeKeySourceImpl.java new file mode 100644 index 000000000000..86017f75f9f0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeKeySourceImpl.java @@ -0,0 +1,137 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.spi.PluralAttributeKeySource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Hardy Ferentschik + * @author Strong Liu + */ +public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { + private final PluralAttribute attribute; + private final boolean isCascadeDeleteEnabled; + + public PluralAttributeKeySourceImpl(PluralAttribute attribute) { + this.attribute = attribute; + this.isCascadeDeleteEnabled = attribute.getOnDeleteAction() == OnDeleteAction.CASCADE; + } + @Override + public boolean isCascadeDeleteEnabled() { + return isCascadeDeleteEnabled; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public String getExplicitForeignKeyName() { + return attribute.getExplicitForeignKeyName(); + } + + @Override + public boolean createForeignKeyConstraint() { + return attribute.createForeignKeyConstraint(); + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + if ( attribute.getMappedByAttributeName() != null ) { + throw new IllegalStateException( "Cannot determine foreign key information because association is not the owner." ); + } + for ( Column joinColumn : attribute.getJoinColumnValues() ) { + if ( StringHelper.isNotEmpty( joinColumn.getReferencedColumnName() ) ) { + return new JoinColumnResolutionDelegateImpl( attribute ); + } + } + return null; + } + + @Override + public List relationalValueSources() { + List joinClumnValues = attribute.getJoinColumnValues(); + if ( joinClumnValues.isEmpty() ) { + return Collections.emptyList(); + } + List result = new ArrayList( joinClumnValues.size() ); + for ( Column joinColumn : joinClumnValues ) { + result.add( new ColumnSourceImpl( joinColumn ) ); + } + return result; + } + + public static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final PluralAttribute attribute; + + public JoinColumnResolutionDelegateImpl(PluralAttribute attribute) { + this.attribute = attribute; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + List joinColumnValues = attribute.getJoinColumnValues(); + if ( joinColumnValues.isEmpty() ) { + return null; + } + List result = new ArrayList( joinColumnValues.size() ); + for ( Column column : attribute.getJoinColumnValues() ) { + result.add( context.resolveColumn( column.getReferencedColumnName(), null, null, null ) ); + } + return result; + } + + @Override + public String getReferencedAttributeName() { + return null; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( null ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceBasicImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceBasicImpl.java new file mode 100644 index 000000000000..002683d21c86 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceBasicImpl.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeIndexDetailsMapKeyBasic; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceBasic; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * @author Steve Ebersole + * @author Strong Liu + */ +public class PluralAttributeMapKeySourceBasicImpl + extends AbstractPluralAttributeIndexSourceImpl + implements PluralAttributeMapKeySourceBasic { + private final List relationalValueSources; + private final Binder.DefaultNamingStrategy defaultNamingStrategy; + + public PluralAttributeMapKeySourceBasicImpl( + PluralAttribute attribute, + PluralAttributeIndexDetailsMapKeyBasic mapKeyDetails) { + super( attribute ); + this.defaultNamingStrategy = new PluralAttributeMapSourceImpl.MapKeyColumnDefaultNaming( attribute ); + this.relationalValueSources = Collections.singletonList( + (RelationalValueSource) new ColumnSourceImpl( new Column( mapKeyDetails.getMapKeyColumnAnnotation() ) ) + ); + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.BASIC; + } + + @Override + public List getDefaultNamingStrategies() { + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceEmbeddedImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceEmbeddedImpl.java new file mode 100644 index 000000000000..959597642894 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceEmbeddedImpl.java @@ -0,0 +1,98 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeIndexDetailsMapKeyEmbedded; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceEmbedded; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * @author Gail Badner + */ +public class PluralAttributeMapKeySourceEmbeddedImpl + extends AbstractPluralAttributeIndexSourceImpl + implements PluralAttributeMapKeySourceEmbedded { + + private final EmbeddableSourceImpl embeddableSource; + private final Binder.DefaultNamingStrategy defaultNamingStrategy; + + public PluralAttributeMapKeySourceEmbeddedImpl( + PluralAttribute attribute, + PluralAttributeIndexDetailsMapKeyEmbedded mapKeyDetails) { + super( attribute ); + + this.embeddableSource = new EmbeddableSourceImpl( + mapKeyDetails.getEmbeddableTypeMetadata(), + SourceHelper.IdentifierPathAttributeBuilder.INSTANCE + ); + this.defaultNamingStrategy = new PluralAttributeMapSourceImpl.MapKeyColumnDefaultNaming( attribute ); + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.AGGREGATE; + } + + @Override + public EmbeddableSource getEmbeddableSource() { + return embeddableSource; + } + + @Override + public List getDefaultNamingStrategies() { + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public List relationalValueSources() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return false; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + public JavaTypeDescriptor getTypeDescriptor() { + return embeddableSource.getTypeDescriptor(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceEntityAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceEntityAttributeImpl.java new file mode 100644 index 000000000000..b57a939da62d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapKeySourceEntityAttributeImpl.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSourceResolver; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceEntityAttribute; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SimpleIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * Modeling of the JPA {@link javax.persistence.MapKey} annotation + * + * @author Steve Ebersole + */ +public class PluralAttributeMapKeySourceEntityAttributeImpl + extends AbstractPluralAttributeIndexSourceImpl + implements PluralAttributeMapKeySourceEntityAttribute, PluralAttributeIndexSourceResolver { + + private final String mapKeyAttributeName; + private final Binder.DefaultNamingStrategy defaultNamingStrategy; + private SingularAttributeSource mapKeyAttributeSource; + + public PluralAttributeMapKeySourceEntityAttributeImpl( + PluralAttribute attribute, + String mapKeyAttributeName) { + super( attribute ); + this.mapKeyAttributeName = mapKeyAttributeName; + this.defaultNamingStrategy = new PluralAttributeMapSourceImpl.MapKeyColumnDefaultNaming( attribute ); + } + + @Override + public PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext context) { + if ( mapKeyAttributeName == null ) { + final IdentifierSource identifierSource = context.resolveIdentifierSource( + pluralAttribute().getElementDetails().getJavaType().getName().toString() + ); + switch ( identifierSource.getNature() ) { + case SIMPLE: { + mapKeyAttributeSource = ( (SimpleIdentifierSource) identifierSource ).getIdentifierAttributeSource(); + break; + } + case AGGREGATED_COMPOSITE: { + mapKeyAttributeSource = ( (AggregatedCompositeIdentifierSource) identifierSource ).getIdentifierAttributeSource(); + } + default: { + throw pluralAttribute().getContext().makeMappingException( + "Non-aggregated composite identifiers are not supported for @MapKey" + ); + } + } + } + else { + AttributeSource attributeSource = context.resolveAttributeSource( + pluralAttribute().getElementDetails().getJavaType().getName().toString(), + mapKeyAttributeName + ); + if ( ! attributeSource.isSingular() ) { + throw new MappingException( + String.format( + "Plural attribute index [%s.%s] is not a singular attribute.", + pluralAttribute().getElementDetails().getJavaType().getName().toString(), + mapKeyAttributeName + ), + pluralAttribute().getContext().getOrigin() + ); + } + mapKeyAttributeSource = (SingularAttributeSource) attributeSource; + } + + return this; + } + + @Override + public String getAttributeName() { + return mapKeyAttributeName; + } + + @Override + public PluralAttributeIndexNature getNature() { + if ( mapKeyAttributeSource == null ) { + return null; + } + + switch ( mapKeyAttributeSource.getSingularAttributeNature() ) { + case BASIC: { + return PluralAttributeIndexNature.BASIC; + } + case COMPOSITE: { + return PluralAttributeIndexNature.AGGREGATE; + } + case ANY: { + return PluralAttributeIndexNature.MANY_TO_ANY; + } + case MANY_TO_ONE: { + return PluralAttributeIndexNature.MANY_TO_MANY; + } + default: { + throw pluralAttribute().getContext().makeMappingException( + "Unexpected attribute nature : " + mapKeyAttributeSource.getSingularAttributeNature() + ); + } + } + } + + @Override + public List getDefaultNamingStrategies() { + return null; + } + + @Override + public List relationalValueSources() { + if ( mapKeyAttributeSource == null ) { + return null; + } + return mapKeyAttributeSource.relationalValueSources(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapSourceImpl.java new file mode 100644 index 000000000000..9c5280edf1ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeMapSourceImpl.java @@ -0,0 +1,102 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeIndexDetails; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeIndexDetailsMapKeyBasic; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeIndexDetailsMapKeyEmbedded; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttributeIndexDetailsMapKeyEntityAttribute; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeMapSourceImpl + extends PluralAttributeSourceImpl + implements IndexedPluralAttributeSource { + private final PluralAttributeIndexSource mapKeySource; + + public PluralAttributeMapSourceImpl( + PluralAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( attribute, overrideAndConverterCollector ); + + this.mapKeySource = determineMapKeySourceInfo( attribute ); + } + + protected PluralAttributeIndexSource determineMapKeySourceInfo(final PluralAttribute attribute) { + final PluralAttributeIndexDetails mapKeyDetails = attribute.getIndexDetails(); + + if ( mapKeyDetails.getIndexNature() == null ) { + return new PluralAttributeMapKeySourceEntityAttributeImpl( + attribute, + ( (PluralAttributeIndexDetailsMapKeyEntityAttribute) mapKeyDetails ).getReferencedAttributeName() + ); + } + + switch ( mapKeyDetails.getIndexNature() ) { + case BASIC: { + return new PluralAttributeMapKeySourceBasicImpl( + attribute, + (PluralAttributeIndexDetailsMapKeyBasic) mapKeyDetails + ); + } + case AGGREGATE: { + return new PluralAttributeMapKeySourceEmbeddedImpl( + attribute, + (PluralAttributeIndexDetailsMapKeyEmbedded) mapKeyDetails + ); + } + default: { + throw attribute.getContext().makeMappingException( + "Support for entities as map keys is not yet implemented" + ); + } + } + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return mapKeySource; + } + + static class MapKeyColumnDefaultNaming implements Binder.DefaultNamingStrategy { + private final PluralAttribute pluralAttribute; + + MapKeyColumnDefaultNaming(PluralAttribute pluralAttribute) { + this.pluralAttribute = pluralAttribute; + } + + @Override + public String defaultName(NamingStrategy namingStrategy) { + return pluralAttribute.getName() + "_KEY"; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeSequentialIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeSequentialIndexSourceImpl.java new file mode 100644 index 000000000000..41fb821540e7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeSequentialIndexSourceImpl.java @@ -0,0 +1,110 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Gail Badner + */ +public class PluralAttributeSequentialIndexSourceImpl + extends AbstractPluralAttributeIndexSourceImpl + implements PluralAttributeSequentialIndexSource { + + private final int base; + private final RelationalValueSource relationalValueSource; + private final Binder.DefaultNamingStrategy defaultNamingStrategy; + + private final static HibernateTypeSource INTEGER_TYPE = new HibernateTypeSource() { + @Override + public String getName() { + return "integer"; + } + + @Override + public Map getParameters() { + return Collections.emptyMap(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + + public PluralAttributeSequentialIndexSourceImpl(final PluralAttribute attribute) { + super( attribute ); + final AnnotationInstance columnAnnotation = attribute.getBackingMember().getAnnotations() + .get( JPADotNames.ORDER_COLUMN ); + this.base = columnAnnotation.value( "base" ) != null + ? columnAnnotation.value( "base" ).asInt() + : 0; + this.relationalValueSource = new ColumnSourceImpl( new Column( columnAnnotation ) ); + this.defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return attribute.getName() + "_ORDER"; + } + }; + } + + @Override + public int base() { + return base; + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.SEQUENTIAL; + } + + @Override + public List getDefaultNamingStrategies() { + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return INTEGER_TYPE; + } + + @Override + public List relationalValueSources() { + return Collections.singletonList( relationalValueSource ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeSourceImpl.java new file mode 100644 index 000000000000..6ee85c21e15c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/PluralAttributeSourceImpl.java @@ -0,0 +1,590 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.AssertionFailure; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.CollectionIdInformation; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.spi.AssociationSource; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.CollectionIdSource; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.Orderable; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSource; +import org.hibernate.metamodel.source.spi.PluralAttributeKeySource; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.Sortable; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Hardy Ferentschik + */ +public class PluralAttributeSourceImpl + implements AnnotationAttributeSource, PluralAttributeSource, Orderable, Sortable { + private final PluralAttribute pluralAttribute; + private final PluralAttributeNature nature; + + private final Set unifiedCascadeStyles; + + private final HibernateTypeSource typeSource; + private final PluralAttributeKeySource keySource; + private final FilterSource[] filterSources; + + private final CollectionIdSource collectionIdSource; + + // If it is not the owner side (i.e., mappedBy != null), then the AttributeSource + // for the owner is required to determine elementSource. + private PluralAttributeElementSource elementSource; + private AttributeSource ownerAttributeSource; + + public PluralAttributeSourceImpl( + PluralAttribute pluralAttribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + this.pluralAttribute = pluralAttribute; + this.nature = pluralAttribute.getPluralAttributeNature(); + + this.unifiedCascadeStyles = determineCascadeStyles( pluralAttribute ); + + this.keySource = new PluralAttributeKeySourceImpl( pluralAttribute ); + this.typeSource = new HibernateTypeSourceImpl( pluralAttribute ); + + + if ( pluralAttribute.getMappedByAttributeName() == null ) { + this.ownerAttributeSource = this; + this.elementSource = determineElementSource( this, this ); + } + this.filterSources = determineFilterSources( pluralAttribute ); + + if ( pluralAttribute.getCollectionIdInformation() == null ) { + this.collectionIdSource = null; + } + else { + collectionIdSource = new CollectionIdSourceImpl( + pluralAttribute.getCollectionIdInformation(), + pluralAttribute.getContext() + ); + } + } + + private static Set determineCascadeStyles(PluralAttribute pluralAttribute) { + final Set cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( + pluralAttribute.getJpaCascadeTypes(), + pluralAttribute.getHibernateCascadeTypes(), + pluralAttribute.getContext() + ); + if ( pluralAttribute.isOrphanRemoval() ) { + cascadeStyles.add( CascadeStyles.DELETE_ORPHAN ); + } + return cascadeStyles; + } + + private FilterSource[] determineFilterSources(PluralAttribute associationAttribute) { + final List result = new ArrayList(); + + final AnnotationInstance filtersAnnotation = associationAttribute.getBackingMember() + .getAnnotations() + .get( HibernateDotNames.FILTERS ); + if ( filtersAnnotation != null ) { + AnnotationInstance[] annotationInstances = filtersAnnotation.value().asNestedArray(); + for ( AnnotationInstance filterAnnotation : annotationInstances ) { + result.add( new FilterSourceImpl( filterAnnotation ) ); + } + + } + + final AnnotationInstance filterAnnotation = associationAttribute.getBackingMember() + .getAnnotations() + .get( HibernateDotNames.FILTER ); + if ( filterAnnotation != null ) { + result.add( new FilterSourceImpl( filterAnnotation ) ); + } + + if ( result.isEmpty() ) { + return null; + } + else { + return result.toArray( new FilterSource[result.size()] ); + } + } + + @Override + public AttributePath getAttributePath() { + return pluralAttribute.getPath(); + } + + @Override + public AttributeRole getAttributeRole() { + return pluralAttribute.getRole(); + } + + @Override + public CollectionIdSource getCollectionIdSource() { + return collectionIdSource; + } + + @Override + public PersistentAttribute getAnnotatedAttribute() { + return getPluralAttribute(); + } + + public PluralAttribute getPluralAttribute() { + return pluralAttribute; + } + + public Set getUnifiedCascadeStyles() { + return unifiedCascadeStyles; + } + + @Override + public PluralAttributeNature getNature() { + return nature; + } + + @Override + public PluralAttributeElementSource getElementSource() { + if ( elementSource == null ) { + throw new IllegalStateException( "elementSource has not been initialized yet." ); + } + return elementSource; + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public int getBatchSize() { + return pluralAttribute.getBatchSize(); + } + + @Override + public boolean usesJoinTable() { + if ( pluralAttribute.getMappedByAttributeName() != null ) { + throw new IllegalStateException( "Cannot determine if a join table is used because plural attribute is not the owner." ); + } + // By default, a unidirectional one-to-many (i.e., with mappedBy == null) uses a join table, + // unless it has join columns defined. + return pluralAttribute.getJoinTableAnnotation() != null || + ( pluralAttribute.getJoinTableAnnotation() == null && + pluralAttribute.getJoinColumnValues().size() == 0 ); + } + + @Override + public JavaTypeDescriptor getElementTypeDescriptor() { + // needed for arrays + if ( ArrayDescriptor.class.isInstance( pluralAttribute.getBackingMember().getType().getErasedType() ) ) { + final ArrayDescriptor arrayDescriptor = (ArrayDescriptor) pluralAttribute.getBackingMember().getType().getErasedType(); + return arrayDescriptor.getComponentType(); + } + else { + return null; + } + } + + private static PluralAttributeElementSource determineElementSource( + AttributeSource ownerAttributeSource, + PluralAttributeSourceImpl pluralAttributeSource) { + if ( ownerAttributeSource == null ) { + throw new AssertionFailure( "ownerAssociationSource must be non-null." ); + } + + final PluralAttribute associationAttribute = pluralAttributeSource.pluralAssociationAttribute(); + switch ( pluralAttributeSource.pluralAssociationAttribute().getNature() ) { + case ELEMENT_COLLECTION_BASIC: { + return new PluralAttributeElementSourceBasicImpl( pluralAttributeSource ); + } + case ELEMENT_COLLECTION_EMBEDDABLE: { + return new PluralAttributeElementSourceEmbeddedImpl( pluralAttributeSource ); + } + case MANY_TO_MANY: { + if ( associationAttribute.getMappedByAttributeName() == null ) { + return new PluralAttributeElementSourceAssociationManyToManyImpl( pluralAttributeSource ); + } + else { + return new MappedByPluralAttributeElementSourceAssociationManyToManyImpl( pluralAttributeSource ); + } + } + case ONE_TO_MANY: { + final boolean usesJoinTable = ownerAttributeSource.isSingular() + ? ( (ToOneAttributeSource) ownerAttributeSource ).getContainingTableName() != null + : ( (PluralAttributeSource) ownerAttributeSource ).usesJoinTable(); + + if ( usesJoinTable ) { + if ( associationAttribute.getMappedByAttributeName() == null ) { + return new PluralAttributeElementSourceAssociationManyToManyImpl( pluralAttributeSource ); + } + else { + return new MappedByPluralAttributeElementSourceAssociationManyToManyImpl( pluralAttributeSource ); + } + } + else { + if ( associationAttribute.getMappedByAttributeName() == null ) { + return new PluralAttributeElementSourceAssociationOneToManyImpl( pluralAttributeSource ); + } + else { + return new MappedByPluralAttributeElementSourceAssociationOneToManyImpl( pluralAttributeSource ); + } + } + } + case MANY_TO_ANY: { + return new PluralAttributeElementSourceAssociationManyToAnyImpl( pluralAttributeSource ); + } + default: { + throw new AssertionError( "Unexpected plural attribute nature :" + associationAttribute.getNature() ); + } + } + } + + @Override + public PluralAttributeKeySource getKeySource() { + return keySource; + } + + @Override + public TableSpecificationSource getCollectionTableSpecificationSource() { + // todo - see org.hibernate.metamodel.internal.Binder#bindOneToManyCollectionKey + // todo - needs to cater for @CollectionTable and @JoinTable + if ( pluralAttribute.getMappedByAttributeName() != null ) { + throw new IllegalStateException( "Cannot get collection table because this association is not the owner." ); + } + final AnnotationInstance joinTableAnnotation = pluralAttribute.getJoinTableAnnotation(); + if ( joinTableAnnotation == null ) { + return null; + } + + return TableSourceImpl.build( joinTableAnnotation, pluralAttribute.getContext() ); + } + + @Override + public String getCollectionTableComment() { + return null; + } + + @Override + public String getCollectionTableCheck() { + return pluralAttribute.getCheckCondition(); + } + + @Override + public Caching getCaching() { + return pluralAttribute.getCaching(); + } + + @Override + public String getCustomPersisterClassName() { + return pluralAttribute.getCustomPersister(); + } + + @Override + public String getWhere() { + return pluralAttribute.getWhereClause(); + } + + @Override + public String getMappedBy() { + return pluralAttribute.getMappedByAttributeName(); + } + + @Override + public boolean isInverse() { + return getMappedBy() != null; + } + + @Override + public String getCustomLoaderName() { + return pluralAttribute.getCustomLoaderName(); + } + + @Override + public CustomSQL getCustomSqlInsert() { + return pluralAttribute.getCustomInsert(); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return pluralAttribute.getCustomUpdate(); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return pluralAttribute.getCustomDelete(); + } + + @Override + public CustomSQL getCustomSqlDeleteAll() { + return pluralAttribute.getCustomDeleteAll(); + } + + @Override + public String getName() { + return pluralAttribute.getName(); + } + + @Override + public boolean isSingular() { + return false; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + if ( StringHelper.isNotEmpty( pluralAttribute.getAccessorStrategy() ) ) { + return pluralAttribute.getAccessorStrategy(); + } + else if ( pluralAttribute.getAccessType() != null ) { + return pluralAttribute.getAccessType().name().toLowerCase(); + } + else { + return null; + } + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return pluralAttribute.isIncludeInOptimisticLocking(); + } + + @Override + public Collection getToolingHintSources() { + // not relevant for annotations + return Collections.emptySet(); + } + + @Override + public String getOrder() { + return elementSource.getNature() == PluralAttributeElementNature.MANY_TO_MANY ? + null : + pluralAttribute.getOrderBy(); + } + + @Override + public boolean isMutable() { + return pluralAttribute.isMutable(); + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getComparatorName() { + return pluralAttribute.getComparatorName(); + } + + @Override + public boolean isSorted() { + return pluralAttribute.isSorted(); + } + + @Override + public FetchTiming getFetchTiming() { + if ( pluralAttribute.isExtraLazy() ) { + return FetchTiming.EXTRA_LAZY; + } + else if ( pluralAttribute.isLazy() ) { + return FetchTiming.DELAYED; + } + else { + return FetchTiming.IMMEDIATE; + } + } + + @Override + public FetchStyle getFetchStyle() { + return pluralAttribute.getFetchStyle(); + } + + @Override + public PluralAttributeElementSource resolvePluralAttributeElementSource(AttributeSourceResolutionContext context) { + if ( elementSource == null ) { + buildElementSource( context ); + + } + return elementSource; + } + + private void buildElementSource(AttributeSourceResolutionContext context) { + // elementSource has not been initialized, so we need to resolve it using the + // association owner. + // Get the owner attribute source that maps the opposite side of the association. + ownerAttributeSource = context.resolveAttributeSource( + pluralAttribute.getElementDetails().getJavaType().getName().toString(), + pluralAttribute.getMappedByAttributeName() + ); + // Initialize resolved entitySource. + elementSource = determineElementSource( ownerAttributeSource, this ); + if ( !MappedByAssociationSource.class.isInstance( elementSource ) ) { + throw new AssertionFailure( "expected a mappedBy association." ); + } + final AssociationSource ownerAssociationSource; + if ( ownerAttributeSource.isSingular() ) { + ownerAssociationSource = (ToOneAttributeSource) ownerAttributeSource; + } + else { + final PluralAttributeSource pluralAttributeSource = (PluralAttributeSource) ownerAttributeSource; + if ( !AssociationSource.class.isInstance( pluralAttributeSource.getElementSource() ) ) { + throw new AssertionFailure( "Owner is not an association." ); + } + ownerAssociationSource = (AssociationSource) pluralAttributeSource.getElementSource(); + } + ownerAssociationSource.addMappedByAssociationSource( (MappedByAssociationSource) elementSource ); + } + + protected PluralAttribute pluralAssociationAttribute() { + return pluralAttribute; + } + + + private static class CollectionIdSourceImpl implements CollectionIdSource { + private final ColumnSourceImpl columnSource; + private final HibernateTypeSource typeSource; + private final String generatorName; + + public CollectionIdSourceImpl(CollectionIdInformation collectionIdInformation, EntityBindingContext context) { + this.columnSource = interpretColumns( collectionIdInformation.getColumns(), context ); + this.typeSource = createTypeSource( collectionIdInformation.getTypeResolver() ); + this.generatorName = collectionIdInformation.getGeneratorDefinition().getName(); + } + + private static ColumnSourceImpl interpretColumns(List columns, EntityBindingContext context) { + if ( columns == null || columns.isEmpty() ) { + return null; + } + + if ( columns.size() > 1 ) { + throw context.makeMappingException( "Expecting just one column for collection id" ); + } + + return new ColumnSourceImpl( columns.get( 0 ) ); + } + + private HibernateTypeSource createTypeSource(AttributeTypeResolver typeResolver) { + if ( typeResolver == null ) { + return EmptyHibernateTypeSource.INSTANCE; + } + + final String resolvedTypeName = typeResolver.getExplicitHibernateTypeName(); + if ( StringHelper.isEmpty( resolvedTypeName ) ) { + return EmptyHibernateTypeSource.INSTANCE; + } + + return new HibernateTypeSource() { + @Override + public String getName() { + return resolvedTypeName; + } + + @Override + public Map getParameters() { + return Collections.emptyMap(); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + } + + @Override + public ColumnSource getColumnSource() { + return null; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return null; + } + + @Override + public String getGeneratorName() { + return null; + } + } + + private static class EmptyHibernateTypeSource implements HibernateTypeSource { + /** + * Singleton access + */ + public static final EmptyHibernateTypeSource INSTANCE = new EmptyHibernateTypeSource(); + + @Override + public String getName() { + return null; + } + + @Override + public Map getParameters() { + return null; + } + + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/RootEntitySourceImpl.java new file mode 100644 index 000000000000..9cda8bc130c3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/RootEntitySourceImpl.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.RootEntityTypeMetadata; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Represents the source information for a "root entity" in an entity hierarchy + * as defined by annotations and XML overrides. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + * @author Brett Meyer + */ +public class RootEntitySourceImpl extends EntitySourceImpl { + private List identifierAttributes; + + /** + * Constructs the root entity. Called from the construction of the + * hierarchy. Part of a very choreographed series of constructor calls + * to build an entity hierarchy. + *

      + * The root entity in the hierarchy is a pivot of sorts. Above it, it is + * ok to have MappedSuperclasses. Below it, there will be a mix of + * Entity and MappedSuperclass. + *

      + * The MappedSuperclasses that are part of the root entity's super tree are + * created in duplicate. For example, given a typical scenario with a common + * MappedSuperclass used for all entities, each hierarchy gets its own copy + * of the MappedSuperclassSourceImpl for that common class. This is + * important because each usage might imply different default AccessType for + * attributes. + * + * @param entityTypeMetadata The metadata for the root entity + * @param hierarchy The hierarchy we are building + */ + public RootEntitySourceImpl( + RootEntityTypeMetadata entityTypeMetadata, + EntityHierarchySourceImpl hierarchy) { + super( entityTypeMetadata, hierarchy, true ); + + this.identifierAttributes = SourceHelper.buildIdentifierAttributeSources( + entityTypeMetadata, + SourceHelper.IdentifierPathAttributeBuilder.INSTANCE + ); + } + + public List getIdentifierAttributes() { + return identifierAttributes; + } + + @Override + public RootEntityTypeMetadata getEntityClass() { + return (RootEntityTypeMetadata) super.getEntityClass(); + } + + @Override + public EntityHierarchySourceImpl getHierarchy() { + return (EntityHierarchySourceImpl) super.getHierarchy(); + } + + @Override + protected boolean isRootEntity() { + return true; + } + + @Override + protected TableSpecificationSource buildPrimaryTable( + AnnotationInstance tableAnnotation, + EntityBindingContext bindingContext) { + return TableSourceImpl.build( tableAnnotation, getEntityClass().getRowId(), bindingContext ); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SecondaryTableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SecondaryTableSourceImpl.java new file mode 100644 index 000000000000..a24e09930e73 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SecondaryTableSourceImpl.java @@ -0,0 +1,167 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.SecondaryTableSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +public class SecondaryTableSourceImpl implements SecondaryTableSource { + private final TableSpecificationSource joinTable; + private final List columnSources; + private final JoinColumnResolutionDelegate fkColumnResolutionDelegate; + + public SecondaryTableSourceImpl( + TableSpecificationSource joinTable, + List joinColumns) { + this.joinTable = joinTable; + + // todo : following normal annotation idiom for source, we probably want to move this stuff up to EntityClass... + columnSources = new ArrayList(); + final List targetColumnNames = new ArrayList(); + boolean hadNamedTargetColumnReferences = false; + for ( Column joinColumn : joinColumns ) { + columnSources.add( + new ColumnSourceImpl( + joinColumn + ) + ); + targetColumnNames.add( joinColumn.getReferencedColumnName() ); + if ( joinColumn.getReferencedColumnName() != null ) { + hadNamedTargetColumnReferences = true; + } + } + + this.fkColumnResolutionDelegate = ! hadNamedTargetColumnReferences + ? null + : new JoinColumnResolutionDelegateImpl( targetColumnNames ); + } + + @Override + public TableSpecificationSource getTableSource() { + return joinTable; + } + + @Override + public List getPrimaryKeyColumnSources() { + return columnSources; + } + + @Override + public String getComment() { + return null; + } + + @Override + public FetchStyle getFetchStyle() { + return null; + } + + @Override + public boolean isInverse() { + return false; + } + + @Override + public boolean isOptional() { + return true; + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public CustomSQL getCustomSqlDelete() { + return null; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return null; + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return null; + } + + @Override + public String getExplicitForeignKeyName() { + // not supported from annotations, unless docs for @ForeignKey are wrong... + return null; + } + + @Override + public boolean createForeignKeyConstraint() { + // not supported from annotations, unless docs for @ForeignKey are wrong... + return true; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return fkColumnResolutionDelegate; + } + + private static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final List targetColumnNames; + + private JoinColumnResolutionDelegateImpl(List targetColumnNames) { + this.targetColumnNames = targetColumnNames; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + List columns = new ArrayList(); + for ( String name : targetColumnNames ) { + // the nulls represent table, schema and catalog name which are ignored anyway... + columns.add( context.resolveColumn( name, null, null, null ) ); + } + return columns; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + + @Override + public String getReferencedAttributeName() { + return null; + } + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SimpleIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SimpleIdentifierSourceImpl.java new file mode 100644 index 000000000000..a50edbf7b57a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SimpleIdentifierSourceImpl.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.source.spi.SimpleIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class SimpleIdentifierSourceImpl extends AbstractIdentifierSource implements SimpleIdentifierSource { + private final SingularAttributeSourceImpl attributeSource; + + public SimpleIdentifierSourceImpl(RootEntitySourceImpl rootEntitySource, SingularAttributeSourceImpl attributeSource) { + super( rootEntitySource ); + this.attributeSource = attributeSource; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.SIMPLE; + } + + @Override + public SingularAttributeSource getIdentifierAttributeSource() { + return attributeSource; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( BasicAttributeSourceImpl.class.isInstance( attributeSource ) ) { + return ( (BasicAttributeSourceImpl) attributeSource ).getAnnotatedAttribute().getIdentifierGeneratorDefinition(); + } + return null; + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public String getIdClassPropertyAccessorName() { + return attributeSource.getPropertyAccessorName(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SingularAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SingularAttributeSourceImpl.java new file mode 100644 index 000000000000..8150e86deab6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SingularAttributeSourceImpl.java @@ -0,0 +1,163 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collection; +import java.util.Collections; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAttribute; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * @author Hardy Ferentschik + */ +public abstract class SingularAttributeSourceImpl implements SingularAttributeSource, AnnotationAttributeSource { + private final SingularAttribute attribute; + private final HibernateTypeSource type; + + + public SingularAttributeSourceImpl(SingularAttribute attribute) { + this.attribute = attribute; + this.type = new HibernateTypeSourceImpl( attribute ); + } + + @Override + public PersistentAttribute getAnnotatedAttribute() { + return attribute; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return type; + } + + @Override + public String getPropertyAccessorName() { + return attribute.getAccessorStrategy(); + } + + @Override + public PropertyGeneration getGeneration() { + return attribute.getPropertyGeneration(); + } + + @Override + public boolean isLazy() { + return attribute.isLazy(); + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return attribute.getNaturalIdMutability(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return attribute.isIncludeInOptimisticLocking(); + } + + @Override + public String getName() { + return attribute.getName(); + } + + @Override + public String getContainingTableName() { + return null; + } + +// /** +// * very ugly, can we just return the columnSourceImpl anyway? +// */ +// @Override +// public List relationalValueSources() { +// if ( relationalValueSources == null ) { +// relationalValueSources = buildRelationalValueSources(); +// } +// return relationalValueSources; +// } +// +// private List buildRelationalValueSources() { +// List results = new ArrayList(); +// +//// if ( attributeOverride != null ) { +//// attributeOverride.apply( attribute ); +//// } +// +// boolean hasDefinedColumnSource = !attribute.getColumnValues().isEmpty(); +// if ( hasDefinedColumnSource ) { +// for ( Column columnValues : attribute.getColumnValues() ) { +// results.add( new ColumnSourceImpl( attribute, columnValues ) ); +// } +// } +// else if ( attribute.getFormulaValue() != null ) { +// results.add( new DerivedValueSourceImpl( attribute.getFormulaValue() ) ); +// } +// else if ( attribute instanceof BasicAttribute ) { +// //for column transformer +// BasicAttribute simpleAttribute = BasicAttribute.class.cast( attribute ); +// if ( simpleAttribute.getCustomReadFragment() != null && simpleAttribute.getCustomWriteFragment() != null ) { +// results.add( new ColumnSourceImpl( attribute, null ) ); +// } +// } +// return results; +// } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Collection getToolingHintSources() { + return Collections.emptySet(); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return attribute.isInsertable(); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return !attribute.isId() && attribute.isUpdatable(); + } + + @Override + public boolean areValuesNullableByDefault() { + return !attribute.isId() && attribute.isOptional(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SizeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SizeSourceImpl.java new file mode 100644 index 000000000000..ba464075c4ea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SizeSourceImpl.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.spi.SizeSource; + +/** + * @author Gail Badner + */ +public class SizeSourceImpl implements SizeSource { + + private final int length; + private final int precision; + private final int scale; + + public SizeSourceImpl(int precision, int scale, int length) { + this.precision = precision; + this.scale = scale; + this.length = length; + } + + public boolean isLengthDefined() { + return true; + } + + public int getLength() { + return length; + } + + public boolean isPrecisionDefined() { + return true; + } + + public int getPrecision() { + return precision; + } + + public boolean isScaleDefined() { + return true; + } + + public int getScale() { + return scale; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SourceHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SourceHelper.java new file mode 100644 index 000000000000..67c936af5751 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SourceHelper.java @@ -0,0 +1,417 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.EmbeddedAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.IdentifiableTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.MappedSuperclassTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.RootEntityTypeMetadata; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; + +/** + * Utilities for building attribute source objects. + * + * @author Steve Ebersole + * @author Strong Liu + */ +public class SourceHelper { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( SourceHelper.class ); + + // todo : the walking supers bits here is due to the total lack of understanding of MappedSuperclasses in Binder... + + public static List buildAttributeSources( + ManagedTypeMetadata managedTypeMetadata, + AttributeBuilder attributeBuilder) { + final List result = new ArrayList(); + + if ( EntityTypeMetadata.class.isInstance( managedTypeMetadata ) ) { + final EntityTypeMetadata entityTypeMetadata = (EntityTypeMetadata) managedTypeMetadata; + + IdentifiableTypeMetadata currentSuperType = entityTypeMetadata.getSuperType(); + + while ( currentSuperType != null && MappedSuperclassTypeMetadata.class.isInstance( currentSuperType ) ) { + collectAttributeSources( result, currentSuperType, entityTypeMetadata, attributeBuilder ); + + currentSuperType = currentSuperType.getSuperType(); + } + } + + collectAttributeSources( result, managedTypeMetadata, managedTypeMetadata, attributeBuilder ); + + return result; + } + + private static void collectAttributeSources( + List result, + ManagedTypeMetadata managedTypeMetadata, + OverrideAndConverterCollector overrideAndConverterCollector, + AttributeBuilder attributeBuilder) { + for ( PersistentAttribute attribute : managedTypeMetadata.getPersistentAttributeMap().values() ) { + switch ( attribute.getNature() ) { + case BASIC: { + result.add( + attributeBuilder.buildBasicAttribute( + (BasicAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case EMBEDDED: { + result.add( + attributeBuilder.buildEmbeddedAttribute( + (EmbeddedAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case MANY_TO_ONE: + case ONE_TO_ONE: { + result.add( + attributeBuilder.buildToOneAttribute( + (SingularAssociationAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case MANY_TO_MANY: + case ONE_TO_MANY: + case ELEMENT_COLLECTION_BASIC: + case ELEMENT_COLLECTION_EMBEDDABLE: { + result.add( + attributeBuilder.buildPluralAttribute( + (PluralAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case ANY: { + result.add( + attributeBuilder.buildAnyAttribute( + attribute, + overrideAndConverterCollector + ) + ); + break; + } + case MANY_TO_ANY: { + result.add( + attributeBuilder.buildManyToAnyAttribute( + attribute, + overrideAndConverterCollector + ) + ); + break; + } + default: { + throw managedTypeMetadata.getLocalBindingContext().makeMappingException( + "Unexpected PersistentAttribute nature encountered : " + attribute.getNature() + ); + } + } + } + } + + public static List buildIdentifierAttributeSources( + RootEntityTypeMetadata rootEntityTypeMetadata, + AttributeBuilder attributeBuilder) { + final List result = new ArrayList(); + +// we already specially collect identifier attributes +// IdentifiableTypeMetadata currentSuperType = rootEntityTypeMetadata.getSuperType(); +// while ( currentSuperType != null && MappedSuperclassTypeMetadata.class.isInstance( currentSuperType ) ) { +// collectIdentifierAttributeSources( result, currentSuperType, rootEntityTypeMetadata, attributeBuilder ); +// +// currentSuperType = currentSuperType.getSuperType(); +// } + + collectIdentifierAttributeSources( result, rootEntityTypeMetadata, rootEntityTypeMetadata, attributeBuilder ); + + return result; + } + + private static void collectIdentifierAttributeSources( + List result, + IdentifiableTypeMetadata identifiableTypeMetadata, + OverrideAndConverterCollector overrideAndConverterCollector, + AttributeBuilder attributeBuilder) { + for ( PersistentAttribute attribute : identifiableTypeMetadata.getIdentifierAttributes() ) { + switch ( attribute.getNature() ) { + case BASIC: { + result.add( + attributeBuilder.buildBasicAttribute( + (BasicAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case EMBEDDED: + case EMBEDDED_ID: { + result.add( + attributeBuilder.buildEmbeddedAttribute( + (EmbeddedAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case MANY_TO_ONE: + case ONE_TO_ONE: { + result.add( + attributeBuilder.buildToOneAttribute( + (SingularAssociationAttribute) attribute, + overrideAndConverterCollector + ) + ); + break; + } + case MANY_TO_MANY: + case ONE_TO_MANY: + case ELEMENT_COLLECTION_BASIC: + case ELEMENT_COLLECTION_EMBEDDABLE: { + throw identifiableTypeMetadata.getLocalBindingContext().makeMappingException( + "Plural attribute cannot be part of identifier : " + attribute.getBackingMember().toString() + ); + } + case ANY: { + throw identifiableTypeMetadata.getLocalBindingContext().makeMappingException( + "Hibernate ANY mapping cannot be part of identifier : " + attribute.getBackingMember().toString() + ); + } + case MANY_TO_ANY: { + throw identifiableTypeMetadata.getLocalBindingContext().makeMappingException( + "Hibernate MANY-TO-ANY mapping cannot be part of identifier : " + attribute.getBackingMember().toString() + ); + } + default: { + throw identifiableTypeMetadata.getLocalBindingContext().makeMappingException( + "Unexpected PersistentAttribute nature encountered : " + attribute.getNature() + ); + } + } + } + } + + public static interface AttributeBuilder { + public SingularAttributeSource buildBasicAttribute( + BasicAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector); + + public EmbeddedAttributeSource buildEmbeddedAttribute( + EmbeddedAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector); + + public ToOneAttributeSource buildToOneAttribute( + SingularAssociationAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector); + + public PluralAttributeSource buildPluralAttribute( + PluralAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector); + + public AttributeSource buildAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector); + + public PluralAttributeSource buildManyToAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector); + } + + + public static class StandardAttributeBuilder implements AttributeBuilder { + /** + * Singleton access + */ + public static final StandardAttributeBuilder INSTANCE = new StandardAttributeBuilder(); + + @Override + public SingularAttributeSource buildBasicAttribute( + BasicAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + return new BasicAttributeSourceImpl( attribute, overrideAndConverterCollector ); + } + + @Override + public EmbeddedAttributeSource buildEmbeddedAttribute( + EmbeddedAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + return new EmbeddedAttributeSourceImpl( attribute, false, false ); + } + + @Override + public ToOneAttributeSource buildToOneAttribute( + SingularAssociationAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + if ( attribute.getMappedByAttributeName() == null ) { + return new ToOneAttributeSourceImpl( attribute, overrideAndConverterCollector ); + } + else { + return new ToOneMappedByAttributeSourceImpl( attribute, overrideAndConverterCollector ); + } + } + + @Override + public PluralAttributeSource buildPluralAttribute( + PluralAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + switch ( attribute.getPluralAttributeNature() ) { + case BAG: + case SET: { + return new PluralAttributeSourceImpl( attribute, overrideAndConverterCollector ); + } + case ID_BAG: { + return new PluralAttributeIdBagSourceImpl( attribute, overrideAndConverterCollector ); + } + case MAP: { + return new PluralAttributeMapSourceImpl( attribute, overrideAndConverterCollector ); + } + case ARRAY: + case LIST: { + return new PluralAttributeIndexedSourceImpl( attribute, overrideAndConverterCollector ); + } + default: { + throw new AssertionFailure( + String.format( + Locale.ENGLISH, + "Unknown or not-yet-supported plural attribute nature: %s", + attribute.getPluralAttributeNature() + ) + ); + } + } + } + + @Override + public AttributeSource buildAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw new NotYetImplementedException(); + } + + @Override + public PluralAttributeSource buildManyToAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw new NotYetImplementedException(); + } + } + + public static class PluralAttributesDisallowedAttributeBuilder extends StandardAttributeBuilder { + /** + * Singleton access + */ + public static final PluralAttributesDisallowedAttributeBuilder INSTANCE = new PluralAttributesDisallowedAttributeBuilder(); + + @Override + public EmbeddedAttributeSource buildEmbeddedAttribute( + EmbeddedAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + return new EmbeddedAttributeSourceImpl( attribute, false, true ); + } + + @Override + public PluralAttributeSource buildPluralAttribute( + PluralAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw attribute.getContext().makeMappingException( + "Plural attributes not allowed in this context : " + attribute.getBackingMember().toString() + ); + } + + @Override + public PluralAttributeSource buildManyToAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw attribute.getContext().makeMappingException( + "Plural attributes not allowed in this context : " + attribute.getBackingMember().toString() + ); + } + } + + public static class IdentifierPathAttributeBuilder extends PluralAttributesDisallowedAttributeBuilder { + /** + * Singleton access + */ + public static final IdentifierPathAttributeBuilder INSTANCE = new IdentifierPathAttributeBuilder(); + + @Override + public PluralAttributeSource buildPluralAttribute( + PluralAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw attribute.getContext().makeMappingException( + "Plural attribute cannot be part of identifier : " + attribute.getBackingMember().toString() + ); + } + + @Override + public PluralAttributeSource buildManyToAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw attribute.getContext().makeMappingException( + "Plural attribute cannot be part of identifier : " + attribute.getBackingMember().toString() + ); + } + + @Override + public AttributeSource buildAnyAttribute( + PersistentAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + throw attribute.getContext().makeMappingException( + "Any mapping cannot be part of identifier : " + attribute.getBackingMember().toString() + ); + } + + @Override + public EmbeddedAttributeSource buildEmbeddedAttribute( + EmbeddedAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + return new EmbeddedAttributeSourceImpl( attribute, true, false ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SubclassEntitySourceImpl.java new file mode 100644 index 000000000000..e9e17a56b078 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/SubclassEntitySourceImpl.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.spi.SubclassEntitySource; + +/** + * @author Hardy Ferentschik + * @author Strong Liu + * @author Steve Ebersole + */ +public class SubclassEntitySourceImpl extends EntitySourceImpl implements SubclassEntitySource { + public SubclassEntitySourceImpl( + EntityTypeMetadata metadata, + EntityHierarchySourceImpl hierarchy, + IdentifiableTypeSourceAdapter superTypeSource) { + super( metadata, hierarchy, superTypeSource ); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TableSourceImpl.java new file mode 100644 index 000000000000..f390fd152bc4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TableSourceImpl.java @@ -0,0 +1,130 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.compare.EqualsHelper; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.TableSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +class TableSourceImpl implements TableSource { + private final String schema; + private final String catalog; + private final String tableName; + private final String rowId; + + static TableSourceImpl build(AnnotationInstance tableAnnotation, EntityBindingContext bindingContext) { + // NOTE : ROWID currently not supported outside case of entity primary table + return build( tableAnnotation, null, bindingContext ); + } + + static TableSourceImpl build(AnnotationInstance tableAnnotation, String rowId, EntityBindingContext bindingContext) { + if ( tableAnnotation == null ) { + return new TableSourceImpl( null, null, null, rowId ); + } + + final ClassLoaderService cls = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + + String explicitTableName = JandexHelper.getValue( + tableAnnotation, + "name", + String.class, + cls + ); + + return new TableSourceImpl( + determineSchemaName( tableAnnotation, cls ), + determineCatalogName( tableAnnotation, cls ), + explicitTableName, + rowId + ); + } + + private static String determineSchemaName(AnnotationInstance tableAnnotation, ClassLoaderService cls) { + return JandexHelper.getValue( tableAnnotation, "schema", String.class, cls ); + } + + private static String determineCatalogName(AnnotationInstance tableAnnotation, ClassLoaderService cls) { + return JandexHelper.getValue( tableAnnotation, "catalog", String.class, cls ); + } + + private TableSourceImpl(String schema, String catalog, String tableName, String rowId) { + this.schema = schema; + this.catalog = catalog; + this.tableName = tableName; + this.rowId = rowId; + } + + @Override + public String getExplicitSchemaName() { + return schema; + } + + @Override + public String getExplicitCatalogName() { + return catalog; + } + + @Override + public String getExplicitTableName() { + return tableName; + } + + @Override + public String getRowId() { + return rowId; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final TableSourceImpl that = ( TableSourceImpl ) o; + return EqualsHelper.equals( this.catalog, that.catalog ) + && EqualsHelper.equals( this.schema, that.schema ) + && EqualsHelper.equals( this.tableName, that.tableName ); + } + + @Override + public int hashCode() { + int result = schema != null ? schema.hashCode() : 0; + result = 31 * result + ( catalog != null ? catalog.hashCode() : 0 ); + result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); + return result; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ToOneAttributeSourceImpl.java new file mode 100644 index 000000000000..b252ed920129 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ToOneAttributeSourceImpl.java @@ -0,0 +1,360 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.internal.binder.ForeignKeyDelegate; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements ToOneAttributeSource { + private final List relationalValueSources; + private final String containingTableName; + private final EntityBindingContext bindingContext; + private final ClassLoaderService cls; + private final ForeignKeyDelegate foreignKeyDelegate; + + public ToOneAttributeSourceImpl( + SingularAssociationAttribute associationAttribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( associationAttribute ); + if ( associationAttribute.getMappedByAttributeName() != null ) { + throw new IllegalArgumentException( "associationAttribute.getMappedByAttributeName() must be null" ); + } + + this.bindingContext = associationAttribute.getContext(); + this.cls = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + + final AssociationOverride override = overrideAndConverterCollector.locateAssociationOverride( + associationAttribute.getPath() + ); + + // Need to initialize relationalValueSources before determining logicalJoinTableName. + this.relationalValueSources = resolveRelationalValueSources( associationAttribute, override ); + + // Need to initialize logicalJoinTableName before determining nature. + this.containingTableName = resolveContainingTableName( associationAttribute, relationalValueSources ); + setSingularAttributeNature( determineNatureIfPossible( associationAttribute ) ); + this.foreignKeyDelegate = new ForeignKeyDelegate( + associationAttribute().getBackingMember().getAnnotations(), cls); + } + + private SingularAttributeNature determineNatureIfPossible( + SingularAssociationAttribute associationAttribute) { + if ( AbstractPersistentAttribute.Nature.MANY_TO_ONE.equals( associationAttribute.getNature() ) ) { + return SingularAttributeNature.MANY_TO_ONE; + } + else if ( AbstractPersistentAttribute.Nature.ONE_TO_ONE.equals( associationAttribute.getNature() ) ) { + if ( getContainingTableName() != null ) { + return SingularAttributeNature.MANY_TO_ONE; + } + else if ( associationAttribute.hasPrimaryKeyJoinColumn() ) { + return SingularAttributeNature.ONE_TO_ONE; + } + else if ( associationAttribute.isId() ) { + // if this association is part of the ID then this can't be a one-to-one + return SingularAttributeNature.MANY_TO_ONE; + } + else if ( associationAttribute.getJoinColumnValues() == null || + associationAttribute.getJoinColumnValues().isEmpty() ) { + return SingularAttributeNature.MANY_TO_ONE; + } + else { + return null; + } + } + else { + throw new AssertionError(String.format( "Wrong attribute nature[%s] for toOne attribute: %s", + associationAttribute.getNature(), associationAttribute.getRole() )); + } + } + + @Override + public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { + if ( getSingularAttributeNature() != null ) { + return; + } + // It would be nice to have the following block in determineNatureIfPossible(), + // but it requires context.resolveIdentifierColumns(), it's here instead. + if ( AbstractPersistentAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) { + final List idColumns = context.resolveIdentifierColumns(); + if ( associationAttribute().getJoinColumnValues().size() != idColumns.size() ) { + setSingularAttributeNature( SingularAttributeNature.MANY_TO_ONE ); + } + else { + Set joinColumnNames = new HashSet( associationAttribute().getJoinColumnValues().size() ); + for ( Column joinColumn : associationAttribute().getJoinColumnValues() ) { + joinColumnNames.add( joinColumn.getName() ); + } + // if join columns are the entity's ID, then it is a one-to-one (mapToPk == true) + boolean areJoinColumnsSameAsIdColumns = true; + for ( org.hibernate.metamodel.spi.relational.Column idColumn : idColumns ) { + if ( ! joinColumnNames.contains( idColumn.getColumnName().getText() ) ) { + areJoinColumnsSameAsIdColumns = false; + break; + } + } + setSingularAttributeNature( + areJoinColumnsSameAsIdColumns ? + SingularAttributeNature.ONE_TO_ONE : + SingularAttributeNature.MANY_TO_ONE + ); + } + } + if ( getSingularAttributeNature() == null ) { + throw new NotYetImplementedException( "unknown type of to-one attribute." ); + } + } + + @Override + public List getDefaultNamingStrategies( + final String entityName, + final String tableName, + final AttributeBinding referencedAttributeBinding) { + if ( EmbeddedAttributeBinding.class.isInstance( referencedAttributeBinding ) ) { + EmbeddedAttributeBinding embeddedAttributeBinding = EmbeddedAttributeBinding.class.cast( + referencedAttributeBinding + ); + List result = new ArrayList( ); + for ( final AttributeBinding attributeBinding : embeddedAttributeBinding.getEmbeddableBinding().attributeBindings() ) { + result.addAll( getDefaultNamingStrategies( entityName, tableName, attributeBinding ) ); + } + return result; + } + else { + List result = new ArrayList( 1 ); + result.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.foreignKeyColumnName( + associationAttribute().getName(), + entityName, + tableName, + referencedAttributeBinding.getAttribute().getName() + ); + } + } + ); + return result; + } + } + + @Override + public List relationalValueSources() { + return relationalValueSources; + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + private List resolveRelationalValueSources( + SingularAssociationAttribute attribute, + AssociationOverride override) { + // todo : utilize the override + final List joinColumns; + if ( attribute.getJoinTableAnnotation() == null ) { + joinColumns = attribute.getJoinColumnValues(); + } + else { + joinColumns = attribute.getInverseJoinColumnValues(); + } + + if ( joinColumns.isEmpty() ) { + return Collections.emptyList(); + } + + final List valueSources = new ArrayList( joinColumns.size() ); + for ( Column joinColumn : joinColumns ) { + valueSources.add( + new ColumnSourceImpl( + attribute, + joinColumn, + getDefaultLogicalJoinTableName( attribute ) + ) + ); + } + return valueSources; + } + + private String getDefaultLogicalJoinTableName(SingularAssociationAttribute attribute) { + if ( attribute.getJoinTableAnnotation() == null ) { + return null; + } + return JandexHelper.getValue( attribute.getJoinTableAnnotation(), "name", String.class, cls ); + } + + + private String resolveContainingTableName( + SingularAssociationAttribute attribute, + List relationalValueSources) { + if ( relationalValueSources.isEmpty() ) { + return getDefaultLogicalJoinTableName( attribute ); + } + String logicalTableName = relationalValueSources.get( 0 ).getContainingTableName(); + for ( int i = 1; i< relationalValueSources.size(); i++ ) { + if ( logicalTableName == null ) { + if ( relationalValueSources.get( i ).getContainingTableName() != null ) { + throw new IllegalStateException( "Relational value sources refer to null and non-null containing tables." ); + } + } + else if ( !logicalTableName.equals( relationalValueSources.get( i ).getContainingTableName() ) ) { + throw new IllegalStateException( "Relational value sources do not refer to the same containing table." ); + } + } + return logicalTableName; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + List joinColumns = + associationAttribute().getJoinTableAnnotation() == null ? + associationAttribute().getJoinColumnValues() : + associationAttribute().getInverseJoinColumnValues(); + boolean hasReferencedColumn = false; + for ( Column joinColumn : joinColumns ) { + if ( joinColumn.getReferencedColumnName() != null ) { + hasReferencedColumn = true; + break; + } + } + return hasReferencedColumn ? new AnnotationJoinColumnResolutionDelegate() : null; + } + + @Override + public String getExplicitForeignKeyName() { + return foreignKeyDelegate.getExplicitForeignKeyName(); + } + + @Override + public boolean createForeignKeyConstraint() { + return foreignKeyDelegate.createForeignKeyConstraint(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public AttributePath getAttributePath() { + return getAnnotatedAttribute().getPath(); + } + + @Override + public AttributeRole getAttributeRole() { + return getAnnotatedAttribute().getRole(); + } + + public class AnnotationJoinColumnResolutionDelegate + implements ForeignKeyContributingSource.JoinColumnResolutionDelegate { + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + final List values = new ArrayList(); + final List joinColumns = + associationAttribute().getJoinTableAnnotation() == null ? + associationAttribute().getJoinColumnValues() : + associationAttribute().getInverseJoinColumnValues(); + for ( Column joinColumn : joinColumns ) { + if ( joinColumn.getReferencedColumnName() == null ) { + return context.resolveRelationalValuesForAttribute( null ); + } + org.hibernate.metamodel.spi.relational.Column resolvedColumn = context.resolveColumn( + joinColumn.getReferencedColumnName(), + null, + null, + null + ); + values.add( resolvedColumn ); + } + return values; + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( + null, + null, + null + ); + } + + @Override + public String getReferencedAttributeName() { + // in annotations we are not referencing attribute but column names via @JoinColumn(s) + return null; + } + + private String resolveLogicalJoinTableName() { + final AnnotationInstance joinTableAnnotation = associationAttribute().getBackingMember() + .getAnnotations() + .get( JPADotNames.JOIN_TABLE ); + + if ( joinTableAnnotation != null ) { + return JandexHelper.getValue( joinTableAnnotation, "name", String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) ); + } + + // todo : this ties into the discussion about naming strategies. This would be part of a logical naming strategy... + return null; + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ToOneMappedByAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ToOneMappedByAttributeSourceImpl.java new file mode 100644 index 000000000000..e0d07dc324ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/ToOneMappedByAttributeSourceImpl.java @@ -0,0 +1,143 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * @author Gail Badner + */ +public class ToOneMappedByAttributeSourceImpl + extends AbstractToOneAttributeSourceImpl + implements MappedByAssociationSource { + private ToOneAttributeSource owner; + + public ToOneMappedByAttributeSourceImpl( + SingularAssociationAttribute associationAttribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( associationAttribute); + if ( associationAttribute.getMappedByAttributeName() == null ) { + throw new IllegalArgumentException( "associationAttribute.getMappedByAttributeName() must be non-null" ); + } + + final AssociationOverride override = overrideAndConverterCollector.locateAssociationOverride( + associationAttribute.getPath() + ); + if ( override != null ) { + // todo : do what... exception? warn? + } + } + + @Override + public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { + if ( getSingularAttributeNature() != null && owner != null) { + return; + } + if ( owner == null ) { + owner = (ToOneAttributeSource) context.resolveAttributeSource( + associationAttribute().getTargetTypeName(), + associationAttribute().getMappedByAttributeName() + ); + owner.addMappedByAssociationSource( this ); + } + if ( getSingularAttributeNature() == null ) { + final SingularAttributeNature singularAttributeNature; + if ( AbstractPersistentAttribute.Nature.MANY_TO_ONE.equals( associationAttribute().getNature() ) ) { + singularAttributeNature = SingularAttributeNature.MANY_TO_ONE; + } + else if ( AbstractPersistentAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) { + if ( owner.getContainingTableName() != null ) { + singularAttributeNature = SingularAttributeNature.MANY_TO_ONE; + } + else { + singularAttributeNature = SingularAttributeNature.ONE_TO_ONE; + } + } + else { + throw new AssertionError(String.format( + "Wrong attribute nature[%s] for toOne attribute: %s", + associationAttribute().getNature(), associationAttribute().getRole() + )); + } + setSingularAttributeNature( singularAttributeNature ); + } + } + + @Override + public boolean isMappedBy() { + return true; + } + + @Override + public String getMappedBy() { + return associationAttribute().getMappedByAttributeName(); + } + + @Override + public List relationalValueSources() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public String getContainingTableName() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public String getExplicitForeignKeyName() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public boolean createForeignKeyConstraint() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } + + @Override + public List getDefaultNamingStrategies(String entityName, String tableName, AttributeBinding referencedAttributeBinding) { + throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TypeDescriptorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TypeDescriptorSourceImpl.java new file mode 100644 index 000000000000..132b53420057 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TypeDescriptorSourceImpl.java @@ -0,0 +1,117 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.AnnotationException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class TypeDescriptorSourceImpl implements TypeDescriptorSource { + private final String name; + private final String implementationClassName; + private final String[] registrationKeys; + private final AnnotationBindingContext bindingContext; + + private Map parameterValueMap; + + public TypeDescriptorSourceImpl(AnnotationInstance typeDefAnnotation, AnnotationBindingContext bindingContext) { + this.bindingContext = bindingContext; + this.name = JandexHelper.getValue( + typeDefAnnotation, "name", String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) + ); + this.implementationClassName = JandexHelper.getValue( typeDefAnnotation, "typeClass", String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) ); + + String defaultForType = JandexHelper.getValue( typeDefAnnotation, "defaultForType", String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) ); + if ( defaultForType != null ) { + if ( void.class.getName().equals( defaultForType ) ) { + defaultForType = null; + } + } + String registrationKey = defaultForType; + + if ( StringHelper.isEmpty( name ) && registrationKey == null ) { + throw new AnnotationException( + String.format( + "Either name or defaultForType (or both) must be set on TypeDefinition [%s]", + implementationClassName + ) + ); + } + + this.registrationKeys = registrationKey == null ? new String[0] : new String[] { registrationKey }; + this.parameterValueMap = extractParameterValues( typeDefAnnotation ); + } + + private Map extractParameterValues(AnnotationInstance typeDefAnnotation) { + Map parameterMaps = new HashMap(); + AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( + typeDefAnnotation, + "parameters", + AnnotationInstance[].class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + parameterMaps.put( + JandexHelper.getValue( parameterAnnotation, "name", String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) ), + JandexHelper.getValue( parameterAnnotation, "value", String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + return parameterMaps; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getTypeImplementationClassName() { + return implementationClassName; + } + + @Override + public String[] getRegistrationKeys() { + return registrationKeys; + } + + @Override + public Map getParameters() { + return parameterValueMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TypedValueExtractor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TypedValueExtractor.java new file mode 100644 index 000000000000..1e49d13d77eb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/TypedValueExtractor.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.jboss.jandex.AnnotationInstance; + +/** + * A contract for extracting values from Jandex representation of an + * annotation. + * + * @author Steve Ebersole + */ +public interface TypedValueExtractor { + /** + * Extracts the value by type from the given annotation attribute value + * representation. The attribute value may be {@code null} (which + * represents an unspecified attribute), in which case we need reference + * to the {@link org.hibernate.boot.registry.classloading.spi.ClassLoaderService} + * to be able to resolve the default value for the given attribute. + * + * @param annotationInstance The representation of the annotation usage + * from which to extract an attribute value. + * @param name The name of the attribute to extract + * + * @return The extracted value. + */ + public T extract(AnnotationInstance annotationInstance, String name); + + /** + * Just like {@link #extract(org.jboss.jandex.AnnotationInstance,String)} + * except that here we return the passed defaultValue if the annotation + * attribute value is {@code null}. + * + * @param annotationInstance The representation of the annotation usage + * from which to extract an attribute value. + * @param name The name of the attribute to extract + * @param defaultValue The typed value to use if the annotation + * attribute value is {@code null} + * + * @return The extracted value. + */ + public T extract(AnnotationInstance annotationInstance, String name, T defaultValue); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/UniqueConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/UniqueConstraintSourceImpl.java new file mode 100644 index 000000000000..1aacdd66edb8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/UniqueConstraintSourceImpl.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.source.spi.UniqueConstraintSource; + +/** + * @author Hardy Ferentschik + */ +class UniqueConstraintSourceImpl extends AbstractConstraintSource implements UniqueConstraintSource { + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames, List orderings) { + super( name, tableName, columnNames, orderings ); + } + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames) { + super( name, tableName, columnNames, Collections.EMPTY_LIST ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "UniqueConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/VersionAttributeSourceImpl.java new file mode 100644 index 000000000000..27f5e8ac3734 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/VersionAttributeSourceImpl.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations; + +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.spi.VersionAttributeSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * @author Steve Ebersole + */ +public class VersionAttributeSourceImpl + extends BasicAttributeSourceImpl + implements VersionAttributeSource { + + public VersionAttributeSourceImpl( + BasicAttribute attribute, + OverrideAndConverterCollector overrideAndConverterCollector) { + super( attribute, overrideAndConverterCollector ); + } + + @Override + public String getUnsavedValue() { + return null; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return NaturalIdMutability.NOT_NATURAL_ID; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractOverrideDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractOverrideDefinition.java new file mode 100644 index 000000000000..1eafac7cbcf6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractOverrideDefinition.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.AssertionFailure; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.compare.EqualsHelper; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class AbstractOverrideDefinition { + + protected static final String PROPERTY_PATH_SEPARATOR = "."; + protected final String attributePath; + protected final EntityBindingContext bindingContext; + + private boolean isApplied; + + public AbstractOverrideDefinition(String prefix, AnnotationInstance attributeOverrideAnnotation, + EntityBindingContext bindingContext) { + if ( attributeOverrideAnnotation == null ) { + throw new IllegalArgumentException( "AnnotationInstance passed cannot be null" ); + } + + if ( !getTargetAnnotation().equals( attributeOverrideAnnotation.name() ) ) { + throw new AssertionFailure( "Unexpected annotation passed to the constructor" ); + } + + this.attributePath = createAttributePath( + prefix, + JandexHelper.getValue( + attributeOverrideAnnotation, + "name", + String.class, + bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ) + ) + ); + this.bindingContext = bindingContext; + } + + protected static String createAttributePath(String prefix, String name) { + if ( StringHelper.isEmpty( name ) ) { + throw new AssertionFailure( "name attribute in @AttributeOverride can't be empty" ); + } + String path = ""; + if ( StringHelper.isNotEmpty( prefix ) ) { + path += prefix; + } + if ( StringHelper.isNotEmpty( path ) && !path.endsWith( PROPERTY_PATH_SEPARATOR ) ) { + path += PROPERTY_PATH_SEPARATOR; + } + path += name; + return path; + } + + public String getAttributePath(){ + return attributePath; + } + + public abstract void apply(AbstractPersistentAttribute persistentAttribute); + + protected abstract DotName getTargetAnnotation(); + + public boolean isApplied() { + return isApplied; + } + + public void setApplied(boolean applied) { + isApplied = applied; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof AbstractOverrideDefinition ) ) { + return false; + } + + AbstractOverrideDefinition that = (AbstractOverrideDefinition) o; + return EqualsHelper.equals( this.attributePath, that.attributePath ); + } + + @Override + public int hashCode() { + return attributePath != null ? attributePath.hashCode() : 0; + } + + @Override + public String toString() { + return "AbstractOverrideDefinition{attributePath='" + attributePath + "'}"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractPersistentAttribute.java new file mode 100644 index 000000000000..d63fa8adde39 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractPersistentAttribute.java @@ -0,0 +1,403 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.logging.Logger; + +/** + * Base class for the different types of persistent attributes + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public abstract class AbstractPersistentAttribute implements PersistentAttribute { + private static final Logger log = Logger.getLogger( AbstractPersistentAttribute.class ); + + private final ManagedTypeMetadata container; + private final String attributeName; + private final AttributePath attributePath; + private final AttributeRole attributeRole; + private final MemberDescriptor backingMember; + private final Nature nature; + private final AccessType accessType; + private final String accessorStrategy; + + private final boolean includeInOptimisticLocking; + + private final boolean isId; + private final boolean isVersioned; + private final NaturalIdMutability naturalIdMutability; + + private final List columnValues; + private final FormulaValue formulaValue; + + private final String checkCondition; + + protected AbstractPersistentAttribute( + ManagedTypeMetadata container, + String attributeName, + AttributePath attributePath, + AttributeRole attributeRole, + MemberDescriptor backingMember, + Nature nature, + AccessType accessType, + String accessorStrategy) { + this.container = container; + this.attributeName = attributeName; + this.attributePath = attributePath; + this.attributeRole = attributeRole; + this.backingMember = backingMember; + this.accessType = accessType; + this.accessorStrategy = accessorStrategy; + + this.isId = determineWhetherIsId( backingMember ); + this.isVersioned = determineWhetherIsVersion( backingMember ); + this.naturalIdMutability = determineNaturalIdMutability( container, backingMember ); + + // todo : could we just get rid of EMBEDDED_ID as an attribute nature? + // Nature.EMBEDDED + isId already covers this case... + if ( nature == Nature.EMBEDDED ) { + this.nature = isId ? Nature.EMBEDDED_ID : Nature.EMBEDDED; + } + else { + this.nature = nature; + } + + this.includeInOptimisticLocking = determineInclusionInOptimisticLocking( backingMember ); + + this.columnValues = extractColumnValues( backingMember ); + this.formulaValue = extractFormulaValue( backingMember ); + + validateColumnsAndFormulas( columnValues, formulaValue ); + + this.checkCondition = extractCheckCondition( backingMember ); + } + + private boolean determineInclusionInOptimisticLocking(MemberDescriptor backingMember) { + // NOTE : default is `true`, the annotation is used to opt out of inclusion + + final AnnotationInstance optimisticLockAnnotation = backingMember.getAnnotations().get( + HibernateDotNames.OPTIMISTIC_LOCK + ); + if ( optimisticLockAnnotation == null ) { + return true; + } + + final boolean excludedFromLocking = optimisticLockAnnotation.value( "excluded" ).asBoolean(); + if ( excludedFromLocking ) { + if ( isId() || isVersion() ) { + throw getContext().makeMappingException( + "@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version : " + + backingMember.toString() + ); + } + } + return !excludedFromLocking; + } + + protected final boolean hasOptimisticLockAnnotation() { + return getBackingMember().getAnnotations().get( HibernateDotNames.OPTIMISTIC_LOCK ) != null; + } + + private String extractCheckCondition(MemberDescriptor backingMember) { + final AnnotationInstance checkAnnotation = backingMember.getAnnotations().get( HibernateDotNames.CHECK ); + if ( checkAnnotation == null ) { + return null; + } + + final AnnotationValue constraintsValue = checkAnnotation.value( "constraints" ); + if ( constraintsValue == null ) { + return null; + } + + final String constraintsString = constraintsValue.asString(); + if ( StringHelper.isEmpty( constraintsString ) ) { + return null; + } + + return constraintsString; + } + + @SuppressWarnings("RedundantIfStatement") + protected boolean determineWhetherIsId(MemberDescriptor backingMember) { + // if this attribute has either @Id or @EmbeddedId, then it is an id attribute + final AnnotationInstance idAnnotation = backingMember.getAnnotations().get( JPADotNames.ID ); + if ( idAnnotation != null ) { + validatePresenceOfIdAnnotation(); + if ( backingMember.getType().getErasedType().findTypeAnnotation( JPADotNames.EMBEDDABLE ) != null ) { + log.warn( + "Attribute was annotated with @Id, but attribute type was annotated as @Embeddable; " + + "did you mean to use @EmbeddedId on the attribute rather than @Id?" + ); + } + return true; + } + + final AnnotationInstance embeddedIdAnnotation = backingMember.getAnnotations().get( JPADotNames.EMBEDDED_ID ); + if ( embeddedIdAnnotation != null ) { + validatePresenceOfEmbeddedIdAnnotation(); + return true; + } + + return false; + } + + protected void validatePresenceOfIdAnnotation() { +// throw container.getLocalBindingContext().makeMappingException( +// "Unexpected presence of @Id annotation : " + backingMember.toLoggableForm() +// ); + } + + protected void validatePresenceOfEmbeddedIdAnnotation() { +// throw container.getLocalBindingContext().makeMappingException( +// "Unexpected presence of @EmbeddedId annotation : " + backingMember.toLoggableForm() +// ); + } + + protected boolean determineWhetherIsVersion(MemberDescriptor backingMember) { + final AnnotationInstance versionAnnotation = backingMember.getAnnotations().get( JPADotNames.VERSION ); + if ( versionAnnotation != null ) { + validatePresenceOfVersionAnnotation(); + return true; + } + + return false; + } + + protected void validatePresenceOfVersionAnnotation() { + throw container.getLocalBindingContext().makeMappingException( + "Unexpected presence of @Version annotation : " + backingMember.toString() + ); + } + + protected NaturalIdMutability determineNaturalIdMutability( + ManagedTypeMetadata container, + MemberDescriptor backingMember) { + final NaturalIdMutability result = AnnotationParserHelper.determineNaturalIdMutability( container, backingMember ); + if ( result != NaturalIdMutability.NOT_NATURAL_ID ) { + validatePresenceOfNaturalIdAnnotation(); + } + return result; + } + + protected void validatePresenceOfNaturalIdAnnotation() { +// throw container.getLocalBindingContext().makeMappingException( +// "Unexpected presence of @NaturalId annotation : " + backingMember.toString() +// ); + } + + private List extractColumnValues(MemberDescriptor backingMember) { + // @javax.persistence.Column + final AnnotationInstance columnAnnotation = backingMember.getAnnotations().get( JPADotNames.COLUMN ); + // @org.hibernate.annotations.Columns + final AnnotationInstance columnsAnnotation = backingMember.getAnnotations().get( HibernateDotNames.COLUMNS ); + + if ( columnAnnotation != null && columnsAnnotation != null ) { + throw getContext().makeMappingException( + "Should not mix @Column and @Columns annotations on same attribute : " + + backingMember.toString() + ); + } + + if ( columnAnnotation == null && columnsAnnotation == null ) { + // try to avoid unnecessary List creation + return Collections.emptyList(); + } + + final List columns = new ArrayList(); + if ( columnAnnotation != null ) { + validatePresenceOfColumnAnnotation(); + columns.add( new Column( columnAnnotation ) ); + } + else { + validatePresenceOfColumnsAnnotation(); + final AnnotationInstance[] columnAnnotations = JandexHelper.getValue( + columnsAnnotation, + "columns", + AnnotationInstance[].class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance annotation : columnAnnotations ) { + columns.add( new Column( annotation ) ); + } + } + return columns; + } + + protected void validatePresenceOfColumnAnnotation() { +// throw container.getLocalBindingContext().makeMappingException( +// "Unexpected presence of @Column annotation : " + backingMember.toString() +// ); + } + + protected void validatePresenceOfColumnsAnnotation() { +// throw container.getLocalBindingContext().makeMappingException( +// "Unexpected presence of @Columns annotation : " + backingMember.toString() +// ); + } + + private FormulaValue extractFormulaValue(MemberDescriptor backingMember) { + final AnnotationInstance formulaAnnotation = backingMember.getAnnotations().get( HibernateDotNames.FORMULA ); + if ( formulaAnnotation == null ) { + return null; + } + + final String expression = formulaAnnotation.value().asString(); + if ( StringHelper.isEmpty( expression ) ) { + throw getContext().makeMappingException( "Formula expression cannot be empty string" ); + } + + return new FormulaValue( null, expression ); + } + + private void validateColumnsAndFormulas(List columnValues, FormulaValue formulaValue) { + if ( !columnValues.isEmpty() && formulaValue != null ) { + throw getContext().makeMappingException( + "Should not mix @Formula and @Column/@Columns annotations : " + backingMember.toString() + ); + } + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // relevant to all attributes + + @Override + public String getName() { + return attributeName; + } + + @Override + public Nature getNature() { + return nature; + } + + @Override + public ManagedTypeMetadata getContainer() { + return container; + } + + @Override + public MemberDescriptor getBackingMember() { + return backingMember; + } + + @Override + public AttributeRole getRole(){ + return attributeRole; + } + + @Override + public AttributePath getPath() { + return attributePath; + } + + @Override + public AccessType getAccessType() { + return accessType; + } + + @Override + public String getAccessorStrategy() { + return accessorStrategy; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // relevant to singular attributes + + public boolean isId() { + return isId; + } + + public boolean isVersion() { + return isVersioned; + } + + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + public FormulaValue getFormulaValue() { + return formulaValue; + } + + public List getColumnValues() { + return columnValues; + } + + public EntityBindingContext getContext() { + return container.getLocalBindingContext(); + } + + @Override + public boolean isIncludeInOptimisticLocking() { + return includeInOptimisticLocking; + } + + public String getCheckCondition() { + return checkCondition; + } + + @Override + public int compareTo(PersistentAttribute mappedProperty) { + return attributeName.compareTo( mappedProperty.getName() ); + } + + @Override + public String toString() { + return "PersistentAttribute{attributeName='" + attributeName + '\'' + '}'; + } + + public abstract boolean isOptional(); + + public abstract boolean isInsertable(); + + public abstract boolean isUpdatable(); + + public abstract PropertyGeneration getPropertyGeneration(); + +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractPluralAttributeIndexDetailsMapKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractPluralAttributeIndexDetailsMapKey.java new file mode 100644 index 000000000000..05fca5c5bbcc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractPluralAttributeIndexDetailsMapKey.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolverComposition; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.EnumeratedTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.TemporalTypeResolver; + + +/** + * PluralAttributeIndexDetails implementation for describing the key of a Map + * + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeIndexDetailsMapKey implements PluralAttributeIndexDetails { + private final PluralAttribute pluralAttribute; + private final JavaTypeDescriptor resolvedMapKeyType; + private final AttributeTypeResolver typeResolver; + + public AbstractPluralAttributeIndexDetailsMapKey( + PluralAttribute pluralAttribute, + MemberDescriptor backingMember, + JavaTypeDescriptor resolvedMapKeyType) { + this.pluralAttribute = pluralAttribute; + this.resolvedMapKeyType = resolvedMapKeyType; + + this.typeResolver = new AttributeTypeResolverComposition( + resolvedMapKeyType, + pluralAttribute.getContext(), + HibernateTypeResolver.createCollectionIndexTypeResolver( pluralAttribute, resolvedMapKeyType ), + EnumeratedTypeResolver.createCollectionIndexTypeResolver( pluralAttribute, resolvedMapKeyType ), + TemporalTypeResolver.createCollectionIndexTypeResolver( pluralAttribute, resolvedMapKeyType ) + ); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return resolvedMapKeyType; + } + + @Override + public AttributeTypeResolver getTypeResolver() { + return typeResolver; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractSingularAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractSingularAttribute.java new file mode 100644 index 000000000000..900711574ef6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AbstractSingularAttribute.java @@ -0,0 +1,183 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import javax.persistence.AccessType; + +import org.hibernate.AnnotationException; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.ConverterAndOverridesHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +import org.jboss.logging.Logger; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractSingularAttribute + extends AbstractPersistentAttribute + implements SingularAttribute { + private static final Logger log = Logger.getLogger( AbstractSingularAttribute.class ); + + protected AbstractSingularAttribute( + ManagedTypeMetadata container, + String attributeName, + AttributePath attributePath, + AttributeRole attributeRole, + MemberDescriptor backingMember, + Nature nature, + AccessType accessType, + String accessorStrategy) { + super( container, attributeName, attributePath, attributeRole, backingMember, nature, accessType, accessorStrategy ); + + if ( backingMember.getAnnotations().containsKey( HibernateDotNames.IMMUTABLE ) ) { + throw new AnnotationException( "@Immutable can be used on entities or collections, not " + + attributeRole.getFullPath() ); + } + + ConverterAndOverridesHelper.INSTANCE.processConverters( + getPath(), + getNature(), + backingMember, + container, + getContext() + ); + ConverterAndOverridesHelper.INSTANCE.processAttributeOverrides( + getPath(), + backingMember, + container, + getContext() + ); + ConverterAndOverridesHelper.INSTANCE.processAssociationOverrides( + getPath(), + backingMember, + container, + getContext() + ); + } + + protected AttributeConversionInfo validateConversionInfo(AttributeConversionInfo conversionInfo) { + // NOTE we cant really throw exceptions here atm because we do not know if + // the converter was explicitly requested or if an auto-apply converter + // was returned. So we simply log a warning and circumvent the conversion + + // todo : regarding ^^, on second thought its likely better if this scaffolding just support locally defined converters + // then it is ok to throw then exceptions + // the idea being that binder would apply auto apply converters if needed + + // disabled is always allowed + if ( !conversionInfo.isConversionEnabled() ) { + return conversionInfo; + } + + // otherwise use of the converter is ok, as long as... + // 1) the attribute is not an id + if ( isId() ) { + log.warnf( + "AttributeConverter [%s] cannot be applied to given attribute [%s] as it is an Id (section 3.8)", + conversionInfo.getConverterTypeDescriptor().getName(), + getBackingMember().toString() + ); + return null; + } + + // 2) the attribute is not a version + if ( isVersion() ) { + log.warnf( + "AttributeConverter [%s] cannot be applied to given attribute [%s] as it is a Version (section 3.8)", + conversionInfo.getConverterTypeDescriptor().getName(), + getBackingMember().toString() + ); + return null; + } + + // 3) the attribute is not an association + if ( getNature() == Nature.MANY_TO_ONE || getNature() == Nature.ONE_TO_ONE ) { + log.warnf( + "AttributeConverter [%s] cannot be applied to given attribute [%s] as it is an association (section 3.8)", + conversionInfo.getConverterTypeDescriptor().getName(), + getBackingMember().toString() + ); + return null; + } + + // 4) the attribute is not an embedded + if ( getNature() == Nature.EMBEDDED || getNature() == Nature.EMBEDDED_ID ) { + log.warnf( + "AttributeConverter [%s] cannot be applied to given attribute [%s] as it is an Embeddable (section 3.8)", + conversionInfo.getConverterTypeDescriptor().getName(), + getBackingMember().toString() + ); + return null; + } + + // 5) the attribute cannot have explicit "conversion" annotations such as + // @Temporal or @Enumerated + if ( getBackingMember().getAnnotations().containsKey( JPADotNames.TEMPORAL ) ) { + log.warnf( + "AttributeConverter [%s] cannot be applied to given attribute [%s] as it is annotated @Temporal (section 3.8)", + conversionInfo.getConverterTypeDescriptor().getName(), + getBackingMember().toString() + ); + return null; + } + if ( getBackingMember().getAnnotations().containsKey( JPADotNames.ENUMERATED ) ) { + log.warnf( + "AttributeConverter [%s] cannot be applied to given attribute [%s] as it is annotated @Enumerated (section 3.8)", + conversionInfo.getConverterTypeDescriptor().getName(), + getBackingMember().toString() + ); + return null; + } + + + return conversionInfo; + } + + @Override + public AttributeConversionInfo getConversionInfo() { + return getContainer().locateConversionInfo( getPath() ); + } + + @Override + public boolean isId() { + return super.isId(); + } + + @Override + public boolean isVersion() { + return super.isVersion(); + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return super.getNaturalIdMutability(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AssociationAttribute.java new file mode 100644 index 000000000000..05b6bf3f46a5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AssociationAttribute.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.Set; +import javax.persistence.CascadeType; + +/** + * @author Steve Ebersole + */ +public interface AssociationAttribute { + public String getMappedByAttributeName(); + + public Set getJpaCascadeTypes(); + public Set getHibernateCascadeTypes(); + public boolean isOrphanRemoval(); + + public boolean isOptional(); + public boolean isIgnoreNotFound(); + public boolean isUnWrapProxy(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AssociationOverride.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AssociationOverride.java new file mode 100644 index 000000000000..b3ab9487cf67 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AssociationOverride.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public class AssociationOverride extends AbstractOverrideDefinition { + + public AssociationOverride(String prefix, AnnotationInstance attributeOverrideAnnotation, + EntityBindingContext bindingContext) { + super( prefix, attributeOverrideAnnotation, bindingContext ); + } + + @Override + protected DotName getTargetAnnotation() { + return JPADotNames.ASSOCIATION_OVERRIDE; + } + + + @Override + public void apply(AbstractPersistentAttribute persistentAttribute) { + } + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AttributeOverride.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AttributeOverride.java new file mode 100644 index 000000000000..de68d6d2fc21 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/AttributeOverride.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * Contains the information about a single {@link javax.persistence.AttributeOverride}. Instances of this class + * are creating during annotation processing and then applied onto the persistence attributes. + * + * @author Hardy Ferentschik + * @todo Take care of prefixes of the form 'element', 'key' and 'value'. Add another type enum to handle this. (HF) + */ +public class AttributeOverride extends AbstractOverrideDefinition{ + private final Column column; + private final AnnotationInstance columnAnnotation; + + public AttributeOverride( + String prefix, + AnnotationInstance attributeOverrideAnnotation, + EntityBindingContext bindingContext) { + super( prefix, attributeOverrideAnnotation, bindingContext ); + + this.columnAnnotation = JandexHelper.getValue( + attributeOverrideAnnotation, + "column", + AnnotationInstance.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + this.column = new Column( columnAnnotation ); + } + + @Override + protected DotName getTargetAnnotation() { + return JPADotNames.ATTRIBUTE_OVERRIDE; + } + + public Column getImpliedColumn() { + return column; + } + + public AnnotationInstance getOverriddenColumnInfo() { + return columnAnnotation; + } + + @Override + public void apply(AbstractPersistentAttribute persistentAttribute) { + int columnSize = persistentAttribute.getColumnValues().size(); + switch ( columnSize ){ + case 0: + persistentAttribute.getColumnValues().add( column ); + break; + case 1: + persistentAttribute.getColumnValues().get( 0 ).applyColumnValues( columnAnnotation ); + break; + default: + //TODO throw exception?? + } + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof AttributeOverride ) ) { + return false; + } + if ( !super.equals( o ) ) { + return false; + } + + AttributeOverride that = (AttributeOverride) o; + + if ( column != null ? !column.equals( that.column ) : that.column != null ) { + return false; + } + if ( columnAnnotation != null ? !columnAnnotation.equals( that.columnAnnotation ) : that.columnAnnotation != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + ( column != null ? column.hashCode() : 0 ); + result = 31 * result + ( columnAnnotation != null ? columnAnnotation.hashCode() : 0 ); + return result; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/BasicAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/BasicAttribute.java new file mode 100644 index 000000000000..5e7d786e2940 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/BasicAttribute.java @@ -0,0 +1,390 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.persistence.AccessType; +import javax.persistence.FetchType; +import javax.persistence.GenerationType; + +import org.hibernate.AnnotationException; +import org.hibernate.annotations.GenerationTime; +import org.hibernate.annotations.SourceType; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolverComposition; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.EnumeratedTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.LobTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.TemporalTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * Represents a singular persistent attribute that is non-composite and non-association. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class BasicAttribute extends AbstractSingularAttribute { + private final SourceType versionSourceType; + private final IdentifierGeneratorDefinition identifierGeneratorDefinition; + + private boolean isLazy; + private boolean isOptional; + + private final PropertyGeneration propertyGeneration; + private final ColumnInclusion insertability; + private final ColumnInclusion updateability; + + private final String customWriteFragment; + private final String customReadFragment; + + private AttributeTypeResolver resolver; + + public BasicAttribute( + ManagedTypeMetadata container, + String attributeName, + AttributePath attributePath, + AttributeRole attributeRole, + MemberDescriptor backingMember, + AccessType accessType, + String accessStrategy) { + super( + container, + attributeName, + attributePath, + attributeRole, + backingMember, + Nature.BASIC, + accessType, + accessStrategy + ); + + this.insertability = new ColumnInclusion( container.canAttributesBeInsertable() ); + this.updateability = new ColumnInclusion( container.canAttributesBeUpdatable() ); + + // a basic attribute can be a version attribute + this.versionSourceType = isVersion() ? extractVersionSourceType( backingMember ) : null; + + if ( isId() ) { + // an id must be unique and cannot be nullable + for ( Column columnValue : getColumnValues() ) { + columnValue.setNullable( false ); + } + updateability.disable(); + identifierGeneratorDefinition = extractIdentifierGeneratorDefinition( backingMember ); + } + else { + identifierGeneratorDefinition = null; + } + + // @Basic + final AnnotationInstance basicAnnotation = backingMember.getAnnotations().get( JPADotNames.BASIC ); + if ( basicAnnotation == null ) { + isLazy = false; + isOptional = true; + } + else { + FetchType fetchType = FetchType.EAGER; + final AnnotationValue fetchValue = basicAnnotation.value( "fetch" ); + if ( fetchValue != null ) { + fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() ); + } + this.isLazy = fetchType == FetchType.LAZY; + + boolean optional = true; + final AnnotationValue optionalValue = basicAnnotation.value( "optional" ); + if ( optionalValue != null ) { + optional = optionalValue.asBoolean(); + } + this.isOptional = optional; + } + + // @Generated + // todo : hook in the new generation stuff + final AnnotationInstance generatedAnnotation = backingMember.getAnnotations().get( HibernateDotNames.GENERATED ); + if ( generatedAnnotation == null ) { + if ( isId() ) { + this.updateability.disable(); + this.propertyGeneration = PropertyGeneration.INSERT; + } + else { + this.propertyGeneration = PropertyGeneration.ALWAYS; + } + } + else { + this.insertability.disable(); + + PropertyGeneration propertyGeneration = PropertyGeneration.ALWAYS; + AnnotationValue generationTimeValue = generatedAnnotation.value(); + if ( generationTimeValue != null ) { + GenerationTime genTime = Enum.valueOf( GenerationTime.class, generationTimeValue.asEnum() ); + if ( GenerationTime.ALWAYS.equals( genTime ) ) { + this.updateability.disable(); + propertyGeneration = PropertyGeneration.parse( genTime.toString().toLowerCase() ); + } + } + this.propertyGeneration = propertyGeneration; + } + + if ( getNaturalIdMutability() == NaturalIdMutability.IMMUTABLE ) { + this.updateability.disable(); + } + + List columnTransformerAnnotations = collectColumnTransformerAnnotations( backingMember ); + String[] readWrite = createCustomReadWrite( columnTransformerAnnotations ); + this.customReadFragment = readWrite[0]; + this.customWriteFragment = readWrite[1]; + } + + @Override + protected void validatePresenceOfIdAnnotation() { + // ok here + } + + @Override + protected void validatePresenceOfEmbeddedIdAnnotation() { + // ok here + } + + @Override + protected void validatePresenceOfVersionAnnotation() { + // ok here + } + + @Override + protected void validatePresenceOfNaturalIdAnnotation() { + // ok here + } + + @Override + protected void validatePresenceOfColumnAnnotation() { + // ok here + } + + @Override + protected void validatePresenceOfColumnsAnnotation() { + // ok here + } + + private SourceType extractVersionSourceType(MemberDescriptor backingMember) { + final AnnotationInstance sourceAnnotation = backingMember.getAnnotations().get( HibernateDotNames.SOURCE ); + if ( sourceAnnotation == null ) { + return null; + } + + return JandexHelper.getEnumValue( + sourceAnnotation, + "value", + SourceType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + } + + private IdentifierGeneratorDefinition extractIdentifierGeneratorDefinition(MemberDescriptor backingMember) { + final AnnotationInstance generatedValueAnnotation = backingMember.getAnnotations().get( JPADotNames.GENERATED_VALUE ); + if ( generatedValueAnnotation == null ) { + return null; + } + + IdentifierGeneratorDefinition generator = null; + + final String generatorName = JandexHelper.getValue( + generatedValueAnnotation, + "generator", + String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + if ( StringHelper.isNotEmpty( generatorName ) ) { + generator = getContext().findIdGenerator( generatorName ); + if ( generator == null ) { + throw getContext().makeMappingException( + String.format( "Unable to find named generator [%s] for %s", generatorName, getRole() ) + ); + } + } + else { + final GenerationType genType = JandexHelper.getEnumValue( + generatedValueAnnotation, + "strategy", + GenerationType.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( + genType, + getContext().getBuildingOptions().isUseNewIdentifierGenerators() + ); + generator = new IdentifierGeneratorDefinition( null, strategy, null ); + } + return generator; + } + + private List collectColumnTransformerAnnotations(MemberDescriptor backingMember) { + List allColumnTransformerAnnotations = new ArrayList(); + + final AnnotationInstance columnTransformerAnnotation = backingMember.getAnnotations().get( + HibernateDotNames.COLUMN_TRANSFORMER + ); + final AnnotationInstance columnTransformersAnnotations = backingMember.getAnnotations().get( + HibernateDotNames.COLUMN_TRANSFORMERS + ); + + if ( columnTransformerAnnotation != null && columnTransformersAnnotations != null ) { + throw getContext().makeMappingException( + "Should not mix @ColumnTransformer and @ColumnTransformers annotations " + + "on same attribute : " + backingMember.toString() + ); + } + + if ( columnTransformersAnnotations != null ) { + AnnotationInstance[] annotationInstances = allColumnTransformerAnnotations.get( 0 ).value().asNestedArray(); + allColumnTransformerAnnotations.addAll( Arrays.asList( annotationInstances ) ); + } + + if ( columnTransformerAnnotation != null ) { + allColumnTransformerAnnotations.add( columnTransformerAnnotation ); + } + return allColumnTransformerAnnotations; + } + + private String[] createCustomReadWrite(List columnTransformerAnnotations) { + String[] readWrite = new String[2]; + + boolean alreadyProcessedForColumn = false; + for ( AnnotationInstance annotationInstance : columnTransformerAnnotations ) { + String forColumn = annotationInstance.value( "forColumn" ) == null + ? null + : annotationInstance.value( "forColumn" ).asString(); + if ( forColumn != null && !isColumnPresentForTransformer( forColumn ) ) { + continue; + } + + if ( alreadyProcessedForColumn ) { + throw new AnnotationException( "Multiple definition of read/write conditions for column " + getRole() ); + } + + readWrite[0] = annotationInstance.value( "read" ) == null + ? null + : annotationInstance.value( "read" ).asString(); + readWrite[1] = annotationInstance.value( "write" ) == null + ? null : + annotationInstance.value( "write" ).asString(); + + alreadyProcessedForColumn = true; + } + return readWrite; + } + + private boolean isColumnPresentForTransformer(final String forColumn) { + assert forColumn != null; + List columns = getColumnValues(); + for ( final Column column : columns ) { + if ( forColumn.equals( column.getName() ) ) { + return true; + } + } + return forColumn.equals( getName() ); + } + + @Override + public boolean isLazy() { + return isLazy; + } + + @Override + public boolean isOptional() { + return isOptional; + } + + @Override + public boolean isInsertable() { + return insertability.shouldInclude(); + } + + @Override + public boolean isUpdatable() { + return updateability.shouldInclude(); + } + + @Override + public PropertyGeneration getPropertyGeneration() { + return propertyGeneration; + } + + public String getCustomWriteFragment() { + return customWriteFragment; + } + + public String getCustomReadFragment() { + return customReadFragment; + } + + public IdentifierGeneratorDefinition getIdentifierGeneratorDefinition() { + return identifierGeneratorDefinition; + } + + public SourceType getVersionSourceType() { + return versionSourceType; + } + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + if ( resolver == null ) { + resolver = buildTypeResolver(); + } + return resolver; + } + + private AttributeTypeResolver buildTypeResolver() { + return new AttributeTypeResolverComposition( + getBackingMember().getType().getErasedType(), + getContext(), + HibernateTypeResolver.createAttributeTypeResolver( this ), + TemporalTypeResolver.createAttributeTypeResolver( this ), + LobTypeResolver.createAttributeTypeResolve( this ), + EnumeratedTypeResolver.createAttributeTypeResolver( this ) + ); + } + + @Override + public String toString() { + return "BasicAttribute{name=" + getBackingMember().toString() + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/CollectionIdInformation.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/CollectionIdInformation.java new file mode 100644 index 000000000000..ddf6b96c87dd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/CollectionIdInformation.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * Models information from a CollectionId annotation + * + * @author Steve Ebersole + */ +public interface CollectionIdInformation { + List getColumns(); + AttributeTypeResolver getTypeResolver(); + IdentifierGeneratorDefinition getGeneratorDefinition(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/CollectionIdInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/CollectionIdInformationImpl.java new file mode 100644 index 000000000000..1ba9b6242602 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/CollectionIdInformationImpl.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * @author Steve Ebersole + */ +public class CollectionIdInformationImpl implements CollectionIdInformation { + private final List columns; + private final AttributeTypeResolver typeResolver; + private final IdentifierGeneratorDefinition generatorDefinition; + + public CollectionIdInformationImpl( + List columns, + AttributeTypeResolver typeResolver, + IdentifierGeneratorDefinition generatorDefinition) { + this.columns = columns; + this.typeResolver = typeResolver; + this.generatorDefinition = generatorDefinition; + } + + @Override + public List getColumns() { + return columns; + } + + @Override + public AttributeTypeResolver getTypeResolver() { + return typeResolver; + } + + @Override + public IdentifierGeneratorDefinition getGeneratorDefinition() { + return generatorDefinition; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/Column.java new file mode 100644 index 000000000000..02185772294a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/Column.java @@ -0,0 +1,312 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +/** + * Container for the properties defined by {@link javax.persistence.Column} or {@link javax.persistence.JoinColumn}. + * + * @author Hardy Ferentschik + */ +public class Column { + private String name = ""; + private String table = null; + + private Boolean unique; + private Boolean nullable; + private Boolean insertable; + private Boolean updatable; + + private int length = 255; + private int precision = 0; + private int scale = 0; + + private String columnDefinition; // used for DDL creation + + private String referencedColumnName; // from @JoinColumn + + public Column(AnnotationInstance columnAnnotation) { + applyCheck( columnAnnotation ); + applyColumnValues( columnAnnotation ); + } + + // todo : can we call applyCheck from within applyColumnValues itself? + // so that checks are applied when we apply overrides too + + protected void applyCheck(AnnotationInstance columnAnnotation) { + if ( columnAnnotation != null ) { + DotName name = columnAnnotation.name(); + if ( !( JPADotNames.COLUMN.equals( name ) + || JPADotNames.JOIN_COLUMN.equals( name ) + || JPADotNames.ORDER_COLUMN.equals( name ) + || JPADotNames.PRIMARY_KEY_JOIN_COLUMN.equals( name ) + || JPADotNames.MAP_KEY_COLUMN.equals( name ) + ) ) { + throw new AssertionFailure( "A @Column or @JoinColumn annotation needs to be passed to the constructor" ); + + } + } + } + + public void applyColumnValues(AnnotationInstance columnAnnotation) { + // if the column annotation is null we don't have to do anything. Everything is already defaulted. + if ( columnAnnotation == null ) { + return; + } + + AnnotationValue nameValue = columnAnnotation.value( "name" ); + if ( nameValue != null ) { + this.name = nameValue.asString(); + } + + AnnotationValue uniqueValue = columnAnnotation.value( "unique" ); + if ( uniqueValue != null ) { + this.unique = uniqueValue.asBoolean(); + } + + AnnotationValue nullableValue = columnAnnotation.value( "nullable" ); + if ( nullableValue != null ) { + this.nullable = nullableValue.asBoolean(); + } + + AnnotationValue insertableValue = columnAnnotation.value( "insertable" ); + if ( insertableValue != null ) { + this.insertable = insertableValue.asBoolean(); + } + + AnnotationValue updatableValue = columnAnnotation.value( "updatable" ); + if ( updatableValue != null ) { + this.updatable = updatableValue.asBoolean(); + } + + AnnotationValue columnDefinition = columnAnnotation.value( "columnDefinition" ); + if ( columnDefinition != null ) { + this.columnDefinition = columnDefinition.asString(); + } + + AnnotationValue tableValue = columnAnnotation.value( "table" ); + if ( tableValue != null ) { + this.table = tableValue.asString(); + } + + AnnotationValue lengthValue = columnAnnotation.value( "length" ); + if ( lengthValue != null ) { + this.length = lengthValue.asInt(); + } + + AnnotationValue precisionValue = columnAnnotation.value( "precision" ); + if ( precisionValue != null ) { + this.precision = precisionValue.asInt(); + } + + AnnotationValue scaleValue = columnAnnotation.value( "scale" ); + if ( scaleValue != null ) { + this.scale = scaleValue.asInt(); + } + + AnnotationValue referencedColumnNameValue = columnAnnotation.value( "referencedColumnName" ); + if ( referencedColumnNameValue != null ) { + this.referencedColumnName = referencedColumnNameValue.asString(); + } + } + + public final String getName() { + return name; + } + + public final Boolean isUnique() { + return unique; + } + + public final Boolean isNullable() { + return nullable; + } + + public final Boolean isInsertable() { + return insertable; + } + + public final Boolean isUpdatable() { + return updatable; + } + + public final String getColumnDefinition() { + return columnDefinition; + } + + public final String getTable() { + return table; + } + + public final int getLength() { + return length; + } + + public final int getPrecision() { + return precision; + } + + public final int getScale() { + return scale; + } + + public void setName(String name) { + this.name = name; + } + + public void setUnique(Boolean unique) { + this.unique = unique; + } + + public void setNullable(Boolean nullable) { + this.nullable = nullable; + } + + public void setInsertable(Boolean insertable) { + this.insertable = insertable; + } + + public void setUpdatable(Boolean updatable) { + this.updatable = updatable; + } + + public void setColumnDefinition(String columnDefinition) { + this.columnDefinition = columnDefinition; + } + + public void setTable(String table) { + this.table = table; + } + + public void setLength(int length) { + this.length = length; + } + + public void setPrecision(int precision) { + this.precision = precision; + } + + public void setScale(int scale) { + this.scale = scale; + } + + public String getReferencedColumnName() { + return referencedColumnName; + } + + public void setReferencedColumnName(String referencedColumnName) { + this.referencedColumnName = referencedColumnName; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "ColumnValues" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", table='" ).append( table ).append( '\'' ); + sb.append( ", unique=" ).append( unique ); + sb.append( ", nullable=" ).append( nullable ); + sb.append( ", insertable=" ).append( insertable ); + sb.append( ", updatable=" ).append( updatable ); + sb.append( ", length=" ).append( length ); + sb.append( ", precision=" ).append( precision ); + sb.append( ", scale=" ).append( scale ); + sb.append( ", columnDefinition='" ).append( columnDefinition ).append( '\'' ); + sb.append( ", referencedColumnName='" ).append( referencedColumnName ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + Column that = (Column) o; + + if ( insertable != that.insertable ) { + return false; + } + if ( length != that.length ) { + return false; + } + if ( nullable != that.nullable ) { + return false; + } + if ( precision != that.precision ) { + return false; + } + if ( scale != that.scale ) { + return false; + } + if ( unique != that.unique ) { + return false; + } + if ( updatable != that.updatable ) { + return false; + } + if ( columnDefinition != null ? !columnDefinition.equals( that.columnDefinition ) : that.columnDefinition != null ) { + return false; + } + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( referencedColumnName != null ? !referencedColumnName.equals( that.referencedColumnName ) : that.referencedColumnName != null ) { + return false; + } + if ( table != null ? !table.equals( that.table ) : that.table != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( table != null ? table.hashCode() : 0 ); + result = 31 * result + ( unique ? 1 : 0 ); + result = 31 * result + ( nullable ? 1 : 0 ); + result = 31 * result + ( insertable ? 1 : 0 ); + result = 31 * result + ( updatable ? 1 : 0 ); + result = 31 * result + length; + result = 31 * result + precision; + result = 31 * result + scale; + result = 31 * result + ( columnDefinition != null ? columnDefinition.hashCode() : 0 ); + result = 31 * result + ( referencedColumnName != null ? referencedColumnName.hashCode() : 0 ); + return result; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/ColumnInclusion.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/ColumnInclusion.java new file mode 100644 index 000000000000..beb29d97c051 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/ColumnInclusion.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +/** + * Helper for determining insertability/updateability of an attribute's columns. + *

      + * By default an attribute's columns are considered writable. Cases which + * indicate it is not writable should call {@link #disable}. + *

      + * Additionally inclusion can be completely disabled up front via the boolean + * argument to the constructor to force non-inclusion from containing contexts. + * Makes it easier to process. + * + * @author Steve Ebersole + */ +public class ColumnInclusion { + private final boolean canBeIncluded; + private boolean included = true; + + /** + * Creates the inclusion helper. + * + * @param canBeIncluded {@code false} here indicates that the inclusion can + * never be included + */ + public ColumnInclusion(boolean canBeIncluded) { + this.canBeIncluded = canBeIncluded; + } + + public void disable() { + this.included = false; + } + + public boolean shouldInclude() { + return canBeIncluded && included; + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/EmbeddedAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/EmbeddedAttribute.java new file mode 100644 index 000000000000..e025e5e4633b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/EmbeddedAttribute.java @@ -0,0 +1,201 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import javax.persistence.AccessType; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.entity.EmbeddableTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Represents a singular persistent attribute that is Embedded + * + * @author Steve Ebersole + */ +public class EmbeddedAttribute extends AbstractSingularAttribute implements EmbeddedContainer { + private final EmbeddableTypeMetadata embeddedDelegate; + private final AttributeTypeResolver attributeTypeResolver; + + private final ColumnInclusion insertability; + private final ColumnInclusion updateability; + + public EmbeddedAttribute( + ManagedTypeMetadata managedTypeMetadata, + String attributeName, + AttributePath attributePath, + AttributeRole attributeRole, + MemberDescriptor backingMember, + AccessType accessType, + String accessorStrategy) { + super( + managedTypeMetadata, + attributeName, + attributePath, + attributeRole, + backingMember, + Nature.EMBEDDED, + accessType, + accessorStrategy + ); + + this.insertability = new ColumnInclusion( managedTypeMetadata.canAttributesBeInsertable() ); + this.updateability = new ColumnInclusion( managedTypeMetadata.canAttributesBeUpdatable() ); + + // See if the user specified a @Target annotation to name a + // more-specific type + JavaTypeDescriptor embeddableType = backingMember.getType().getErasedType(); + final AnnotationInstance targetAnnotation = backingMember.getAnnotations().get( HibernateDotNames.TARGET ); + if ( targetAnnotation != null ) { + embeddableType = getContext().getJavaTypeDescriptorRepository().getType( + targetAnnotation.value().asClass().name() + ); + } + + // we pass `this` (as EmbeddedContainer) in order to route calls back properly. + this.embeddedDelegate = new EmbeddableTypeMetadata( + embeddableType, + this, + attributeRole, + attributePath, + accessType, + accessorStrategy, + managedTypeMetadata.getLocalBindingContext().getBaseContext() + ); + + this.attributeTypeResolver = HibernateTypeResolver.createAttributeTypeResolver( this ); + + if ( isId() ) { + updateability.disable(); + } + + if ( getNaturalIdMutability() == NaturalIdMutability.IMMUTABLE ) { + updateability.disable(); + } + } + + public EmbeddableTypeMetadata getEmbeddableTypeMetadata() { + return embeddedDelegate; + } + + + // EmbeddedContainer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath) { + return getContainer().locateConversionInfo( attributePath ); + } + + @Override + public AttributeOverride locateAttributeOverride(AttributePath attributePath) { + return getContainer().locateAttributeOverride( attributePath ); + } + + @Override + public AssociationOverride locateAssociationOverride(AttributePath attributePath) { + return getContainer().locateAssociationOverride( attributePath ); + } + + @Override + public void registerConverter(AttributePath attributePath, AttributeConversionInfo conversionInfo) { + getContainer().registerConverter( attributePath, conversionInfo ); + } + + @Override + public void registerAttributeOverride(AttributePath attributePath, AttributeOverride override) { + getContainer().registerAttributeOverride( attributePath, override ); + } + + @Override + public void registerAssociationOverride(AttributePath attributePath, AssociationOverride override) { + getContainer().registerAssociationOverride( attributePath, override ); + } + + @Override + public NaturalIdMutability getContainerNaturalIdMutability() { + return super.getNaturalIdMutability(); + } + + @Override + public boolean getContainerOptionality() { + return isOptional(); + } + + @Override + public boolean getContainerUpdatability() { + return isUpdatable(); + } + + @Override + public boolean getContainerInsertability() { + return isInsertable(); + } + + + // PersistentAttribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + return attributeTypeResolver; + } + + // todo : implement these + + @Override + public boolean isLazy() { + return false; + } + + @Override + public boolean isOptional() { + return false; + } + + @Override + public boolean isInsertable() { + return insertability.shouldInclude(); + } + + @Override + public boolean isUpdatable() { + return updateability.shouldInclude(); + } + + + @Override + public PropertyGeneration getPropertyGeneration() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/EmbeddedContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/EmbeddedContainer.java new file mode 100644 index 000000000000..cc35a50f0a51 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/EmbeddedContainer.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * Defines the container of an embedded value. Acts as the container for + * a EmbeddableTypeMetadata, bridging back to the "embedded". + * + * @author Steve Ebersole + */ +public interface EmbeddedContainer extends OverrideAndConverterCollector { + public MemberDescriptor getBackingMember(); + + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath); + + public AttributeOverride locateAttributeOverride(AttributePath attributePath); + + public AssociationOverride locateAssociationOverride(AttributePath attributePath); + + public NaturalIdMutability getContainerNaturalIdMutability(); + + boolean getContainerOptionality(); + boolean getContainerUpdatability(); + boolean getContainerInsertability(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/FetchableAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/FetchableAttribute.java new file mode 100644 index 000000000000..2206446d2fc6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/FetchableAttribute.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.engine.FetchStyle; + +/** + * @author Steve Ebersole + */ +public interface FetchableAttribute { + public FetchStyle getFetchStyle(); + public boolean isLazy(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/FormulaValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/FormulaValue.java new file mode 100644 index 000000000000..827df65a4083 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/FormulaValue.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +/** + * @author Strong Liu + */ +public class FormulaValue { + private final String tableName; + private final String expression; + + public FormulaValue(String tableName, String expression) { + this.tableName = tableName; + this.expression = expression; + } + + public String getExpression() { + return expression; + } + + public String getContainingTableName() { + return tableName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/OverrideAndConverterCollector.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/OverrideAndConverterCollector.java new file mode 100644 index 000000000000..2dccad791562 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/OverrideAndConverterCollector.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.spi.AttributePath; + +/** + * Contract used in normalizing AttributeConverters, AttributeOverrides and + * AssociationOverrides. + * + * @author Steve Ebersole + */ +public interface OverrideAndConverterCollector { + void registerConverter(AttributePath attributePath, AttributeConversionInfo conversionInfo); + + void registerAttributeOverride(AttributePath attributePath, AttributeOverride override); + + void registerAssociationOverride(AttributePath attributePath, AssociationOverride override); + + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath); + + public AttributeOverride locateAttributeOverride(AttributePath attributePath); + + public AssociationOverride locateAssociationOverride(AttributePath attributePath); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PersistentAttribute.java new file mode 100644 index 000000000000..90aa7b70b4d4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PersistentAttribute.java @@ -0,0 +1,177 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import javax.persistence.AccessType; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; + +import org.jboss.jandex.DotName; + +/** + * Represents the most basic definition of a persistent attribute. At + * the "next level up" we categorize attributes as either:

        + *
      • singular - {@link SingularAttribute}
      • + *
      • plural - {@link PluralAttribute}
      • + *
      + * + * @author Steve Ebersole + */ +public interface PersistentAttribute extends Comparable { + /** + * Access the name of the attribute being modeled. + * + * @return The attribute name + */ + String getName(); + + /** + * The nature (category) of the attribute being modeled. + * + * @return The attribute nature + */ + Nature getNature(); + + /** + * The container (class) for the attribute + * + * @return The attribute container + */ + ManagedTypeMetadata getContainer(); + + /** + * The member on the container that represents the attribute *as defined + * by AccessType*. In other words this is the class member where we can + * look for annotations. It is not necessarily the same as the backing + * member used to inject/extract values during runtime. + * + * @return The backing member + */ + MemberDescriptor getBackingMember(); + + /** + * This is a unique name for the attribute within the entire mapping. + * Generally roles are rooted at an entity name. Each path in the role + * is separated by hash (#) signs. + *

      + * Practically speaking, this is used to uniquely identify collection + * and embeddable mappings. + * + * @return The attribute role. + */ + AttributeRole getRole(); + + /** + * This is a unique name for the attribute within a top-level container. + * Mainly this is a normalized name used to apply AttributeOverride and + * AssociationOverride annotations. + * + * @return The attribute path + */ + AttributePath getPath(); + + /** + * Obtain the AccessType in use for this attribute. The AccessType defines where + * to look for annotations and is never {@code null} + * + * @return The AccessType, never {@code null}. + */ + AccessType getAccessType(); + + /** + * Obtain the runtime accessor strategy. This defines how we inject and + * extract values to/from the attribute at runtime. + * + * @return The runtime accessor strategy + */ + String getAccessorStrategy(); + + /** + * Is this attribute lazy? + *

      + * NOTE : Hibernate currently only really supports laziness for + * associations. But JPA metadata defines lazy for basic attributes + * too; so we report that info at the basic level + * + * @return Whether the attribute it lazy. + */ + boolean isLazy(); + + /** + * Do changes in this attribute trigger optimistic locking checks? + * + * @return {@code true} (the default) indicates the attribute is included + * in optimistic locking; {@code false} indicates it is not. + */ + boolean isIncludeInOptimisticLocking(); + + // ugh + public PropertyGeneration getPropertyGeneration(); + + public abstract boolean isOptional(); + + public abstract boolean isInsertable(); + + public abstract boolean isUpdatable(); + + + AttributeTypeResolver getHibernateTypeResolver(); + + public EntityBindingContext getContext(); + + /** + * An enum defining the nature (categorization) of a persistent attribute. + */ + public static enum Nature { + BASIC( JPADotNames.BASIC ), + EMBEDDED_ID( JPADotNames.EMBEDDED_ID ), + EMBEDDED( JPADotNames.EMBEDDED ), + ANY( HibernateDotNames.ANY ), + ONE_TO_ONE( JPADotNames.ONE_TO_ONE ), + MANY_TO_ONE( JPADotNames.MANY_TO_ONE ), + ONE_TO_MANY( JPADotNames.ONE_TO_MANY ), + MANY_TO_MANY( JPADotNames.MANY_TO_MANY ), + MANY_TO_ANY( HibernateDotNames.MANY_TO_ANY ), + ELEMENT_COLLECTION_BASIC( JPADotNames.ELEMENT_COLLECTION ), + ELEMENT_COLLECTION_EMBEDDABLE( JPADotNames.ELEMENT_COLLECTION ); + + private final DotName annotationDotName; + + Nature(DotName annotationDotName) { + this.annotationDotName = annotationDotName; + } + + public DotName getAnnotationDotName() { + return annotationDotName; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttribute.java new file mode 100644 index 000000000000..ecbce5105fab --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttribute.java @@ -0,0 +1,912 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import javax.persistence.AccessType; +import javax.persistence.CascadeType; + +import org.hibernate.TruthValue; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.LazyCollectionOption; +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.FetchStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.binder.ForeignKeyDelegate; +import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.CollectionTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.ExplicitTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.source.internal.annotations.util.AssociationHelper; +import org.hibernate.metamodel.source.internal.annotations.util.ConverterAndOverridesHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.LOADER; +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.ON_DELETE; +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.PERSISTER; +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.WHERE; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.EMBEDDABLE; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ENTITY; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.MAP_KEY; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.MAP_KEY_CLASS; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.MAP_KEY_COLUMN; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.MAP_KEY_ENUMERATED; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.MAP_KEY_TEMPORAL; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ORDER_BY; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ORDER_COLUMN; + +/** + * Represents a plural persistent attribute. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Strong Liu + */ +public class PluralAttribute + extends AbstractPersistentAttribute + implements FetchableAttribute, AssociationAttribute { + private static final EnumSet CANNOT_HAVE_COLLECTION_ID = EnumSet.of( + PluralAttributeNature.SET, + PluralAttributeNature.MAP, + PluralAttributeNature.LIST, + PluralAttributeNature.ARRAY + ); + + private final String mappedByAttributeName; + private final Set jpaCascadeTypes; + private final Set hibernateCascadeTypes; + private final boolean isOrphanRemoval; + private final boolean ignoreNotFound; + private final boolean isOptional; + private final boolean isUnWrapProxy; + + private final FetchStyle fetchStyle; + private final boolean isLazy; + + // information about the collection + private final CollectionIdInformation collectionIdInformation; + private final PluralAttributeNature pluralAttributeNature; + private final String customPersister; + private final Caching caching; + private final String comparatorName; + private final String customLoaderName; + private final CustomSQL customInsert; + private final CustomSQL customUpdate; + private final CustomSQL customDelete; + private final CustomSQL customDeleteAll; + private final String whereClause; + private final String orderBy; + private final boolean sorted; + private final boolean isExtraLazy; + private final boolean mutable; + private final int batchSize; + + // information about the FK + private final OnDeleteAction onDeleteAction; + private final ForeignKeyDelegate foreignKeyDelegate; + + private final AttributeTypeResolver collectionTypeResolver; + + // information about the element + private final PluralAttributeElementDetails elementDetails; + + // information about the index + private final PluralAttributeIndexDetails indexDetails; + + private final AnnotationInstance joinTableAnnotation; + private ArrayList joinColumnValues = new ArrayList(); + private ArrayList inverseJoinColumnValues = new ArrayList(); + + private final ClassLoaderService classLoaderService; + + public PluralAttribute( + ManagedTypeMetadata container, + String name, + AttributePath attributePath, + AttributeRole attributeRole, + MemberDescriptor backingMember, + Nature attributeNature, + JavaTypeDescriptor elementType, + JavaTypeDescriptor indexType, + AccessType accessType, + String accessorStrategy) { + super( + container, + name, + attributePath, + attributeRole, + backingMember, + attributeNature, + accessType, + accessorStrategy + ); + + this.classLoaderService = getContext().getServiceRegistry().getService( ClassLoaderService.class ); + + // just to get the error the test expects + // todo : I'd really rather see this driven from the class-level, not the attribute-level + AssociationHelper.INSTANCE.determineMapsId( + backingMember, + attributeNature, + container.getLocalBindingContext() + ); + + final AnnotationInstance associationAnnotation = backingMember.getAnnotations().get( attributeNature.getAnnotationDotName() ); + final AnnotationInstance lazyCollectionAnnotation = backingMember.getAnnotations().get( HibernateDotNames.LAZY_COLLECTION ); + + this.mappedByAttributeName = AssociationHelper.INSTANCE.determineMappedByAttributeName( associationAnnotation ); + + this.fetchStyle = AssociationHelper.INSTANCE.determineFetchStyle( backingMember ); + this.isLazy = AssociationHelper.INSTANCE.determineWhetherIsLazy( + associationAnnotation, + lazyCollectionAnnotation, + backingMember, + fetchStyle, + true + ); + this.isExtraLazy = determineWhetherIsExtraLazy( lazyCollectionAnnotation ); + + this.isOptional = AssociationHelper.INSTANCE.determineOptionality( associationAnnotation ); + this.isUnWrapProxy = AssociationHelper.INSTANCE.determineWhetherToUnwrapProxy( backingMember ); + + this.jpaCascadeTypes = AssociationHelper.INSTANCE.determineCascadeTypes( associationAnnotation ); + this.hibernateCascadeTypes = AssociationHelper.INSTANCE.determineHibernateCascadeTypes( backingMember ); + this.isOrphanRemoval = AssociationHelper.INSTANCE.determineOrphanRemoval( associationAnnotation ); + this.ignoreNotFound = AssociationHelper.INSTANCE.determineWhetherToIgnoreNotFound( backingMember ); + + this.collectionIdInformation = extractCollectionIdInformation( backingMember ); + this.pluralAttributeNature = resolvePluralAttributeNature( backingMember, collectionIdInformation ); + + this.elementDetails = resolveElementDetails( backingMember, attributeNature, elementType ); + this.indexDetails = resolveIndexDetails( backingMember, pluralAttributeNature, indexType ); + this.collectionTypeResolver = new CollectionTypeResolver( this ); + + this.mutable = !backingMember.getAnnotations().containsKey( HibernateDotNames.IMMUTABLE ); + final AnnotationInstance batchAnnotation = backingMember.getAnnotations().get( HibernateDotNames.BATCH_SIZE ); + if ( batchAnnotation != null ) { + this.batchSize = batchAnnotation.value( "size" ).asInt(); + } + else { + this.batchSize = -1; + } + + this.whereClause = determineWereClause( backingMember ); + this.orderBy = determineOrderBy( backingMember ); + + this.foreignKeyDelegate = new ForeignKeyDelegate( backingMember.getAnnotations(), classLoaderService ); + + this.caching = determineCachingSettings( backingMember ); + + this.customPersister = determineCustomPersister( backingMember ); + this.customLoaderName = determineCustomLoaderName( backingMember ); + this.customInsert = AnnotationParserHelper.createCustomSQL( + backingMember.getAnnotations().get( HibernateDotNames.SQL_INSERT ) + ); + this.customUpdate = AnnotationParserHelper.createCustomSQL( + backingMember.getAnnotations().get( HibernateDotNames.SQL_UPDATE ) + ); + this.customDelete = AnnotationParserHelper.createCustomSQL( + backingMember.getAnnotations().get( HibernateDotNames.SQL_DELETE ) + ); + this.customDeleteAll = AnnotationParserHelper.createCustomSQL( + backingMember.getAnnotations().get( HibernateDotNames.SQL_DELETE_ALL ) + ); + + this.onDeleteAction = determineOnDeleteAction( backingMember ); + + final AnnotationInstance sortNaturalAnnotation = backingMember.getAnnotations().get( HibernateDotNames.SORT_NATURAL ); + final AnnotationInstance sortComparatorAnnotation = backingMember.getAnnotations().get( HibernateDotNames.SORT_COMPARATOR ); + if ( sortNaturalAnnotation != null ) { + this.sorted = true; + this.comparatorName = "natural"; + } + else if ( sortComparatorAnnotation != null ) { + this.sorted = true; + this.comparatorName = sortComparatorAnnotation.value().asString(); + } + else { + this.sorted = false; + this.comparatorName = null; + } + + if ( this.mappedByAttributeName == null ) { + // todo : not at all a fan of this mess... + AssociationHelper.INSTANCE.processJoinColumnAnnotations( + backingMember, + joinColumnValues, + getContext() + ); + AssociationHelper.INSTANCE.processJoinTableAnnotations( + backingMember, + joinColumnValues, + inverseJoinColumnValues, + getContext() + ); + this.joinTableAnnotation = AssociationHelper.INSTANCE.extractExplicitJoinTable( + backingMember, + getContext() + ); + } + else { + this.joinTableAnnotation = null; + } + joinColumnValues.trimToSize(); + inverseJoinColumnValues.trimToSize(); + + ConverterAndOverridesHelper.INSTANCE.processConverters( + getPath(), + getNature(), + backingMember, + container, + getContext() + ); + ConverterAndOverridesHelper.INSTANCE.processAttributeOverrides( + getPath(), + backingMember, + container, + getContext() + ); + ConverterAndOverridesHelper.INSTANCE.processAssociationOverrides( + getPath(), + backingMember, + container, + getContext() + ); + + validateMapping(); + } + + private CollectionIdInformation extractCollectionIdInformation(MemberDescriptor backingMember) { + final AnnotationInstance collectionId = backingMember.getAnnotations().get( HibernateDotNames.COLLECTION_ID ); + if ( collectionId == null ) { + return null; + } + + final IdentifierGeneratorDefinition generator = new IdentifierGeneratorDefinition( + null, + collectionId.value( "generator" ).asString(), + null + ); + + final AnnotationInstance type = JandexHelper.getValue( collectionId, "type", AnnotationInstance.class, + classLoaderService ); + final AnnotationValue typeType = type.value( "type" ); + final String typeName = typeType == null ? null : typeType.asString(); + if ( StringHelper.isEmpty( typeName ) ) { + throw getContext().makeMappingException( + "Plural attribute [" + backingMember.toString() + "] specified @CollectionId.type incorrectly, " + + "type name was missing" + ); + } + final ExplicitTypeResolver typeResolver = new ExplicitTypeResolver( typeName, extractTypeParameters( type ) ); + + final AnnotationInstance[] columnAnnotations = JandexHelper.getValue( + collectionId, + "columns", + AnnotationInstance[].class, + classLoaderService + ); + final List idColumns = CollectionHelper.arrayList( columnAnnotations.length ); + for ( AnnotationInstance columnAnnotation : columnAnnotations ) { + idColumns.add( new Column( columnAnnotation ) ); + } + + return new CollectionIdInformationImpl( idColumns, typeResolver, generator ); + } + + private Map extractTypeParameters(AnnotationInstance type) { + final AnnotationInstance[] paramAnnotations = JandexHelper.getValue( + type, + "parameters", + AnnotationInstance[].class, + classLoaderService + ); + if ( paramAnnotations == null || paramAnnotations.length == 0 ) { + return Collections.emptyMap(); + } + else if ( paramAnnotations.length == 1 ) { + return Collections.singletonMap( + paramAnnotations[0].value( "name" ).asString(), + paramAnnotations[0].value( "value" ).asString() + ); + } + + final Map parameters = CollectionHelper.mapOfSize( paramAnnotations.length ); + for ( AnnotationInstance paramAnnotation : paramAnnotations ) { + parameters.put( + paramAnnotation.value( "name" ).asString(), + paramAnnotation.value( "value" ).asString() + ); + } + return parameters; + } + + + private PluralAttributeNature resolvePluralAttributeNature( + MemberDescriptor backingMember, + CollectionIdInformation collectionIdInformation) { + //TODO org.hibernate.cfg.annotations.CollectionBinder#hasToBeSorted + + final JavaTypeDescriptor pluralType = backingMember.getType().getErasedType(); + + if ( ArrayDescriptor.class.isInstance( pluralType ) ) { + return PluralAttributeNature.ARRAY; + } + + if ( getContext().getJavaTypeDescriptorRepository().jdkMapDescriptor().isAssignableFrom( pluralType ) ) { + return PluralAttributeNature.MAP; + } + + if ( getContext().getJavaTypeDescriptorRepository().jdkSetDescriptor().isAssignableFrom( pluralType ) ) { + return PluralAttributeNature.SET; + } + + if ( getContext().getJavaTypeDescriptorRepository().jdkListDescriptor().isAssignableFrom( pluralType ) ) { + // we have a LIST nature as long as there is an @OrderColumn annotation + if ( backingMember.getAnnotations().containsKey( ORDER_COLUMN ) ) { + return PluralAttributeNature.LIST; + } + } + + // just a double check... + if ( !getContext().getJavaTypeDescriptorRepository().jdkCollectionDescriptor().isAssignableFrom( pluralType ) ) { + throw getContext().makeMappingException( + "Plural attribute [" + backingMember.toString() + "] was not a collection or an array" + ); + } + + // at this point we have either a BAG or IDBAG, depending on whether + // there is a @CollectionId present + + // todo : does ID_BAG really need a separate nature? + return collectionIdInformation != null + ? PluralAttributeNature.ID_BAG + : PluralAttributeNature.BAG; + } + + private PluralAttributeElementDetails resolveElementDetails( + MemberDescriptor backingMember, + Nature attributeNature, + JavaTypeDescriptor elementType) { + switch ( attributeNature ) { + case ELEMENT_COLLECTION_BASIC: { + return new PluralAttributeElementDetailsBasic( this, elementType ); + } + case ELEMENT_COLLECTION_EMBEDDABLE: { + return new PluralAttributeElementDetailsEmbedded( this, elementType ); + } + case ONE_TO_MANY: + case MANY_TO_MANY: { + return new PluralAttributeElementDetailsEntity( this, elementType ); + } + case MANY_TO_ANY: { + throw new NotYetImplementedException( "@ManyToAny element support still baking" ); + } + default: { + throw getContext().makeMappingException( + "Unexpected nature encountered for plural attribute : " + attributeNature + ); + } + } + } + + private PluralAttributeIndexDetails resolveIndexDetails( + MemberDescriptor backingMember, + PluralAttributeNature pluralAttributeNature, + JavaTypeDescriptor indexType) { + // could be an array/list + if ( pluralAttributeNature == PluralAttributeNature.ARRAY + || pluralAttributeNature == PluralAttributeNature.LIST ) { + return new PluralAttributeIndexDetailsSequential( this, backingMember ); + } + + // or a map + if ( pluralAttributeNature != PluralAttributeNature.MAP ) { + return null; + } + + final AnnotationInstance mapKeyAnnotation = backingMember.getAnnotations().get( MAP_KEY ); + final AnnotationInstance mapKeyClassAnnotation = backingMember.getAnnotations().get( MAP_KEY_CLASS ); + final AnnotationInstance mapKeyColumnAnnotation = backingMember.getAnnotations().get( MAP_KEY_COLUMN ); + final AnnotationInstance mapKeyEnumeratedAnnotation = backingMember.getAnnotations().get( MAP_KEY_ENUMERATED ); + final AnnotationInstance mapKeyTemporalAnnotation = backingMember.getAnnotations().get( MAP_KEY_TEMPORAL ); + + final List mapKeyJoinColumnAnnotations = collectMapKeyJoinColumnAnnotations( backingMember ); + + if ( mapKeyAnnotation != null && mapKeyClassAnnotation != null ) { + // this is an error according to the spec... + throw getContext().makeMappingException( + "Map attribute defined both @MapKey and @MapKeyClass; only one should be used : " + + backingMember.toLoggableForm() + ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Level 1 : @MapKey + + if ( mapKeyAnnotation != null ) { + final AnnotationValue value = mapKeyAnnotation.value( "name" ); + String mapKeyAttributeName = null; + if ( value != null ) { + mapKeyAttributeName = StringHelper.nullIfEmpty( value.asString() ); + } + return new PluralAttributeIndexDetailsMapKeyEntityAttribute( this, backingMember, indexType, mapKeyAttributeName ); + } + + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Level 2 : @MapKeyEnumerated / @MapKeyTemporal imply basic key + + if ( mapKeyEnumeratedAnnotation != null || mapKeyTemporalAnnotation != null ) { + return new PluralAttributeIndexDetailsMapKeyBasic( this, backingMember, indexType, mapKeyColumnAnnotation ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Level 3 : if we could not decode a specific key type, we assume basic + + JavaTypeDescriptor mapKeyType = indexType; + if ( mapKeyClassAnnotation != null ) { + final DotName name = mapKeyClassAnnotation.value().asClass().name(); + mapKeyType = getContext().getJavaTypeDescriptorRepository().getType( name ); + } + if ( mapKeyType == null ) { + if ( !mapKeyJoinColumnAnnotations.isEmpty() ) { + throw getContext().makeMappingException( + "Map key type could not be resolved (to determine entity name to use as key), " + + "but @MapKeyJoinColumn(s) was present. Map should either use generics or " + + "use @MapKeyClass to specify entity class" + ); + } + return new PluralAttributeIndexDetailsMapKeyBasic( this, backingMember, indexType, mapKeyColumnAnnotation ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Level 4 : if @MapKeyJoinColumn(s) were specified, we have an entity + + if ( !mapKeyJoinColumnAnnotations.isEmpty() ) { + throw new NotYetImplementedException( "Entities as map keys not yet implemented" ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Level 5 : if decode the nature of the map key type + + if ( mapKeyType.findTypeAnnotation( EMBEDDABLE ) != null ) { + return new PluralAttributeIndexDetailsMapKeyEmbedded( this, backingMember, indexType ); + } + + if ( mapKeyType.findTypeAnnotation( ENTITY ) != null ) { + throw new NotYetImplementedException( "Entities as map keys not yet implemented" ); + } + + return new PluralAttributeIndexDetailsMapKeyBasic( this, backingMember, indexType, mapKeyColumnAnnotation ); + } + + private List collectMapKeyJoinColumnAnnotations(MemberDescriptor backingMember) { + final AnnotationInstance singular = backingMember.getAnnotations().get( JPADotNames.MAP_KEY_JOIN_COLUMN ); + final AnnotationInstance plural = backingMember.getAnnotations().get( JPADotNames.MAP_KEY_JOIN_COLUMNS ); + + if ( singular != null && plural != null ) { + throw getContext().makeMappingException( + "Attribute [" + backingMember.toLoggableForm() + + "] declared both @MapKeyJoinColumn and " + + "@MapKeyJoinColumns; should only use one or the other" + ); + } + + if ( singular == null && plural == null ) { + return Collections.emptyList(); + } + + if ( singular != null ) { + return Collections.singletonList( singular ); + } + + final AnnotationInstance[] annotations = JandexHelper.extractAnnotationsValue( + plural, + "value" + ); + if ( annotations == null || annotations.length == 0 ) { + return null; + } + + return Arrays.asList( annotations ); + } + + private Caching determineCachingSettings(MemberDescriptor backingMember) { + Caching caching = new Caching( TruthValue.UNKNOWN ); + + final AnnotationInstance hbmCacheAnnotation = backingMember.getAnnotations().get( HibernateDotNames.CACHE ); + if ( hbmCacheAnnotation != null ) { + caching.setRequested( TruthValue.TRUE ); + + final AnnotationValue usageValue = hbmCacheAnnotation.value( "usage" ); + if ( usageValue != null ) { + caching.setAccessType( CacheConcurrencyStrategy.parse( usageValue.asEnum() ).toAccessType() ); + } + + final AnnotationValue regionValue = hbmCacheAnnotation.value( "region" ); + if ( regionValue != null ) { + caching.setRegion( regionValue.asString() ); + } + + // NOTE "include" is irrelevant for collections + } + + return caching; + } + + private boolean determineWhetherIsExtraLazy(AnnotationInstance lazyCollectionAnnotation) { + if ( lazyCollectionAnnotation == null ) { + return false; + } + final AnnotationValue optionValue = lazyCollectionAnnotation.value( "value" ); + if ( optionValue == null ) { + return false; + } + final LazyCollectionOption option = LazyCollectionOption.valueOf( optionValue.asEnum() ); + return option == LazyCollectionOption.EXTRA; + } + + private String determineCustomLoaderName(MemberDescriptor backingMember) { + final AnnotationInstance loaderAnnotation = backingMember.getAnnotations().get( LOADER ); + return loaderAnnotation == null + ? null + : StringHelper.nullIfEmpty( loaderAnnotation.value( "namedQuery" ).asString() ); + } + + private String determineCustomPersister(MemberDescriptor backingMember) { + final AnnotationInstance persisterAnnotation = backingMember.getAnnotations().get( PERSISTER ); + return persisterAnnotation == null + ? null + : StringHelper.nullIfEmpty( persisterAnnotation.value( "impl" ).asString() ); + } + + private OnDeleteAction determineOnDeleteAction(MemberDescriptor backingMember) { + final AnnotationInstance onDeleteAnnotation = backingMember.getAnnotations().get( + ON_DELETE + ); + return onDeleteAnnotation == null + ? null + : OnDeleteAction.valueOf( onDeleteAnnotation.value( "action" ).asString() ); + } + + private String determineWereClause(MemberDescriptor backingMember) { + final AnnotationInstance whereAnnotation = backingMember.getAnnotations().get( WHERE ); + return whereAnnotation == null + ? null + : StringHelper.nullIfEmpty( whereAnnotation.value( "clause" ).asString() ); + } + + private String determineOrderBy(MemberDescriptor backingMember) { + final AnnotationInstance hbmOrderBy = backingMember.getAnnotations().get( HibernateDotNames.ORDER_BY ); + final AnnotationInstance jpaOrderBy = backingMember.getAnnotations().get( ORDER_BY ); + + if ( hbmOrderBy != null && jpaOrderBy != null ) { + throw getContext().makeMappingException( + "Cannot use sql order by clause (@org.hibernate.annotations.OrderBy) " + + "in conjunction with JPA order by clause (@java.persistence.OrderBy) on " + + backingMember.toString() + ); + } + + + if ( hbmOrderBy != null ) { + return StringHelper.nullIfEmpty( hbmOrderBy.value( "clause" ).asString() ); + } + + if ( jpaOrderBy != null ) { + // this could be an empty string according to JPA spec 11.1.38 - + // If the ordering element is not specified for an entity association, ordering by the primary key of the + // associated entity is assumed + // The binder will need to take this into account and generate the right property names + final AnnotationValue orderByValue = jpaOrderBy.value(); + final String value = orderByValue == null ? null : StringHelper.nullIfEmpty( orderByValue.asString() ); + if ( value == null || value.equalsIgnoreCase( "asc" ) ) { + return isBasicCollection() ? "$element$ asc" : "id asc" ; + } + else if ( value.equalsIgnoreCase( "desc" ) ) { + return isBasicCollection() ? "$element$ desc" : "id desc"; + } + else { + return value; + } + } + + return null; + } + + private void validateMapping() { + checkSortedTypeIsSortable(); + checkIfCollectionIdIsWronglyPlaced(); + } + + private void checkIfCollectionIdIsWronglyPlaced() { + if ( collectionIdInformation != null && CANNOT_HAVE_COLLECTION_ID.contains( pluralAttributeNature ) ) { + throw new MappingException( + "The Collection type doesn't support @CollectionId annotation: " + getRole(), + getContext().getOrigin() + ); + } + } + + private void checkSortedTypeIsSortable() { + if ( pluralAttributeNature != PluralAttributeNature.MAP + && pluralAttributeNature != PluralAttributeNature.SET ) { + return; + } + + final JavaTypeDescriptor sortedMapType = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( SortedMap.class.getName() ) + ); + final JavaTypeDescriptor sortedSetType = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( SortedSet.class.getName() ) + ); + if ( sortedMapType.isAssignableFrom( getBackingMember().getType().getErasedType() ) + || sortedSetType.isAssignableFrom( getBackingMember().getType().getErasedType() ) ) { + if ( !isSorted() ) { + throw getContext().makeMappingException( + "A SortedSet/SortedMap attribute has to define @SortNatural or @SortComparator : " + + getBackingMember().toString() + ); + } + } + } + + public AnnotationInstance getJoinTableAnnotation() { + return joinTableAnnotation; + } + + public ArrayList getJoinColumnValues() { + return joinColumnValues; + } + + public ArrayList getInverseJoinColumnValues() { + return inverseJoinColumnValues; + } + + @Override + public boolean isOptional() { + return isOptional; + } + + @Override + public boolean isInsertable() { + // irrelevant + return true; + } + + @Override + public boolean isUpdatable() { + // irrelevant + return true; + } + + @Override + public PropertyGeneration getPropertyGeneration() { + return PropertyGeneration.NEVER; + } + + @Override + public String getMappedByAttributeName() { + return mappedByAttributeName; + } + + @Override + public Set getJpaCascadeTypes() { + return jpaCascadeTypes; + } + + @Override + public Set getHibernateCascadeTypes() { + return hibernateCascadeTypes; + } + + @Override + public boolean isOrphanRemoval() { + return isOrphanRemoval; + } + + @Override + public boolean isIgnoreNotFound() { + return ignoreNotFound; + } + + @Override + public boolean isUnWrapProxy() { + return isUnWrapProxy; + } + + @Override + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + @Override + public boolean isLazy() { + return isLazy; + } + + public CollectionIdInformation getCollectionIdInformation() { + return collectionIdInformation; + } + + public PluralAttributeElementDetails getElementDetails() { + return elementDetails; + } + + public PluralAttributeIndexDetails getIndexDetails() { + return indexDetails; + } + + public PluralAttributeNature getPluralAttributeNature() { + return pluralAttributeNature; + } + + public String getWhereClause() { + return whereClause; + } + + public String getOrderBy() { + return orderBy; + } + + public String getInverseForeignKeyName() { + return foreignKeyDelegate.getInverseForeignKeyName(); + } + public String getExplicitForeignKeyName(){ + return foreignKeyDelegate.getExplicitForeignKeyName(); + } + public boolean createForeignKeyConstraint(){ + return foreignKeyDelegate.createForeignKeyConstraint(); + } + + public Caching getCaching() { + return caching; + } + + public String getCustomPersister() { + return customPersister; + } + + public String getCustomLoaderName() { + return customLoaderName; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public CustomSQL getCustomDeleteAll() { + return customDeleteAll; + } + + @Override + public String toString() { + return "PluralAttribute{name='" + getRole().getFullPath() + '\'' + '}'; + } + public OnDeleteAction getOnDeleteAction() { + return onDeleteAction; + } + + public String getComparatorName() { + return comparatorName; + } + + public boolean isSorted() { + return sorted; + } + + + + + @Override + public boolean isIncludeInOptimisticLocking() { + return hasOptimisticLockAnnotation() + ? super.isIncludeInOptimisticLocking() + : StringHelper.isEmpty( getMappedByAttributeName() ); + } + + public int getBatchSize() { + return batchSize; + } + + public boolean isExtraLazy() { + return isExtraLazy; + } + + private boolean isBasicCollection(){ + return getNature() == Nature.ELEMENT_COLLECTION_BASIC || getNature() == Nature.ELEMENT_COLLECTION_EMBEDDABLE; + } + + + public boolean isMutable() { + return mutable; + } + + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + return collectionTypeResolver; + } + +// public AttributeTypeResolver getIndexTypeResolver() { +// if ( indexType == null ) { +// return getDefaultHibernateTypeResolver(); +// } +// else if ( indexTypeResolver == null ) { +// CompositeAttributeTypeResolver resolver = new CompositeAttributeTypeResolver( this ); +// final String name = getName() + ".index"; +// resolver.addHibernateTypeResolver( HibernateTypeResolver.createCollectionIndexTypeResolver( this ) ); +// // TODO: Lob allowed as collection index? I don't see an annotation for that. +// resolver.addHibernateTypeResolver( EnumeratedTypeResolver.createCollectionIndexTypeResolver( this ) ); +// resolver.addHibernateTypeResolver( TemporalTypeResolver.createCollectionIndexTypeResolver( this ) ); +// indexTypeResolver = resolver; +// } +// return indexTypeResolver; +// } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetails.java new file mode 100644 index 000000000000..f22c1f0f24bc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetails.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * Presents metadata about the elements of a plural attribute + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementDetails { + /** + * Get the descriptor for the Java type of the collection elements. + * + * @return The descriptor for the Java type of the collection elements. + */ + public JavaTypeDescriptor getJavaType(); + + /** + * Get the nature of the element values. + * + * @return The element nature + */ + public PluralAttributeElementNature getElementNature(); + + /** + * Get the type resolver for the collection elements. + * + * @return The type resolver for the collection elements. + */ + public AttributeTypeResolver getTypeResolver(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsBasic.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsBasic.java new file mode 100644 index 000000000000..3f438329401b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsBasic.java @@ -0,0 +1,106 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolverComposition; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.EnumeratedTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.LobTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.TemporalTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeElementDetailsBasic implements PluralAttributeElementDetails { + private final JavaTypeDescriptor javaType; + private final AttributeTypeResolver typeResolver; + + public PluralAttributeElementDetailsBasic( + PluralAttribute pluralAttribute, + JavaTypeDescriptor inferredElementType) { + this.javaType = determineJavaType( pluralAttribute, inferredElementType ); + this.typeResolver = buildTypeResolver( pluralAttribute, javaType ); + } + + private static JavaTypeDescriptor determineJavaType(PluralAttribute pluralAttribute, JavaTypeDescriptor elementType) { + if ( elementType != null ) { + return elementType; + } + + final AnnotationInstance annotation = pluralAttribute.getBackingMember().getAnnotations().get( JPADotNames.ELEMENT_COLLECTION ); + if ( annotation == null ) { + throw pluralAttribute.getContext().makeMappingException( + "Could not determine element type information for plural attribute [" + + pluralAttribute.getBackingMember().toString() + + "]; could not locate @ElementCollection annotation" + ); + } + + final AnnotationValue targetClassValue = annotation.value( "targetClass" ); + if ( targetClassValue == null ) { + throw pluralAttribute.getContext().makeMappingException( + "Could not determine element type information for plural attribute [" + + pluralAttribute.getBackingMember().toString() + + "]; @ElementCollection did not specify targetClass" + ); + } + + return pluralAttribute.getContext().getJavaTypeDescriptorRepository().getType( + targetClassValue.asClass().name() + ); + } + + private static AttributeTypeResolver buildTypeResolver(PluralAttribute pluralAttribute, JavaTypeDescriptor javaType) { + return new AttributeTypeResolverComposition( + javaType, + pluralAttribute.getContext(), + HibernateTypeResolver.createCollectionElementTypeResolver( pluralAttribute, javaType ), + TemporalTypeResolver.createCollectionElementTypeResolver( pluralAttribute, javaType ), + LobTypeResolver.createCollectionElementTypeResolve( pluralAttribute, javaType ), + EnumeratedTypeResolver.createCollectionElementTypeResolver( pluralAttribute, javaType ) + ); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return javaType; + } + + @Override + public PluralAttributeElementNature getElementNature() { + return PluralAttributeElementNature.BASIC; + } + + @Override + public AttributeTypeResolver getTypeResolver() { + return typeResolver; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsEmbedded.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsEmbedded.java new file mode 100644 index 000000000000..938b76e4789b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsEmbedded.java @@ -0,0 +1,201 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolverComposition; +import org.hibernate.metamodel.source.internal.annotations.entity.EmbeddableTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeElementDetailsEmbedded implements PluralAttributeElementDetails, EmbeddedContainer { + private final PluralAttribute pluralAttribute; + + private final ClassDescriptor javaType; + private final EmbeddableTypeMetadata embeddableTypeMetadata; + private final AttributeTypeResolver typeResolver; + + public PluralAttributeElementDetailsEmbedded( + PluralAttribute pluralAttribute, + JavaTypeDescriptor inferredElementType) { + this.pluralAttribute = pluralAttribute; + this.javaType = determineJavaType( pluralAttribute, inferredElementType ); + + if ( this.javaType == null ) { + throw pluralAttribute.getContext().makeMappingException( + "Could not determine element type information for plural attribute : " + + pluralAttribute.getBackingMember().toString() + ); + } + + this.embeddableTypeMetadata = buildEmbeddedMetadata( pluralAttribute, javaType ); + this.typeResolver = new AttributeTypeResolverComposition( javaType, pluralAttribute.getContext() ); + } + + private static ClassDescriptor determineJavaType( + PluralAttribute pluralAttribute, + JavaTypeDescriptor inferredElementType) { + + // NOTE : ClassDescriptor because atm only classes can be embedded/embeddable + + final AnnotationInstance targetAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( HibernateDotNames.TARGET ); + if ( targetAnnotation != null ) { + final AnnotationValue targetValue = targetAnnotation.value(); + if ( targetValue != null ) { + return (ClassDescriptor) pluralAttribute.getContext().getJavaTypeDescriptorRepository().getType( + targetValue.asClass().name() + ); + } + } + + final AnnotationInstance elementCollectionAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( JPADotNames.ELEMENT_COLLECTION ); + if ( elementCollectionAnnotation != null ) { + final AnnotationValue targetClassValue = elementCollectionAnnotation.value( "targetClass" ); + if ( targetClassValue != null ) { + return (ClassDescriptor) pluralAttribute.getContext().getJavaTypeDescriptorRepository().getType( + targetClassValue.asClass().name() + ); + } + } + + return (ClassDescriptor) inferredElementType; + } + + private EmbeddableTypeMetadata buildEmbeddedMetadata(PluralAttribute pluralAttribute, ClassDescriptor javaType) { + final boolean isMap = pluralAttribute.getPluralAttributeNature() == PluralAttributeNature.MAP; + final AttributeRole role = isMap + ? pluralAttribute.getRole().append( "value" ) + : pluralAttribute.getRole().append( "element" ); + final AttributePath path = isMap + ? pluralAttribute.getPath().append( "value" ) + : pluralAttribute.getPath(); + + // we pass `this` (as EmbeddedContainer) in order to route calls back properly. + return new EmbeddableTypeMetadata( + javaType, + this, + role, + path, + pluralAttribute.getAccessType(), + pluralAttribute.getAccessorStrategy(), + pluralAttribute.getContext() + ); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return javaType; + } + + @Override + public PluralAttributeElementNature getElementNature() { + return PluralAttributeElementNature.AGGREGATE; + } + + @Override + public AttributeTypeResolver getTypeResolver() { + return typeResolver; + } + + public EmbeddableTypeMetadata getEmbeddableTypeMetadata() { + return embeddableTypeMetadata; + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // EmbeddedContainer impl + + @Override + public MemberDescriptor getBackingMember() { + return pluralAttribute.getBackingMember(); + } + + @Override + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath) { + return pluralAttribute.getContainer().locateConversionInfo( attributePath ); + } + + @Override + public AttributeOverride locateAttributeOverride(AttributePath attributePath) { + return pluralAttribute.getContainer().locateAttributeOverride( attributePath ); + } + + @Override + public AssociationOverride locateAssociationOverride(AttributePath attributePath) { + return pluralAttribute.getContainer().locateAssociationOverride( attributePath ); + } + + @Override + public NaturalIdMutability getContainerNaturalIdMutability() { + return null; + } + + @Override + public boolean getContainerOptionality() { + return false; + } + + @Override + public boolean getContainerUpdatability() { + return false; + } + + @Override + public boolean getContainerInsertability() { + return false; + } + + @Override + public void registerConverter(AttributePath attributePath, AttributeConversionInfo conversionInfo) { + pluralAttribute.getContainer().registerConverter( attributePath, conversionInfo ); + } + + @Override + public void registerAttributeOverride(AttributePath attributePath, AttributeOverride override) { + pluralAttribute.getContainer().registerAttributeOverride( attributePath, override ); + } + + @Override + public void registerAssociationOverride(AttributePath attributePath, AssociationOverride override) { + pluralAttribute.getContainer().registerAssociationOverride( attributePath, override ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsEntity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsEntity.java new file mode 100644 index 000000000000..7a683a304e91 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeElementDetailsEntity.java @@ -0,0 +1,143 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeElementDetailsEntity implements PluralAttributeElementDetails { + private final ClassDescriptor javaType; + private final PluralAttributeElementNature elementNature; + private final AttributeTypeResolver typeResolver; + + public PluralAttributeElementDetailsEntity( + PluralAttribute pluralAttribute, + JavaTypeDescriptor inferredElementType) { + this.javaType = determineJavaType( pluralAttribute, inferredElementType ); + + if ( this.javaType == null ) { + throw pluralAttribute.getContext().makeMappingException( + "Could not determine element type information for plural attribute : " + + pluralAttribute.getBackingMember().toString() + ); + } + + this.elementNature = decodeElementNature( pluralAttribute ); + this.typeResolver = buildTypeResolver( pluralAttribute, javaType ); + } + + private ClassDescriptor determineJavaType( + PluralAttribute pluralAttribute, + JavaTypeDescriptor inferredElementType) { + + // NOTE : ClassDescriptor because JPA says an entity must be a class, not an interface + + final AnnotationInstance targetAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( HibernateDotNames.TARGET ); + if ( targetAnnotation != null ) { + final AnnotationValue targetValue = targetAnnotation.value(); + if ( targetValue != null ) { + return (ClassDescriptor) pluralAttribute.getContext().getJavaTypeDescriptorRepository().getType( + targetValue.asClass().name() + ); + } + } + + final AnnotationInstance oneToManyAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( JPADotNames.ONE_TO_MANY ); + if ( oneToManyAnnotation != null ) { + final AnnotationValue targetClassValue = oneToManyAnnotation.value( "targetEntity" ); + if ( targetClassValue != null ) { + return (ClassDescriptor) pluralAttribute.getContext().getJavaTypeDescriptorRepository().getType( + targetClassValue.asClass().name() + ); + } + } + + final AnnotationInstance manyToManyAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( JPADotNames.MANY_TO_MANY ); + if ( manyToManyAnnotation != null ) { + final AnnotationValue targetClassValue = manyToManyAnnotation.value( "targetEntity" ); + if ( targetClassValue != null ) { + return (ClassDescriptor) pluralAttribute.getContext().getJavaTypeDescriptorRepository().getType( + targetClassValue.asClass().name() + ); + } + } + + return (ClassDescriptor) inferredElementType; + } + + private PluralAttributeElementNature decodeElementNature(PluralAttribute pluralAttribute) { + switch ( pluralAttribute.getNature() ) { + case MANY_TO_ANY: { + return PluralAttributeElementNature.MANY_TO_ANY; + } + case MANY_TO_MANY: { + return PluralAttributeElementNature.MANY_TO_MANY; + } + case ONE_TO_MANY: { + return PluralAttributeElementNature.ONE_TO_MANY; + } + default: { + throw pluralAttribute.getContext().makeMappingException( + "Unexpected plural attribute nature : " + pluralAttribute.getNature() + ); + } + } + } + + private AttributeTypeResolver buildTypeResolver(PluralAttribute pluralAttribute, ClassDescriptor javaType) { + // todo : No idea what this should be for entities : return the entity name as type name? return no type name? + return null; + } + + @Override + public JavaTypeDescriptor getJavaType() { + return javaType; + } + + @Override + public PluralAttributeElementNature getElementNature() { + return elementNature; + } + + @Override + public AttributeTypeResolver getTypeResolver() { + return typeResolver; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetails.java new file mode 100644 index 000000000000..0950428da253 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetails.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * Presents metadata about the elements of a plural attribute. + *

      + * Note that this is actually only valid for persistent lists and maps. For + * all other plural attribute natures, + * + * @author Steve Ebersole + */ +public interface PluralAttributeIndexDetails { + /** + * Get the descriptor for the Java type of the collection index. + * + * @return The descriptor for the Java type of the collection index. + */ + public JavaTypeDescriptor getJavaType(); + + /** + * Get the nature of the collection index. To a large degree, this is + * used to know what further, more specific type-casts can be performed. + * + * @return The nature of the collection index + */ + public PluralAttributeIndexNature getIndexNature(); + + /** + * Get the type resolver for the collection index. + * + * @return The type resolver for the collection index. + */ + public AttributeTypeResolver getTypeResolver(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyBasic.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyBasic.java new file mode 100644 index 000000000000..08ad2fa455a4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyBasic.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeIndexDetailsMapKeyBasic extends AbstractPluralAttributeIndexDetailsMapKey { + private final AnnotationInstance mapKeyColumnAnnotation; + + public PluralAttributeIndexDetailsMapKeyBasic( + PluralAttribute pluralAttribute, + MemberDescriptor backingMember, + JavaTypeDescriptor resolvedMapKeyType, + AnnotationInstance mapKeyColumnAnnotation) { + super( pluralAttribute, backingMember, resolvedMapKeyType ); + this.mapKeyColumnAnnotation = mapKeyColumnAnnotation; + } + + public AnnotationInstance getMapKeyColumnAnnotation() { + return mapKeyColumnAnnotation; + } + + @Override + public PluralAttributeIndexNature getIndexNature() { + return PluralAttributeIndexNature.BASIC; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyEmbedded.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyEmbedded.java new file mode 100644 index 000000000000..3e5946916463 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyEmbedded.java @@ -0,0 +1,129 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.entity.EmbeddableTypeMetadata; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeIndexDetailsMapKeyEmbedded + extends AbstractPluralAttributeIndexDetailsMapKey + implements EmbeddedContainer { + + private final PluralAttribute pluralAttribute; + private final EmbeddableTypeMetadata embeddableTypeMetadata; + + public PluralAttributeIndexDetailsMapKeyEmbedded( + PluralAttribute pluralAttribute, + MemberDescriptor backingMember, + JavaTypeDescriptor resolvedMapKeyType) { + super( pluralAttribute, backingMember, resolvedMapKeyType ); + this.pluralAttribute = pluralAttribute; + + // we pass `this` (as EmbeddedContainer) in order to route calls back properly. + this.embeddableTypeMetadata = new EmbeddableTypeMetadata( + resolvedMapKeyType, + this, + pluralAttribute.getRole().append( "key" ), + pluralAttribute.getPath().append( "key" ), + pluralAttribute.getAccessType(), + pluralAttribute.getAccessorStrategy(), + pluralAttribute.getContext() + ); + } + + public EmbeddableTypeMetadata getEmbeddableTypeMetadata() { + return embeddableTypeMetadata; + } + + @Override + public PluralAttributeIndexNature getIndexNature() { + return PluralAttributeIndexNature.AGGREGATE; + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // EmbeddedContainer impl + + @Override + public MemberDescriptor getBackingMember() { + return pluralAttribute.getBackingMember(); + } + + @Override + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath) { + return pluralAttribute.getContainer().locateConversionInfo( attributePath ); + } + + @Override + public AttributeOverride locateAttributeOverride(AttributePath attributePath) { + return pluralAttribute.getContainer().locateAttributeOverride( attributePath ); + } + + @Override + public AssociationOverride locateAssociationOverride(AttributePath attributePath) { + return pluralAttribute.getContainer().locateAssociationOverride( attributePath ); + } + + @Override + public NaturalIdMutability getContainerNaturalIdMutability() { + return null; + } + + @Override + public boolean getContainerOptionality() { + return false; + } + + @Override + public boolean getContainerUpdatability() { + return false; + } + + @Override + public boolean getContainerInsertability() { + return false; + } + + @Override + public void registerConverter(AttributePath attributePath, AttributeConversionInfo conversionInfo) { + pluralAttribute.getContainer().registerConverter( attributePath, conversionInfo ); + } + + @Override + public void registerAttributeOverride(AttributePath attributePath, AttributeOverride override) { + pluralAttribute.getContainer().registerAttributeOverride( attributePath, override ); + } + + @Override + public void registerAssociationOverride(AttributePath attributePath, AssociationOverride override) { + pluralAttribute.getContainer().registerAssociationOverride( attributePath, override ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyEntityAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyEntityAttribute.java new file mode 100644 index 000000000000..779a6d35b598 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsMapKeyEntityAttribute.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeIndexDetailsMapKeyEntityAttribute extends AbstractPluralAttributeIndexDetailsMapKey { + private final String referencedAttributeName; + + public PluralAttributeIndexDetailsMapKeyEntityAttribute( + PluralAttribute pluralAttribute, + MemberDescriptor backingMember, + JavaTypeDescriptor resolvedMapKeyType, + String referencedAttributeName) { + super( pluralAttribute, backingMember, resolvedMapKeyType ); + this.referencedAttributeName = referencedAttributeName; + } + + public String getReferencedAttributeName() { + return referencedAttributeName; + } + + @Override + public PluralAttributeIndexNature getIndexNature() { + // we don't know until we can resolve the referenced entity attribute + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsSequential.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsSequential.java new file mode 100644 index 000000000000..aba77a4643a8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PluralAttributeIndexDetailsSequential.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.LIST_INDEX_BASE; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ORDER_COLUMN; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeIndexDetailsSequential implements PluralAttributeIndexDetails { + private final PluralAttribute pluralAttribute; + + private final Column orderColumn; + private final int base; + + public PluralAttributeIndexDetailsSequential(PluralAttribute pluralAttribute, MemberDescriptor backingMember) { + this.pluralAttribute = pluralAttribute; + + this.orderColumn = determineOrderColumn( backingMember ); + this.base = determineIndexBase( backingMember ); + } + + private Column determineOrderColumn(MemberDescriptor backingMember) { + final AnnotationInstance orderColumnAnnotation = backingMember.getAnnotations().get( ORDER_COLUMN ); + if ( orderColumnAnnotation == null ) { + return null; + } + return new Column( orderColumnAnnotation ); + } + + private int determineIndexBase(MemberDescriptor backingMember) { + final AnnotationInstance listIndexBase = backingMember.getAnnotations().get( LIST_INDEX_BASE ); + if ( listIndexBase == null ) { + return 0; + } + + final AnnotationValue baseValue = listIndexBase.value(); + if ( baseValue == null ) { + return 0; + } + + return baseValue.asInt(); + } + + public Column getOrderColumn() { + return orderColumn; + } + + public int getBase() { + return base; + } + + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + + @Override + public PluralAttributeIndexNature getIndexNature() { + return PluralAttributeIndexNature.SEQUENTIAL; + } + + @Override + public AttributeTypeResolver getTypeResolver() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PrimaryKeyJoinColumn.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PrimaryKeyJoinColumn.java new file mode 100644 index 000000000000..b321e68d537a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/PrimaryKeyJoinColumn.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Strong Liu + */ +public class PrimaryKeyJoinColumn extends Column { + private String referencedColumnName; + + public PrimaryKeyJoinColumn(AnnotationInstance columnAnnotation) { + super( columnAnnotation ); + } + + @Override + public void applyColumnValues(AnnotationInstance columnAnnotation) { + super.applyColumnValues( columnAnnotation ); + if ( columnAnnotation != null ) { + AnnotationValue nameValue = columnAnnotation.value( "referencedColumnName" ); + if ( nameValue != null ) { + this.referencedColumnName = nameValue.asString(); + } + } + } + + public String getReferencedColumnName() { + return referencedColumnName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/SingularAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/SingularAssociationAttribute.java new file mode 100644 index 000000000000..bfbcbcd50e22 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/SingularAssociationAttribute.java @@ -0,0 +1,265 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.ArrayList; +import java.util.Set; +import javax.persistence.AccessType; +import javax.persistence.CascadeType; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.CompositeAttributeTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.attribute.type.HibernateTypeResolver; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.util.AssociationHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; + +import org.jboss.jandex.AnnotationInstance; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class SingularAssociationAttribute + extends AbstractSingularAttribute + implements FetchableAttribute, AssociationAttribute { + + private final String target; + private final String mappedByAttributeName; + private final Set jpaCascadeTypes; + private final Set hibernateCascadeTypes; + private final boolean isOrphanRemoval; + private final boolean ignoreNotFound; + private final boolean isOptional; + private final boolean isUnWrapProxy; + + private final FetchStyle fetchStyle; + private final boolean isLazy; + + private final AnnotationInstance joinTableAnnotation; + private ArrayList joinColumnValues = new ArrayList(); + private ArrayList inverseJoinColumnValues = new ArrayList(); + + private final String mapsIdAttributeName; + + private final boolean hasPrimaryKeyJoinColumn; + + private AttributeTypeResolver resolver; + + public SingularAssociationAttribute( + ManagedTypeMetadata container, + String attributeName, + AttributePath attributePath, + AttributeRole attributeRole, + MemberDescriptor backingMember, + Nature attributeNature, + AccessType accessType, + String accessorStrategy) { + super( + container, + attributeName, + attributePath, + attributeRole, + backingMember, + attributeNature, + accessType, + accessorStrategy + ); + + final AnnotationInstance associationAnnotation = backingMember.getAnnotations().get( attributeNature.getAnnotationDotName() ); + + this.target = AssociationHelper.INSTANCE.determineTarget( + backingMember, + associationAnnotation, + backingMember.getType().getErasedType(), + getContext() + ); + + this.mappedByAttributeName = AssociationHelper.INSTANCE.determineMappedByAttributeName( associationAnnotation ); + + this.fetchStyle = AssociationHelper.INSTANCE.determineFetchStyle( backingMember ); + this.isLazy = AssociationHelper.INSTANCE.determineWhetherIsLazy( + associationAnnotation, + backingMember.getAnnotations().get( HibernateDotNames.LAZY_TO_ONE ), + backingMember, + fetchStyle, + false + ); + + this.isOptional = AssociationHelper.INSTANCE.determineOptionality( associationAnnotation ); + this.isUnWrapProxy = AssociationHelper.INSTANCE.determineWhetherToUnwrapProxy( backingMember ); + + this.jpaCascadeTypes = AssociationHelper.INSTANCE.determineCascadeTypes( associationAnnotation ); + this.hibernateCascadeTypes = AssociationHelper.INSTANCE.determineHibernateCascadeTypes( backingMember ); + this.isOrphanRemoval = AssociationHelper.INSTANCE.determineOrphanRemoval( associationAnnotation ); + this.ignoreNotFound = AssociationHelper.INSTANCE.determineWhetherToIgnoreNotFound( backingMember ); + + this.mapsIdAttributeName = AssociationHelper.INSTANCE.determineMapsId( + backingMember, + attributeNature, + container.getLocalBindingContext() + ); + + if ( this.mappedByAttributeName == null ) { + // todo : not at all a fan of this mess... + AssociationHelper.INSTANCE.processJoinColumnAnnotations( + backingMember, + joinColumnValues, + getContext() + ); + AssociationHelper.INSTANCE.processJoinTableAnnotations( + backingMember, + joinColumnValues, + inverseJoinColumnValues, + getContext() + ); + this.joinTableAnnotation = AssociationHelper.INSTANCE.extractExplicitJoinTable( + backingMember, + getContext() + ); + } + else { + this.joinTableAnnotation = null; + } + joinColumnValues.trimToSize(); + inverseJoinColumnValues.trimToSize(); + + this.hasPrimaryKeyJoinColumn = backingMember.getAnnotations().containsKey( JPADotNames.PRIMARY_KEY_JOIN_COLUMN ) + || backingMember.getAnnotations().containsKey( JPADotNames.PRIMARY_KEY_JOIN_COLUMNS ); + } + + public String getTargetTypeName() { + return target; + } + + @Override + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + @Override + public boolean isLazy() { + return isLazy; + } + + @Override + public String getMappedByAttributeName() { + return mappedByAttributeName; + } + + @Override + public Set getJpaCascadeTypes() { + return jpaCascadeTypes; + } + + @Override + public Set getHibernateCascadeTypes() { + return hibernateCascadeTypes; + } + + @Override + public boolean isOrphanRemoval() { + return isOrphanRemoval; + } + + @Override + public boolean isIgnoreNotFound() { + return ignoreNotFound; + } + + @Override + public boolean isUnWrapProxy() { + return isUnWrapProxy; + } + + public boolean hasPrimaryKeyJoinColumn() { + return hasPrimaryKeyJoinColumn; + } + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + if ( resolver == null ) { + resolver = getDefaultHibernateTypeResolver(); + } + return resolver; + } + + private AttributeTypeResolver getDefaultHibernateTypeResolver() { + return new CompositeAttributeTypeResolver( + this, + HibernateTypeResolver.createAttributeTypeResolver( this ) + ); + } + + @Override + public boolean isOptional() { + return isOptional; + } + + @Override + public boolean isInsertable() { + // todo : this is configurable right? + return true; + } + + @Override + public boolean isUpdatable() { + // todo : this is configurable right? + return true; + } + + @Override + public boolean isIncludeInOptimisticLocking() { + if ( hasOptimisticLockAnnotation() ) { + return super.isIncludeInOptimisticLocking(); + } + else { + // uh, saywhatnow? + return isInsertable(); + } + } + + @Override + public PropertyGeneration getPropertyGeneration() { + return PropertyGeneration.NEVER; + } + + public AnnotationInstance getJoinTableAnnotation() { + return joinTableAnnotation; + } + + public ArrayList getJoinColumnValues() { + return joinColumnValues; + } + + public ArrayList getInverseJoinColumnValues() { + return inverseJoinColumnValues; + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/SingularAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/SingularAttribute.java new file mode 100644 index 000000000000..c1477f9e90e8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/SingularAttribute.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * Represents a singular persistent attribute. + * + * @author Steve Ebersole + */ +public interface SingularAttribute extends PersistentAttribute { + boolean isId(); + + boolean isVersion(); + + NaturalIdMutability getNaturalIdMutability(); + + AttributeConversionInfo getConversionInfo(); + + public FormulaValue getFormulaValue(); + + public List getColumnValues(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/package.html new file mode 100755 index 000000000000..6f41661c51fe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/package.html @@ -0,0 +1,34 @@ + + + + + +

      + This package contains classes related to mapped attributes and associations of a mapped entity. It also contains the + attribute related source implementations. +

      + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AbstractAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AbstractAttributeTypeResolver.java new file mode 100644 index 000000000000..c023014c3e15 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AbstractAttributeTypeResolver.java @@ -0,0 +1,138 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.TypeDefinition; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public abstract class AbstractAttributeTypeResolver implements AttributeTypeResolver { + private final String name; + private final JavaTypeDescriptor javaType; + private final AnnotationInstance annotation; + private final EntityBindingContext context; + + public AbstractAttributeTypeResolver( + String name, + JavaTypeDescriptor javaType, + AnnotationInstance annotation, + EntityBindingContext context){ + this.name = name; + this.javaType = javaType; + this.annotation = annotation; + this.context = context; + } + + @Override + final public String getExplicitHibernateTypeName() { + String type = getExplicitAnnotatedHibernateTypeName(); + // If the attribute is annotated with a type, use it. Otherwise, + // check for a @TypeDef. + if ( !StringHelper.isEmpty( type ) ) { + return type; + } + else { + return hasTypeDef() ? javaType().getName().toString() : null; + } + } + + @Override + final public String getExplicitAnnotatedHibernateTypeName() { + return resolveHibernateTypeName(); + } + + @Override + final public Map getExplicitHibernateTypeParameters() { + Map result = new HashMap( ); + //this is only use by enum type and serializable blob type, but we put there anyway + // TODO: why? + //result.put( + // DynamicParameterizedType.RETURNED_CLASS, + // javaClass().getName() + //); + if ( StringHelper.isNotEmpty( getExplicitHibernateTypeName() ) ) { + result.putAll( resolveHibernateTypeParameters() ); + } + return result; + } + + protected final TypeDefinition getTypeDefinition() { + return context.getMetadataCollector().getTypeDefinition( + javaType().getName().toString() + ); + } + + protected final boolean hasTypeDef() { + return context.getMetadataCollector().hasTypeDefinition( + javaType().getName().toString() + ); + } + + protected abstract String resolveHibernateTypeName(); + + protected Map resolveHibernateTypeParameters() { + return Collections.emptyMap(); + } + + protected String name() { + return name; + } + + protected JavaTypeDescriptor javaType() { + return javaType; + } + + protected AnnotationInstance annotation() { + return annotation; + } + + protected static AnnotationInstance resolveAnnotationInstance( + Map> annotations, + DotName dotName) { + return JandexHelper.getSingleAnnotation( + annotations, + dotName + ); + } + + protected EntityBindingContext getContext() { + return context; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AttributeTypeResolver.java new file mode 100644 index 000000000000..13670962bec7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AttributeTypeResolver.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Map; + +/** + * Determines explicit Hibernate type information for JPA mapped attributes when additional type information is + * provided via annotations like {@link javax.persistence.Lob}, {@link javax.persistence.Enumerated} and + * {@link javax.persistence.Temporal}. + * + * @author Strong Liu + */ +public interface AttributeTypeResolver { + /** + * @return Returns an explicit hibernate type name in case the mapped attribute has an additional + * {@link org.hibernate.annotations.Type} annotation or an implicit type is given via the use of annotations like + * {@link javax.persistence.Lob}, {@link javax.persistence.Enumerated} and + * {@link javax.persistence.Temporal}. If no annotated types are + * available, checks for type definitions in + * {@link org.hibernate.annotations.TypeDef}. Returns null if none of the + * above are found. + */ + String getExplicitHibernateTypeName(); + + /** + * @return Returns the same type name as + * {@link #getExplicitHibernateTypeName}, but skips the + * {@link org.hibernate.annotations.TypeDef} check. This is mainly for + * {@link CompositeAttributeTypeResolver}, as it needs to check the + * {@link org.hibernate.annotations.TypeDef} only once at the very end if nothing + * is returned by the list of resolvers. + */ + String getExplicitAnnotatedHibernateTypeName(); + + /** + * @return Returns a map of optional type parameters. See {@link #getExplicitHibernateTypeName()}. + */ + Map getExplicitHibernateTypeParameters(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AttributeTypeResolverComposition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AttributeTypeResolverComposition.java new file mode 100644 index 000000000000..d5db74db52f9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/AttributeTypeResolverComposition.java @@ -0,0 +1,104 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; + +/** + * An AttributeTypeResolver that allows aggregation of other + * AttributeTypeResolvers (composition) + * + * @author Steve Ebersole + * @author Strong Liu + * @author Brett Meyer + */ +public class AttributeTypeResolverComposition implements AttributeTypeResolver { + private final String inferredJavaTypeName; + private final AnnotationBindingContext context; + private final List resolvers; + + public AttributeTypeResolverComposition( + JavaTypeDescriptor inferredJavaType, + AnnotationBindingContext context) { + this( inferredJavaType, context, Collections.emptyList() ); + } + + public AttributeTypeResolverComposition( + JavaTypeDescriptor inferredJavaType, + AnnotationBindingContext context, + AttributeTypeResolver... resolvers) { + this( inferredJavaType, context, Arrays.asList( resolvers ) ); + } + + public AttributeTypeResolverComposition( + JavaTypeDescriptor inferredJavaType, + AnnotationBindingContext context, + List resolvers) { + this.inferredJavaTypeName = inferredJavaType.getName().toString(); + this.context = context; + this.resolvers = resolvers; + } + + @Override + public String getExplicitHibernateTypeName() { + final String resolvedType = getExplicitAnnotatedHibernateTypeName(); + if ( resolvedType != null ) { + return resolvedType; + } + + if ( context.getMetadataCollector().hasTypeDefinition( inferredJavaTypeName ) ) { + return inferredJavaTypeName; + } + + return null; + } + + @Override + public String getExplicitAnnotatedHibernateTypeName() { + for ( AttributeTypeResolver resolver : resolvers ) { + final String result = resolver.getExplicitAnnotatedHibernateTypeName(); + if ( result != null ) { + return result; + } + } + return null; + } + + @Override + public Map getExplicitHibernateTypeParameters() { + for ( AttributeTypeResolver resolver : resolvers ) { + final Map result = resolver.getExplicitHibernateTypeParameters(); + if ( result != null && !result.isEmpty() ) { + return result; + } + } + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/CollectionTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/CollectionTypeResolver.java new file mode 100644 index 000000000000..cfc3d518cfd9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/CollectionTypeResolver.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Resolver for finding the Hibernate Type information as indicated for a plural attribute + * via the {@link org.hibernate.annotations.CollectionType} annotation + * + * @author Steve Ebersole + */ +public class CollectionTypeResolver implements AttributeTypeResolver { + private final String explicitTypeName; + private final Map explicitTypeParameters; + + public CollectionTypeResolver(PluralAttribute pluralAttribute) { + final AnnotationInstance collectionTypeAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( HibernateDotNames.COLLECTION_TYPE ); + if ( collectionTypeAnnotation == null ) { + this.explicitTypeName = null; + this.explicitTypeParameters = Collections.emptyMap(); + } + else { + this.explicitTypeName = StringHelper.nullIfEmpty( collectionTypeAnnotation.value( "type" ).asString() ); + if ( explicitTypeName == null ) { + throw pluralAttribute.getContext().makeMappingException( + "Encountered @CollectionType annotation that did not specify type : " + + pluralAttribute.getBackingMember().toString() + ); + } + + final AnnotationInstance[] parameterAnnotations = JandexHelper.extractAnnotationsValue( + collectionTypeAnnotation, + "parameters" + ); + if ( parameterAnnotations == null || parameterAnnotations.length == 0 ) { + this.explicitTypeParameters = Collections.emptyMap(); + } + else { + this.explicitTypeParameters = new HashMap(); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + this.explicitTypeParameters.put( + parameterAnnotation.value( "name" ).asString(), + parameterAnnotation.value( "value" ).asString() + ); + } + } + } + } + + @Override + public String getExplicitHibernateTypeName() { + return explicitTypeName; + } + + @Override + public String getExplicitAnnotatedHibernateTypeName() { + return explicitTypeName; + } + + @Override + public Map getExplicitHibernateTypeParameters() { + return explicitTypeParameters; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/CompositeAttributeTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/CompositeAttributeTypeResolver.java new file mode 100644 index 000000000000..6c3639ca8ad7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/CompositeAttributeTypeResolver.java @@ -0,0 +1,104 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; + +/** + * @author Strong Liu + * @author Brett Meyer + */ +public class CompositeAttributeTypeResolver implements AttributeTypeResolver { + private final AbstractPersistentAttribute persistentAttribute; + private List resolvers = new ArrayList(); + private AttributeTypeResolver theResolver; + + public CompositeAttributeTypeResolver(AbstractPersistentAttribute persistentAttribute, + AttributeTypeResolver... resolvers) { + this.persistentAttribute = persistentAttribute; + this.resolvers.addAll( Arrays.asList( resolvers ) ); + } + + public void addHibernateTypeResolver(AttributeTypeResolver resolver) { + if ( resolver == null ) { + throw new AssertionFailure( "The Given AttributeTypeResolver is null." ); + } + resolvers.add( resolver ); + } + + @Override + public String getExplicitHibernateTypeName() { + String type = getExplicitAnnotatedHibernateTypeName(); + if ( StringHelper.isNotEmpty( type ) ) { + return type; + } + + // todo : isn't this kind of the anti-thesis of an *explicit* name? + final String attributeTypeName = persistentAttribute.getBackingMember().getType().getErasedType().getName().toString(); + if ( persistentAttribute.getContext().getMetadataCollector().hasTypeDefinition( attributeTypeName ) ) { + return attributeTypeName; + } + + return null; + } + + @Override + public String getExplicitAnnotatedHibernateTypeName() { + if ( theResolver != null ) { + return theResolver.getExplicitAnnotatedHibernateTypeName(); + } + for ( AttributeTypeResolver resolver : resolvers ) { + String type = resolver.getExplicitAnnotatedHibernateTypeName(); + if ( StringHelper.isNotEmpty( type ) ) { + theResolver = resolver; + return type; + } + } + return null; + } + + @Override + public Map getExplicitHibernateTypeParameters() { + if ( theResolver != null ) { + return theResolver.getExplicitHibernateTypeParameters(); + } + for ( AttributeTypeResolver resolver : resolvers ) { + Map parameters = resolver.getExplicitHibernateTypeParameters(); + if ( CollectionHelper.isNotEmpty( parameters ) ) { + return parameters; + } + } + return Collections.EMPTY_MAP; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/EnumeratedTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/EnumeratedTypeResolver.java new file mode 100644 index 000000000000..55fd4f38cf97 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/EnumeratedTypeResolver.java @@ -0,0 +1,159 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.AnnotationException; +import org.hibernate.metamodel.reflite.internal.ModifierUtils; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.type.EnumType; +import org.hibernate.usertype.DynamicParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class EnumeratedTypeResolver extends AbstractAttributeTypeResolver { + + public static EnumeratedTypeResolver createAttributeTypeResolver(AbstractPersistentAttribute attribute) { + return new EnumeratedTypeResolver( + attribute.getName(), + attribute.getBackingMember().getType().getErasedType(), + attribute.getBackingMember().getAnnotations().get( JPADotNames.ENUMERATED ), + attribute.getContext() + ); + } + + public static EnumeratedTypeResolver createCollectionElementTypeResolver(PluralAttribute pluralAttribute, JavaTypeDescriptor elementType) { + return new EnumeratedTypeResolver( + pluralAttribute.getName(), + elementType, + pluralAttribute.getBackingMember().getAnnotations().get( JPADotNames.ENUMERATED ), + pluralAttribute.getContext() + ); + } + + public static EnumeratedTypeResolver createCollectionIndexTypeResolver(PluralAttribute pluralAttribute, JavaTypeDescriptor mapKeyType) { + return new EnumeratedTypeResolver( + pluralAttribute.getName(), + mapKeyType, + pluralAttribute.getBackingMember().getAnnotations().get( JPADotNames.MAP_KEY_ENUMERATED ), + pluralAttribute.getContext() + ); + } + + private final String typeName; + private final Map typeParameters; + + private EnumeratedTypeResolver( + String name, + JavaTypeDescriptor javaType, + AnnotationInstance annotation, + EntityBindingContext context) { + super( name, javaType, annotation, context ); + + final boolean isEnum = ModifierUtils.isEnum( javaType ); + if ( !isEnum ) { + if ( annotation != null ) { + throw new AnnotationException( + String.format( + "Attribute %s is not a enumerated type, but has %s annotation.", + name(), + annotation.name().toString() + ) + ); + } + + this.typeName = null; + this.typeParameters = Collections.emptyMap(); + } + else { + if ( annotation != null ) { + this.typeName = EnumType.class.getName(); + this.typeParameters = determineTypeParameters( annotation ); + } + else { + final TypeDefinition typeDefinition = getTypeDefinition(); + if ( typeDefinition != null ) { + this.typeName = typeDefinition.getTypeImplementorClass().getName(); + this.typeParameters = determineTypeParameters( null ); + if ( typeDefinition.getParameters() != null + && !typeDefinition.getParameters().isEmpty() ) { + typeParameters.putAll( typeDefinition.getParameters() ); + } + } + else { + this.typeName = EnumType.class.getName(); + this.typeParameters = determineTypeParameters( null ); + } + } + } + } + + private Map determineTypeParameters(AnnotationInstance annotation) { + javax.persistence.EnumType enumType = javax.persistence.EnumType.ORDINAL; + if ( annotation != null ) { + final AnnotationValue enumTypeValue = annotation.value(); + if ( enumTypeValue != null ) { + enumType = javax.persistence.EnumType.valueOf( enumTypeValue.asEnum() ); + } + } + + HashMap typeParameters = new HashMap(); + if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) { + typeParameters.put( EnumType.TYPE, String.valueOf( java.sql.Types.INTEGER ) ); + typeParameters.put( EnumType.NAMED, String.valueOf( false ) ); + } + else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) { + typeParameters.put( EnumType.TYPE, String.valueOf( java.sql.Types.VARCHAR ) ); + typeParameters.put( EnumType.NAMED, String.valueOf( true ) ); + } + typeParameters.put( EnumType.ENUM, javaType().getName().toString() ); + // todo : this may be trouble. doesn't this expect the the Class reference? + typeParameters.put( DynamicParameterizedType.RETURNED_CLASS, javaType().getName().toString() ); + return typeParameters; + } + + @Override + public String resolveHibernateTypeName() { + return typeName; + } + + @Override + protected Map resolveHibernateTypeParameters() { + return typeParameters; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/ExplicitTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/ExplicitTypeResolver.java new file mode 100644 index 000000000000..7cd3d0253cd1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/ExplicitTypeResolver.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Collections; +import java.util.Map; + +/** + * Type resolver where we completely expect an explicit type. + * + * @author Steve Ebersole + */ +public class ExplicitTypeResolver implements AttributeTypeResolver { + private final String typeName; + private final Map typeParameters; + + public ExplicitTypeResolver(String typeName) { + this( typeName, Collections.emptyMap() ); + } + + public ExplicitTypeResolver(String typeName, Map typeParameters) { + this.typeName = typeName; + this.typeParameters = typeParameters; + } + + @Override + public String getExplicitHibernateTypeName() { + return typeName; + } + + @Override + public String getExplicitAnnotatedHibernateTypeName() { + return typeName; + } + + @Override + public Map getExplicitHibernateTypeParameters() { + return typeParameters; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/HibernateTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/HibernateTypeResolver.java new file mode 100644 index 000000000000..c6d580f4a677 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/HibernateTypeResolver.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.usertype.DynamicParameterizedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * Type Resolver which checks {@link org.hibernate.annotations.Type} to find the type info. + * + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class HibernateTypeResolver extends AbstractAttributeTypeResolver { + private final String typeName; + + public static HibernateTypeResolver createAttributeTypeResolver(AbstractPersistentAttribute attribute) { + return new HibernateTypeResolver( + attribute.getName(), + attribute.getBackingMember().getType().getErasedType(), + attribute.getBackingMember().getAnnotations().get( HibernateDotNames.TYPE ), + attribute.getContext() + ); + } + + public static HibernateTypeResolver createCollectionElementTypeResolver(PluralAttribute pluralAttribute, JavaTypeDescriptor elementType) { + return new HibernateTypeResolver( + pluralAttribute.getName(), + elementType, + pluralAttribute.getBackingMember().getAnnotations().get( HibernateDotNames.TYPE ), + pluralAttribute.getContext() + ); + } + + public static HibernateTypeResolver createCollectionIndexTypeResolver(PluralAttribute pluralAttribute, JavaTypeDescriptor mapKeyType) { + // todo : should also handle @MapKeyClass here.. + // todo : even @MapKey since it would indicate a type by the reference attribute + final AnnotationInstance mapKeyTypeAnnotation = pluralAttribute.getBackingMember() + .getAnnotations() + .get( HibernateDotNames.MAP_KEY_TYPE ); + final AnnotationInstance typeAnnotation = mapKeyTypeAnnotation == null + ? null + : JandexHelper.extractAnnotationValue( mapKeyTypeAnnotation, "value" ); + return new HibernateTypeResolver( + pluralAttribute.getName(), + mapKeyType, + typeAnnotation, + pluralAttribute.getContext() + ); + } + + private HibernateTypeResolver( + String name, + JavaTypeDescriptor javaType, + AnnotationInstance annotation, + EntityBindingContext context) { + super( name, javaType, annotation, context ); + + if ( annotation != null ) { + this.typeName = JandexHelper.getValue( + annotation, + "type", + String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) + ); + } + else { + this.typeName = null; + } + } + + @Override + protected String resolveHibernateTypeName() { + return typeName; + } + + @Override + protected Map resolveHibernateTypeParameters() { + if ( annotation() != null ) { + AnnotationValue parameterAnnotationValue = annotation().value( "parameters" ); + if ( parameterAnnotationValue != null ) { + AnnotationInstance[] parameterAnnotations = parameterAnnotationValue.asNestedArray(); + final HashMap typeParameters = new HashMap( parameterAnnotations.length ); + for ( AnnotationInstance parameterAnnotationInstance : parameterAnnotations ) { + typeParameters.put( + JandexHelper.getValue( parameterAnnotationInstance, "name", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ), + JandexHelper.getValue( parameterAnnotationInstance, "value", String.class, + getContext().getServiceRegistry().getService( ClassLoaderService.class ) ) + ); + } + return typeParameters; + } + else if ( typeName != null && !hasTypeDef() ) { + try { + final Class typeClass = + getContext().getServiceRegistry().getService( ClassLoaderService.class ).classForName( typeName ); + if ( DynamicParameterizedType.class.isAssignableFrom( typeClass ) ) { + return Collections.singletonMap( + DynamicParameterizedType.RETURNED_CLASS, + javaType().getName().toString() + ); + } + } + catch (ClassLoadingException ex ) { + // ignore + } + } + } + + return Collections.emptyMap(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/LobTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/LobTypeResolver.java new file mode 100644 index 000000000000..e78e524f65d1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/LobTypeResolver.java @@ -0,0 +1,242 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import java.io.Serializable; +import java.sql.Blob; +import java.sql.Clob; +import java.util.Collections; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.type.CharacterArrayClobType; +import org.hibernate.type.PrimitiveCharacterArrayClobType; +import org.hibernate.type.SerializableToBlobType; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.WrappedMaterializedBlobType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + * @author Steve Ebersole + */ +public class LobTypeResolver extends AbstractAttributeTypeResolver { + public static LobTypeResolver createAttributeTypeResolve(AbstractPersistentAttribute attribute) { + return new LobTypeResolver( + attribute.getName(), + attribute.getBackingMember().getType().getErasedType(), + attribute.getBackingMember().getAnnotations().get( JPADotNames.LOB ), + attribute.getContext() + ); + } + + public static LobTypeResolver createCollectionElementTypeResolve(PluralAttribute pluralAttribute, JavaTypeDescriptor elementType) { + return new LobTypeResolver( + pluralAttribute.getName(), + elementType, + pluralAttribute.getBackingMember().getAnnotations().get( JPADotNames.LOB ), + pluralAttribute.getContext() + ); + } + + + private final String impliedTypeName; + + private LobTypeResolver( + String name, + JavaTypeDescriptor javaType, + AnnotationInstance annotation, + EntityBindingContext context) { + super( name, javaType, annotation, context ); + + this.impliedTypeName = doResolve(); + } + + @Override + public String resolveHibernateTypeName() { + return impliedTypeName; + } + + @Override + protected Map resolveHibernateTypeParameters() { + if ( SerializableToBlobType.class.getName().equals( getExplicitHibernateTypeName() ) ) { + return Collections.singletonMap( SerializableToBlobType.CLASS_NAME, javaType().getName().toString() ); + } + else { + return super.resolveHibernateTypeParameters(); + } + } + + public String doResolve() { + if ( annotation() == null ) { + //only check attributes annotated with @Lob + return null; + } + + if ( clobType().isAssignableFrom( javaType() ) ) { + return StandardBasicTypes.CLOB.getName(); + } + + if ( blobType().isAssignableFrom( javaType() ) ) { + return StandardBasicTypes.BLOB.getName(); + } + + if ( stringType().isAssignableFrom( javaType() ) ) { + return StandardBasicTypes.MATERIALIZED_CLOB.getName(); + } + + if ( characterArrayType().isAssignableFrom( javaType() ) ) { + return CharacterArrayClobType.class.getName(); + } + + if ( charArrayType().isAssignableFrom( javaType() ) ) { + return PrimitiveCharacterArrayClobType.class.getName(); + } + + if ( byteWrapperArrayType().isAssignableFrom( javaType() ) ) { + return WrappedMaterializedBlobType.class.getName(); + } + + if ( byteArrayType().isAssignableFrom( javaType() ) ) { + return StandardBasicTypes.MATERIALIZED_BLOB.getName(); + } + + if ( serializableType().isAssignableFrom( javaType() ) ) { + return SerializableToBlobType.class.getName(); + } + + return "blob"; + } + + private static JavaTypeDescriptor clobDescriptor; + + private JavaTypeDescriptor clobType() { + if ( clobDescriptor == null ) { + clobDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( Clob.class.getName() ) + ); + } + return clobDescriptor; + } + + private static JavaTypeDescriptor blobDescriptor; + + private JavaTypeDescriptor blobType() { + if ( blobDescriptor == null ) { + blobDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( Blob.class.getName() ) + ); + } + return blobDescriptor; + } + + + private static JavaTypeDescriptor stringDescriptor; + + private JavaTypeDescriptor stringType() { + if ( stringDescriptor == null ) { + stringDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( String.class.getName() ) + ); + } + return stringDescriptor; + } + + + private static JavaTypeDescriptor characterArrayDescriptor; + + private JavaTypeDescriptor characterArrayType() { + if ( characterArrayDescriptor == null ) { + characterArrayDescriptor = getContext().getJavaTypeDescriptorRepository().arrayType( + getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( Character.class.getName() ) + ) + ); + } + return characterArrayDescriptor; + } + + + private static JavaTypeDescriptor charArrayDescriptor; + + private JavaTypeDescriptor charArrayType() { + if ( charArrayDescriptor == null ) { + charArrayDescriptor = getContext().getJavaTypeDescriptorRepository().arrayType( + getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( char.class.getName() ) + ) + ); + } + return charArrayDescriptor; + } + + + private static JavaTypeDescriptor byteWrapperArrayDescriptor; + + private JavaTypeDescriptor byteWrapperArrayType() { + if ( byteWrapperArrayDescriptor == null ) { + byteWrapperArrayDescriptor = getContext().getJavaTypeDescriptorRepository().arrayType( + getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( Byte.class.getName() ) + ) + ); + } + return byteWrapperArrayDescriptor; + } + + + private static JavaTypeDescriptor byteArrayDescriptor; + + private JavaTypeDescriptor byteArrayType() { + if ( byteArrayDescriptor == null ) { + byteArrayDescriptor = getContext().getJavaTypeDescriptorRepository().arrayType( + getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( byte.class.getName() ) + ) + ); + } + return byteArrayDescriptor; + } + + + private static JavaTypeDescriptor serializableDescriptor; + + private JavaTypeDescriptor serializableType() { + if ( serializableDescriptor == null ) { + serializableDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( Serializable.class.getName() ) + ); + } + return serializableDescriptor; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/TemporalTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/TemporalTypeResolver.java new file mode 100644 index 000000000000..17a45f96413f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/TemporalTypeResolver.java @@ -0,0 +1,251 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.internal.annotations.attribute.type; + +import javax.persistence.TemporalType; + +import org.hibernate.annotations.SourceType; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.type.StandardBasicTypes; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + * @author Brett Meyer + * @author Gail Badner + */ +public class TemporalTypeResolver extends AbstractAttributeTypeResolver { + private final SourceType versionSourceType; + + public static TemporalTypeResolver createAttributeTypeResolver(BasicAttribute attribute) { + return new TemporalTypeResolver( + attribute.getName(), + attribute.getBackingMember().getType().getErasedType(), + attribute.getBackingMember().getAnnotations().get( JPADotNames.TEMPORAL ), + attribute.getContext(), + attribute.getVersionSourceType() + ); + } + + public static TemporalTypeResolver createCollectionElementTypeResolver(PluralAttribute attribute, JavaTypeDescriptor elementType) { + return new TemporalTypeResolver( + attribute.getName(), + elementType, + attribute.getBackingMember().getAnnotations().get( JPADotNames.TEMPORAL ), + attribute.getContext(), + null + ); + } + + public static TemporalTypeResolver createCollectionIndexTypeResolver(PluralAttribute attribute, JavaTypeDescriptor mapKeyType) { + return new TemporalTypeResolver( + attribute.getName(), + mapKeyType, + attribute.getBackingMember().getAnnotations().get( JPADotNames.MAP_KEY_TEMPORAL ), + attribute.getContext(), + null + ); + } + + private final TemporalNature nature; + + private TemporalTypeResolver( + String name, + JavaTypeDescriptor javaType, + AnnotationInstance annotation, + EntityBindingContext context, + SourceType versionSourceType) { + super( name, javaType, annotation, context ); + + this.versionSourceType = versionSourceType; + + this.nature = interpretNature( javaType ); + if ( nature == TemporalNature.NONE ) { + if ( annotation != null ) { + throw context.makeMappingException( + '@' + annotation.name().toString() + " should only be used on temporal values : " + name() + ); + } + } + } + + private TemporalNature interpretNature(JavaTypeDescriptor javaType) { + if ( calendarType().isAssignableFrom( javaType ) ) { + return TemporalNature.CALENDAR; + } + else if ( jdbcTimestampType().isAssignableFrom( javaType ) ) { + return TemporalNature.JDBC_TIMESTAMP; + } + else if ( jdbcTimeType().isAssignableFrom( javaType ) ) { + return TemporalNature.JDBC_TIME; + } + else if ( jdbcDateType().isAssignableFrom( javaType ) ) { + return TemporalNature.JDBC_DATE; + } + else if ( jdkDateType().isAssignableFrom( javaType ) ) { + return TemporalNature.JDK_DATE; + } + else { + return TemporalNature.NONE; + } + } + + private JavaTypeDescriptor calendarDescriptor; + + private JavaTypeDescriptor calendarType() { + if ( calendarDescriptor == null ) { + calendarDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( java.util.Calendar.class.getName() ) + ); + } + return calendarDescriptor; + } + + private JavaTypeDescriptor jdbcTimestampDescriptor; + + private JavaTypeDescriptor jdbcTimestampType() { + if ( jdbcTimestampDescriptor == null ) { + jdbcTimestampDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( java.sql.Timestamp.class.getName() ) + ); + } + return jdbcTimestampDescriptor; + } + + private JavaTypeDescriptor jdbcTimeDescriptor; + + private JavaTypeDescriptor jdbcTimeType() { + if ( jdbcTimeDescriptor == null ) { + jdbcTimeDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( java.sql.Time.class.getName() ) + ); + } + return jdbcTimeDescriptor; + } + + private JavaTypeDescriptor jdbcDateDescriptor; + + private JavaTypeDescriptor jdbcDateType() { + if ( jdbcDateDescriptor == null ) { + jdbcDateDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( java.sql.Date.class.getName() ) + ); + } + return jdbcDateDescriptor; + } + + private JavaTypeDescriptor jdkDateDescriptor; + + private JavaTypeDescriptor jdkDateType() { + if ( jdkDateDescriptor == null ) { + jdkDateDescriptor = getContext().getJavaTypeDescriptorRepository().getType( + DotName.createSimple( java.util.Date.class.getName() ) + ); + } + return jdkDateDescriptor; + } + + @Override + public String resolveHibernateTypeName() { + if ( nature == TemporalNature.NONE ) { + return null; + } + + if ( versionSourceType != null ) { + return versionSourceType.typeName(); + } + + if ( annotation() == null ) { + // Although JPA 2.1 states that @Temporal is required on + // Date/Calendar attributes, we allow it to be left off in order + // to support legacy mappings using the following mappings: + // java.util.Calendar -> CalendarType + // java.sql.Date -> DateType + // java.sql.Time -> TimeType + // java.util.Date -> TimestampType + // java.sql.Timestamp -> TimestampType + switch ( nature ) { + case CALENDAR: { + return StandardBasicTypes.CALENDAR.getName(); + } + case JDBC_DATE: { + return StandardBasicTypes.DATE.getName(); + } + case JDBC_TIME: { + return StandardBasicTypes.TIME.getName(); + } + case JDK_DATE: + case JDBC_TIMESTAMP: { + return StandardBasicTypes.TIMESTAMP.getName(); + } + default: { + // java is funny sometimes ;) + return null; + } + } + } + else { + final TemporalType temporalType = TemporalType.valueOf( annotation().value().asEnum() ); + final boolean isCalendar = nature == TemporalNature.CALENDAR; + switch ( temporalType ) { + case TIMESTAMP: { + return isCalendar + ? StandardBasicTypes.CALENDAR.getName() + : StandardBasicTypes.TIMESTAMP.getName(); + } + case TIME: { + return isCalendar + ? StandardBasicTypes.CALENDAR_TIME.getName() + : StandardBasicTypes.TIME.getName(); + } + case DATE: { + return isCalendar + ? StandardBasicTypes.CALENDAR_DATE.getName() + : StandardBasicTypes.DATE.getName(); + } + default: { + // java is funny sometimes ;) + return null; + } + } + } + } + + public static enum TemporalNature { + JDK_DATE, + JDBC_DATE, + JDBC_TIME, + JDBC_TIMESTAMP, + CALENDAR, + NONE + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/package.html new file mode 100755 index 000000000000..bff34d014c82 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/attribute/type/package.html @@ -0,0 +1,33 @@ + + + + + +

      + This package contains classes to resolve explicit Hibernate type information for mapped attributes. +

      + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EmbeddableTypeMetadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EmbeddableTypeMetadata.java new file mode 100644 index 000000000000..e82c503f85a8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EmbeddableTypeMetadata.java @@ -0,0 +1,194 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import java.util.Collection; +import javax.persistence.AccessType; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.EmbeddedContainer; +import org.hibernate.metamodel.source.internal.annotations.util.ConverterAndOverridesHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +import org.jboss.jandex.AnnotationInstance; + +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.PARENT; + +/** + * This is called *Embeddable* type metadata to closely follow the JPA + * terminology; just be aware that this more closely models the *Embedded*. + * Generally this is used as a delegate from "composite contexts" such as + * Embedded attributes and plural attributes with Embedded elements/keys. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class EmbeddableTypeMetadata extends ManagedTypeMetadata { + private final EmbeddedContainer container; + private final NaturalIdMutability naturalIdMutability; + private final String parentReferencingAttributeName; + private final String customTuplizerClassName; + + public EmbeddableTypeMetadata( + JavaTypeDescriptor embeddableType, + EmbeddedContainer container, + AttributeRole attributeRoleBase, + AttributePath attributePathBase, + AccessType defaultAccessType, + String defaultAccessorStrategy, + AnnotationBindingContext context) { + super( embeddableType, attributeRoleBase, attributePathBase, defaultAccessType, defaultAccessorStrategy, context ); + + this.container = container; + this.naturalIdMutability = container.getContainerNaturalIdMutability(); + this.parentReferencingAttributeName = decodeParentAnnotation( embeddableType ); + this.customTuplizerClassName = decodeTuplizerAnnotation( container ); + + // the idea here is to collect up class-level annotations and to apply + // the maps from supers + collectConversionInfo(); + collectAttributeOverrides(); + collectAssociationOverrides(); + + collectAttributesIfNeeded(); + } + + private String decodeParentAnnotation(JavaTypeDescriptor embeddableType) { + final Collection parentAnnotations = embeddableType.findAnnotations( PARENT ); + if ( parentAnnotations == null || parentAnnotations.isEmpty() ) { + return null; + } + + if ( parentAnnotations.size() > 1 ) { + throw getLocalBindingContext().makeMappingException( + "Embeddable class contained multiple @Parent annotations; only one is allowed" + ); + } + + final AnnotationInstance parentAnnotation = parentAnnotations.iterator().next(); + return JandexHelper.getPropertyName( parentAnnotation.target() ); + } + + private String decodeTuplizerAnnotation(EmbeddedContainer container) { + // prefer tuplizer defined at the embedded level + { + final AnnotationInstance tuplizerAnnotation = container.getBackingMember().getAnnotations().get( + HibernateDotNames.TUPLIZER + ); + if ( tuplizerAnnotation != null ) { + return tuplizerAnnotation.value( "impl" ).asString(); + } + } + + // The tuplizer on the embeddable (if one) would be covered by this.getCustomTuplizerClassName()... + return super.getCustomTuplizerClassName(); + } + + private void collectConversionInfo() { + } + + private void collectAttributeOverrides() { + ConverterAndOverridesHelper.INSTANCE.processAttributeOverrides( + new AttributePath(), + this, + this, + getLocalBindingContext() + ); + } + + private void collectAssociationOverrides() { + } + + public String getParentReferencingAttributeName() { + return parentReferencingAttributeName; + } + + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public String getCustomTuplizerClassName() { + return customTuplizerClassName; + } + + @Override + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath) { + return container.locateConversionInfo( attributePath ); + } + + @Override + public AttributeOverride locateAttributeOverride(AttributePath attributePath) { + return container.locateAttributeOverride( attributePath ); + } + + @Override + public AssociationOverride locateAssociationOverride(AttributePath attributePath) { + return container.locateAssociationOverride( attributePath ); + } + + @Override + public void registerConverter(AttributePath attributePath, AttributeConversionInfo conversionInfo) { + container.registerConverter( attributePath, conversionInfo ); + } + + @Override + public void registerAttributeOverride(AttributePath attributePath, AttributeOverride override) { + container.registerAttributeOverride( attributePath, override ); + } + + @Override + public void registerAssociationOverride(AttributePath attributePath, AssociationOverride override) { + container.registerAssociationOverride( attributePath, override ); + } + + @Override + public boolean canAttributesBeInsertable() { + return container.getContainerInsertability(); + } + + @Override + @SuppressWarnings("SimplifiableIfStatement") + public boolean canAttributesBeUpdatable() { + if ( naturalIdMutability == NaturalIdMutability.IMMUTABLE ) { + return false; + } + return container.getContainerUpdatability(); + } + + @Override + public NaturalIdMutability getContainerNaturalIdMutability() { + return naturalIdMutability; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EntityBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EntityBindingContext.java new file mode 100644 index 000000000000..22ad78cfc3be --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EntityBindingContext.java @@ -0,0 +1,76 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import org.hibernate.AnnotationException; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.BaseDelegatingBindingContext; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + + +/** + * Annotation version of a local binding context. + * + * @author Steve Ebersole + */ +public class EntityBindingContext + extends BaseDelegatingBindingContext + implements LocalBindingContext, AnnotationBindingContext { + private final AnnotationBindingContext contextDelegate; + private final Origin origin; + + public EntityBindingContext(AnnotationBindingContext contextDelegate, ManagedTypeMetadata source) { + super( contextDelegate ); + this.contextDelegate = contextDelegate; + this.origin = new Origin( SourceType.ANNOTATION, source.getName() ); + } + + public AnnotationBindingContext getBaseContext() { + return contextDelegate; + } + + @Override + public Origin getOrigin() { + return origin; + } + + @Override + public MappingException makeMappingException(String message) { + return new AnnotationException( message, getOrigin() ); + } + + @Override + public MappingException makeMappingException(String message, Exception cause) { + return new AnnotationException( message, cause, getOrigin() ); + } + + @Override + public IdentifierGeneratorDefinition findIdGenerator(String name) { + return contextDelegate.findIdGenerator( name ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EntityTypeMetadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EntityTypeMetadata.java new file mode 100644 index 000000000000..dbb48ebb0168 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/EntityTypeMetadata.java @@ -0,0 +1,554 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ENTITY; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.AccessType; + +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.binder.ForeignKeyDelegate; +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.source.internal.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * Representation of metadata (configured via annotations or orm.xml) attached + * to an Entity. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class EntityTypeMetadata extends IdentifiableTypeMetadata { + private final String explicitEntityName; + private final String customLoaderQueryName; + private final String[] synchronizedTableNames; + private final int batchSize; + private final String customPersister; + private final boolean isDynamicInsert; + private final boolean isDynamicUpdate; + private final boolean isSelectBeforeUpdate; + private final CustomSQL customInsert; + private final CustomSQL customUpdate; + private final CustomSQL customDelete; + private final String discriminatorMatchValue; + private final boolean isLazy; + private final String proxy; + private final ForeignKeyDelegate foreignKeyDelegate; + + private final ClassLoaderService classLoaderService; + + // todo : ??? + private final OnDeleteAction onDeleteAction; + private final List joinedSubclassPrimaryKeyJoinColumnSources; + + + /** + * This form is intended for construction of root Entity. + */ + public EntityTypeMetadata( + JavaTypeDescriptor javaTypeDescriptor, + AccessType defaultAccessType, + AnnotationBindingContext bindingContext) { + super( javaTypeDescriptor, defaultAccessType, true, bindingContext ); + + this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + + this.explicitEntityName = determineExplicitEntityName(); + this.customLoaderQueryName = determineCustomLoader(); + this.synchronizedTableNames = determineSynchronizedTableNames(); + this.batchSize = determineBatchSize(); + + this.customInsert = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_INSERT, + javaTypeDescriptor.getJandexClassInfo().annotations(), + javaTypeDescriptor.getJandexClassInfo() + ); + this.customUpdate = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_UPDATE, + javaTypeDescriptor.getJandexClassInfo().annotations(), + javaTypeDescriptor.getJandexClassInfo() + ); + this.customDelete = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_DELETE, + javaTypeDescriptor.getJandexClassInfo().annotations(), + javaTypeDescriptor.getJandexClassInfo() + ); + + // dynamic insert (see HHH-6397) + final AnnotationInstance dynamicInsertAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.DYNAMIC_INSERT + ); + if ( dynamicInsertAnnotation != null ) { + this.isDynamicInsert = JandexHelper.getValue( + dynamicInsertAnnotation, + "value", + Boolean.class, + classLoaderService + ); + } + else { + this.isDynamicInsert = false; + } + + // dynamic update (see HHH-6398) + final AnnotationInstance dynamicUpdateAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.DYNAMIC_UPDATE + ); + if ( dynamicUpdateAnnotation != null ) { + this.isDynamicUpdate = JandexHelper.getValue( + dynamicUpdateAnnotation, + "value", + Boolean.class, + classLoaderService + ); + } + else { + this.isDynamicUpdate = false; + } + + + // select-before-update (see HHH-6399) + final AnnotationInstance selectBeforeUpdateAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.SELECT_BEFORE_UPDATE + ); + if ( selectBeforeUpdateAnnotation != null ) { + this.isSelectBeforeUpdate = JandexHelper.getValue( + selectBeforeUpdateAnnotation, + "value", + Boolean.class, + classLoaderService + ); + } + else { + this.isSelectBeforeUpdate = false; + } + + // Custom persister + String entityPersisterClass = null; + final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.PERSISTER, + ClassInfo.class + ); + if ( persisterAnnotation != null && persisterAnnotation.value( "impl" ) != null ) { + entityPersisterClass = persisterAnnotation.value( "impl" ).asString(); + } + this.customPersister = entityPersisterClass; + + // Proxy generation + final AnnotationInstance hibernateProxyAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.PROXY + ); + if ( hibernateProxyAnnotation != null ) { + this.isLazy = hibernateProxyAnnotation.value( "lazy" ) == null + || hibernateProxyAnnotation.value( "lazy" ).asBoolean(); + if ( this.isLazy ) { + final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" ); + this.proxy = proxyClassValue == null ? getName() : proxyClassValue.asString(); + } + else { + this.proxy = null; + } + } + else { + // defaults are that it is lazy and that the class itself is the proxy class + this.isLazy = true; + this.proxy = getName(); + } + + + final AnnotationInstance discriminatorValueAnnotation = getJavaTypeDescriptor().findTypeAnnotation( + JPADotNames.DISCRIMINATOR_VALUE + ); + if ( discriminatorValueAnnotation != null ) { + this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString(); + } + else { + this.discriminatorMatchValue = null; + } + + // TODO: bind JPA @ForeignKey? + foreignKeyDelegate = new ForeignKeyDelegate(); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // todo : which (if any) of these to keep? + this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns(); + this.onDeleteAction = determineOnDeleteAction(); + } + + + /** + * This form is intended for construction of Entity subclasses. + */ + public EntityTypeMetadata( + ClassDescriptor javaTypeDescriptor, + IdentifiableTypeMetadata superType, + AccessType defaultAccessType, + AnnotationBindingContext bindingContext) { + super( javaTypeDescriptor, superType, defaultAccessType, bindingContext ); + + this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + + this.explicitEntityName = determineExplicitEntityName(); + this.customLoaderQueryName = determineCustomLoader(); + this.synchronizedTableNames = determineSynchronizedTableNames(); + this.batchSize = determineBatchSize(); + + this.customInsert = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_INSERT, + javaTypeDescriptor.getJandexClassInfo().annotations(), + javaTypeDescriptor.getJandexClassInfo() + ); + this.customUpdate = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_UPDATE, + javaTypeDescriptor.getJandexClassInfo().annotations(), + javaTypeDescriptor.getJandexClassInfo() + ); + this.customDelete = AnnotationParserHelper.processCustomSqlAnnotation( + HibernateDotNames.SQL_DELETE, + javaTypeDescriptor.getJandexClassInfo().annotations(), + javaTypeDescriptor.getJandexClassInfo() + ); + + // dynamic insert (see HHH-6397) + final AnnotationInstance dynamicInsertAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.DYNAMIC_INSERT + ); + if ( dynamicInsertAnnotation != null ) { + this.isDynamicInsert = JandexHelper.getValue( + dynamicInsertAnnotation, + "value", + Boolean.class, + classLoaderService + ); + } + else { + this.isDynamicInsert = false; + } + + // dynamic update (see HHH-6398) + final AnnotationInstance dynamicUpdateAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.DYNAMIC_UPDATE + ); + if ( dynamicUpdateAnnotation != null ) { + this.isDynamicUpdate = JandexHelper.getValue( + dynamicUpdateAnnotation, + "value", + Boolean.class, + classLoaderService + ); + } + else { + this.isDynamicUpdate = false; + } + + + // select-before-update (see HHH-6399) + final AnnotationInstance selectBeforeUpdateAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.SELECT_BEFORE_UPDATE + ); + if ( selectBeforeUpdateAnnotation != null ) { + this.isSelectBeforeUpdate = JandexHelper.getValue( + selectBeforeUpdateAnnotation, + "value", + Boolean.class, + classLoaderService + ); + } + else { + this.isSelectBeforeUpdate = false; + } + + // Custom persister + String entityPersisterClass = null; + final AnnotationInstance persisterAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.PERSISTER, + ClassInfo.class + ); + if ( persisterAnnotation != null && persisterAnnotation.value( "impl" ) != null ) { + entityPersisterClass = persisterAnnotation.value( "impl" ).asString(); + } + this.customPersister = entityPersisterClass; + + // Proxy generation + final AnnotationInstance hibernateProxyAnnotation = JandexHelper.getSingleAnnotation( + javaTypeDescriptor.getJandexClassInfo(), + HibernateDotNames.PROXY + ); + if ( hibernateProxyAnnotation != null ) { + this.isLazy = hibernateProxyAnnotation.value( "lazy" ) == null + || hibernateProxyAnnotation.value( "lazy" ).asBoolean(); + if ( this.isLazy ) { + final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" ); + this.proxy = proxyClassValue == null ? getName() : proxyClassValue.asString(); + } + else { + this.proxy = null; + } + } + else { + // defaults are that it is lazy and that the class itself is the proxy class + this.isLazy = true; + this.proxy = getName(); + } + + + final AnnotationInstance discriminatorValueAnnotation = getJavaTypeDescriptor().findTypeAnnotation( + JPADotNames.DISCRIMINATOR_VALUE + ); + if ( discriminatorValueAnnotation != null ) { + this.discriminatorMatchValue = discriminatorValueAnnotation.value().asString(); + } + else { + this.discriminatorMatchValue = null; + } + + // TODO: bind JPA @ForeignKey? + foreignKeyDelegate = new ForeignKeyDelegate(); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // todo : which (if any) of these to keep? + this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns(); + this.onDeleteAction = determineOnDeleteAction(); + } + + private static AccessType determineAccessType(ClassDescriptor javaTypeDescriptor, AccessType defaultAccessType) { + AccessType accessType = defaultAccessType; + + final AnnotationInstance localAccessAnnotation = javaTypeDescriptor.findLocalTypeAnnotation( JPADotNames.ACCESS ); + if ( localAccessAnnotation != null ) { + accessType = AccessType.valueOf( localAccessAnnotation.value().asEnum() ); + } + + return accessType; + } + + private String determineExplicitEntityName() { + final AnnotationInstance jpaEntityAnnotation = getJavaTypeDescriptor().findLocalTypeAnnotation( ENTITY ); + if ( jpaEntityAnnotation == null ) { + // can this really ever be true here?! + return null; + } + + final AnnotationValue nameValue = jpaEntityAnnotation.value( "name" ); + if ( nameValue == null ) { + return null; + } + + return StringHelper.nullIfEmpty( nameValue.asString() ); + } + + private String determineCustomLoader() { + String customLoader = null; + // Custom sql loader + final AnnotationInstance sqlLoaderAnnotation = getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.LOADER + ); + if ( sqlLoaderAnnotation != null && sqlLoaderAnnotation.target() instanceof ClassInfo) { + customLoader = sqlLoaderAnnotation.value( "namedQuery" ).asString(); + } + return customLoader; + } + + private String[] determineSynchronizedTableNames() { + final AnnotationInstance synchronizeAnnotation = getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.SYNCHRONIZE + ); + if ( synchronizeAnnotation != null ) { + return synchronizeAnnotation.value().asStringArray(); + } + else { + return StringHelper.EMPTY_STRINGS; + } + } + + private int determineBatchSize() { + final AnnotationInstance batchSizeAnnotation = getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.BATCH_SIZE + ); + return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt(); + } + + private OnDeleteAction determineOnDeleteAction() { + final AnnotationInstance onDeleteAnnotation = getJavaTypeDescriptor().findTypeAnnotation( + HibernateDotNames.ON_DELETE + ); + if ( onDeleteAnnotation != null ) { + return JandexHelper.getEnumValue( + onDeleteAnnotation, + "action", + OnDeleteAction.class, + classLoaderService + ); + } + return null; + } + + + public String getExplicitEntityName() { + return explicitEntityName; + } + + public String getEntityName() { + return getJavaTypeDescriptor().getName().local(); + } + + public boolean isDynamicInsert() { + return isDynamicInsert; + } + + public boolean isDynamicUpdate() { + return isDynamicUpdate; + } + + public boolean isSelectBeforeUpdate() { + return isSelectBeforeUpdate; + } + + public String getCustomLoaderQueryName() { + return customLoaderQueryName; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public String[] getSynchronizedTableNames() { + return synchronizedTableNames; + } + + public List getJoinedSubclassPrimaryKeyJoinColumnSources() { + return joinedSubclassPrimaryKeyJoinColumnSources; + } + + public String getCustomPersister() { + return customPersister; + } + + public boolean isLazy() { + return isLazy; + } + + public String getProxy() { + return proxy; + } + + public int getBatchSize() { + return batchSize; + } + + public boolean isEntityRoot() { + return getSuperType() == null; + } + + public String getDiscriminatorMatchValue() { + return discriminatorMatchValue; + } + + + public String getInverseForeignKeyName() { + return foreignKeyDelegate.getInverseForeignKeyName(); + } + public String getExplicitForeignKeyName(){ + return foreignKeyDelegate.getExplicitForeignKeyName(); + } + public boolean createForeignKeyConstraint(){ + return foreignKeyDelegate.createForeignKeyConstraint(); + } + + public OnDeleteAction getOnDeleteAction() { + return onDeleteAction; + } + + + protected List determinePrimaryKeyJoinColumns() { + final AnnotationInstance primaryKeyJoinColumns = getJavaTypeDescriptor().findLocalTypeAnnotation( + JPADotNames.PRIMARY_KEY_JOIN_COLUMNS + ); + final AnnotationInstance primaryKeyJoinColumn = getJavaTypeDescriptor().findLocalTypeAnnotation( + JPADotNames.PRIMARY_KEY_JOIN_COLUMN + ); + + final List results; + if ( primaryKeyJoinColumns != null ) { + AnnotationInstance[] values = primaryKeyJoinColumns.value().asNestedArray(); + results = new ArrayList( values.length ); + for ( final AnnotationInstance annotationInstance : values ) { + results.add( new PrimaryKeyJoinColumn( annotationInstance ) ); + } + } + else if ( primaryKeyJoinColumn != null ) { + results = new ArrayList( 1 ); + results.add( new PrimaryKeyJoinColumn( primaryKeyJoinColumn ) ); + } + else { + results = null; + } + return results; + } + + public boolean hasMultiTenancySourceInformation() { + return getJavaTypeDescriptor().findTypeAnnotation( HibernateDotNames.MULTI_TENANT ) != null + || getJavaTypeDescriptor().findTypeAnnotation( HibernateDotNames.TENANT_COLUMN ) != null + || getJavaTypeDescriptor().findTypeAnnotation( HibernateDotNames.TENANT_FORMULA ) != null; + } + + public boolean containsDiscriminator() { + return getJavaTypeDescriptor().findTypeAnnotation( JPADotNames.DISCRIMINATOR_COLUMN ) != null + || getJavaTypeDescriptor().findTypeAnnotation( HibernateDotNames.DISCRIMINATOR_FORMULA ) != null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/IdType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/IdType.java new file mode 100644 index 000000000000..4ab6c7d371b8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/IdType.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +/** + * An enum for the type of id configuration for an entity. + * + * @author Hardy Ferentschik + */ +public enum IdType { + /** + * single @Id annotation. Corresponds to + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE} + */ + SIMPLE, + + /** + * multiple @Id annotations. Corresponds to + * {@link org.hibernate.id.EntityIdentifierNature#NON_AGGREGATED_COMPOSITE} + */ + NON_AGGREGATED, + + /** + * Indicates encountered {@code @EmbeddedId} annotation. Corresponds to + * {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE} + */ + AGGREGATED, + + /** + * does not contain any identifier mappings + */ + NONE +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/IdentifiableTypeMetadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/IdentifiableTypeMetadata.java new file mode 100644 index 000000000000..bf09efbf0c51 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/IdentifiableTypeMetadata.java @@ -0,0 +1,459 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import javax.persistence.AccessType; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.JpaCallbackSourceImpl; +import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAttribute; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPAListenerHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.internal.jandex.PseudoJpaDotNames; +import org.hibernate.metamodel.source.spi.JpaCallbackSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.Type; +import org.jboss.logging.Logger; + +/** + * Representation of metadata (configured via annotations or orm.xml) attached + * to an Entity or a MappedSuperclass. + * + * @author Steve Ebersole + */ +public class IdentifiableTypeMetadata extends ManagedTypeMetadata { + private static final Logger log = Logger.getLogger( IdentifiableTypeMetadata.class ); + + private IdType idType; + private List identifierAttributes; + private BasicAttribute versionAttribute; + + private final Map conversionInfoMap = new HashMap(); + private final Map attributeOverrideMap = new HashMap(); + private final Map associationOverrideMap = new HashMap(); + + private List collectedJpaCallbackSources; + + /** + * This form is intended for construction of root Entity, and any of + * its MappedSuperclasses + * + * @param javaTypeDescriptor The Entity/MappedSuperclass class descriptor + * @param defaultAccessType The default AccessType for the hierarchy + * @param isRoot Is this the root entity? + * @param bindingContext The context + */ + public IdentifiableTypeMetadata( + JavaTypeDescriptor javaTypeDescriptor, + AccessType defaultAccessType, + boolean isRoot, + AnnotationBindingContext bindingContext) { + super( javaTypeDescriptor, defaultAccessType, isRoot, bindingContext ); + + // the idea here is to collect up class-level annotations and to apply + // the maps from supers + collectConversionInfo(); + collectAttributeOverrides(); + collectAssociationOverrides(); + } + + protected void collectConversionInfo() { + // we only need to do this on root + } + + protected void collectAttributeOverrides() { + // we only need to do this on root + } + + protected void collectAssociationOverrides() { + // we only need to do this on root + } + +// // todo : account for supers/subs... +// if ( CollectionHelper.isEmpty( getMappedSuperclassTypeMetadatas() ) ) { +// return RootEntityTypeMetadata.super.getAssociationOverrideMap(); +// } +// Map map = new HashMap(); +// for ( MappedSuperclassTypeMetadata mappedSuperclassTypeMetadata : getMappedSuperclassTypeMetadatas() ) { +// map.putAll( mappedSuperclassTypeMetadata.getAssociationOverrideMap() ); +// } +// map.putAll( RootEntityTypeMetadata.super.getAssociationOverrideMap() ); +// return map; + + /** + * This form is intended for cases where the Entity/MappedSuperclass + * is part of the root subclass tree. + * + * @param javaTypeDescriptor Metadata for the Entity/MappedSuperclass + * @param superType The metadata for the super type. + * @param defaultAccessType The default AccessType for the entity hierarchy + * @param context The binding context + */ + public IdentifiableTypeMetadata( + ClassDescriptor javaTypeDescriptor, + IdentifiableTypeMetadata superType, + AccessType defaultAccessType, + AnnotationBindingContext context) { + super( javaTypeDescriptor, superType, defaultAccessType, context ); + + // the idea here is to collect up class-level annotations and to apply + // the maps from supers + collectConversionInfo(); + collectAttributeOverrides(); + collectAssociationOverrides(); + } + + @Override + public boolean isAbstract() { + return super.isAbstract(); + } + + @Override + public AttributeConversionInfo locateConversionInfo(AttributePath attributePath) { + return conversionInfoMap.get( attributePath ); + } + + @Override + public AttributeOverride locateAttributeOverride(AttributePath attributePath) { + return attributeOverrideMap.get( attributePath ); + } + + @Override + public AssociationOverride locateAssociationOverride(AttributePath attributePath) { + return associationOverrideMap.get( attributePath ); + } + + @Override + public IdentifiableTypeMetadata getSuperType() { + return (IdentifiableTypeMetadata) super.getSuperType(); + } + + /** + * Obtain the InheritanceType defined locally within this class + * + * @return Return the InheritanceType locally defined; {@code null} indicates + * no InheritanceType was locally defined. + */ + public InheritanceType getLocallyDefinedInheritanceType() { + final AnnotationInstance inheritanceAnnotation = JandexHelper.getSingleAnnotation( + getJavaTypeDescriptor().getJandexClassInfo(), + JPADotNames.INHERITANCE + ); + if ( inheritanceAnnotation != null ) { + final AnnotationValue strategyValue = inheritanceAnnotation.value( "strategy" ); + if ( strategyValue != null ) { + return InheritanceType.valueOf( strategyValue.asEnum() ); + } + else { + // the @Inheritance#strategy default value + return InheritanceType.SINGLE_TABLE; + } + } + + return null; + } + + /** + * Obtain all JPA callbacks specifically indicated on the entity itself. This + * includes:
        + *
      • local callbacks (methods on the class itself)
      • + *
      • callbacks from @EntityListener annotation on the class itself
      • + *
      + * + * @return The callbacks. {@code null} is never returned + */ + public List getJpaCallbacks() { + if ( collectedJpaCallbackSources == null ) { + collectedJpaCallbackSources = collectJpaCallbacks(); + } + return collectedJpaCallbackSources; + } + + private List collectJpaCallbacks() { + final LinkedHashSet callbacks = new LinkedHashSet(); + + // local (to the entity itself) callback + collectCallbacks( getJavaTypeDescriptor(), false, callbacks ); + + // EntityListeners annotation on the entity + final AnnotationInstance entityListenersAnnotation = JandexHelper.getSingleAnnotation( + getJavaTypeDescriptor().getJandexClassInfo(), + JPADotNames.ENTITY_LISTENERS + ); + if ( entityListenersAnnotation != null ) { + final Type[] types = entityListenersAnnotation.value().asClassArray(); + for ( Type type : types ) { + final JavaTypeDescriptor entityListener = getLocalBindingContext().getJavaTypeDescriptorRepository().getType( + getLocalBindingContext().getJavaTypeDescriptorRepository().buildName( type.name().toString() ) + ); + collectCallbacks( entityListener, true, callbacks ); + } + } + + // EntityListeners "annotation" defined as default in orm.xml + final Collection defaultEntityListenersAnnotations = + getLocalBindingContext().getJandexAccess().getIndex().getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); + // there really should be only one or none... + if ( defaultEntityListenersAnnotations != null ) { + if ( defaultEntityListenersAnnotations.size() > 1 ) { + log.debugf( + "Encountered multiple default definitions; merging lists" + ); + } + for ( AnnotationInstance defaultEntityListenersAnnotation : defaultEntityListenersAnnotations ) { + final Type[] types = defaultEntityListenersAnnotation.value().asClassArray(); + for ( Type type : types ) { + final JavaTypeDescriptor entityListener = getLocalBindingContext().getJavaTypeDescriptorRepository().getType( + getLocalBindingContext().getJavaTypeDescriptorRepository().buildName( type.name().toString() ) + ); + collectCallbacks( entityListener, true, callbacks ); + } + } + } + + return new ArrayList( callbacks ); + } + + private void collectCallbacks( + JavaTypeDescriptor javaTypeDescriptor, + boolean isListener, + LinkedHashSet callbacks) { + if ( isListener && !ClassDescriptor.class.isInstance( javaTypeDescriptor ) ) { + throw getLocalBindingContext().makeMappingException( + "Callback listener cannot be an interface : " + javaTypeDescriptor.getName().toString() + ); + } + + final String prePersistCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.PRE_PERSIST, + isListener + ); + final String preRemoveCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.PRE_REMOVE, + isListener + ); + final String preUpdateCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.PRE_UPDATE, + isListener + ); + final String postLoadCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.POST_LOAD, + isListener + ); + final String postPersistCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.POST_PERSIST, + isListener + ); + final String postRemoveCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.POST_REMOVE, + isListener + ); + final String postUpdateCallback = JPAListenerHelper.findCallback( + javaTypeDescriptor, + JPADotNames.POST_UPDATE, + isListener + ); + + if ( prePersistCallback == null + && preRemoveCallback == null + && preUpdateCallback == null + && postLoadCallback == null + && postPersistCallback == null + && postRemoveCallback == null + && postUpdateCallback == null ) { + if ( isListener ) { + log.debugf( + "Entity listener class [%s] named by @EntityListener on entity [%s] contained no callback methods", + javaTypeDescriptor.getName(), + getJavaTypeDescriptor().getName() + ); + } + } + else { + callbacks.add( + new JpaCallbackSourceImpl( + javaTypeDescriptor, + isListener, + prePersistCallback, + preRemoveCallback, + preUpdateCallback, + postLoadCallback, + postPersistCallback, + postRemoveCallback, + postUpdateCallback + ) + ); + } + } + + @Override + public void registerConverter( + AttributePath attributePath, + AttributeConversionInfo conversionInfo) { + conversionInfoMap.put( attributePath, conversionInfo ); + } + + @Override + public void registerAttributeOverride( + AttributePath attributePath, + AttributeOverride override) { + if ( attributeOverrideMap.containsKey( attributePath ) ) { + // an already registered path indicates that a higher context has already + // done a registration; ignore the incoming one. + log.debugf( + "On registration of @AttributeOverride we already had a " + + "registered override for the given path [%s]; ignoring. " + + "This subsequent registration should indicate a 'lower " + + "precedence' location." + ); + } + else { + attributeOverrideMap.put( attributePath, override ); + } + } + + @Override + public void registerAssociationOverride( + AttributePath attributePath, + AssociationOverride override) { + associationOverrideMap.put( attributePath, override ); + } + + @Override + protected void categorizeAttribute(PersistentAttribute persistentAttribute) { + if ( SingularAttribute.class.isInstance( persistentAttribute ) ) { + final SingularAttribute singularAttribute = (SingularAttribute) persistentAttribute; + if ( singularAttribute.isVersion() ) { + if ( versionAttribute != null ) { + throw getLocalBindingContext().makeMappingException( + String.format( + Locale.ENGLISH, + "Multiple attributes [%s, %s] were indicated as Version", + versionAttribute.getName(), + singularAttribute.getName() + ) + ); + } + if ( singularAttribute.isId() ) { + throw getLocalBindingContext().makeMappingException( + String.format( + Locale.ENGLISH, + "Attributes [%s] was indicated as Id and as Version", + singularAttribute.getName() + ) + ); + } + // only BasicAttributes can be versions + versionAttribute = (BasicAttribute) singularAttribute; + return; + } + + if ( singularAttribute.isId() ) { + if ( identifierAttributes == null ) { + // first collected identifier attribute + identifierAttributes = new ArrayList(); + switch ( singularAttribute.getNature() ) { + case EMBEDDED: + case EMBEDDED_ID: { + idType = IdType.AGGREGATED; + break; + } + default: { + idType = IdType.SIMPLE; + break; + } + } + } + else { + // multiple collected identifier attribute + idType = IdType.NON_AGGREGATED; + } + identifierAttributes.add( singularAttribute ); + return; + } + } + + super.categorizeAttribute( persistentAttribute ); + } + + + public IdType getIdType() { + collectAttributesIfNeeded(); + + if ( idType == null ) { + if ( getSuperType() != null ) { + return getSuperType().getIdType(); + } + } + return idType == null ? IdType.NONE : idType; + } + + public List getIdentifierAttributes() { + collectAttributesIfNeeded(); + + if ( identifierAttributes == null ) { + if ( getSuperType() != null ) { + return getSuperType().getIdentifierAttributes(); + } + } + return identifierAttributes == null ? Collections.emptyList() : identifierAttributes; + } + + public BasicAttribute getVersionAttribute() { + collectAttributesIfNeeded(); + + if ( versionAttribute == null ) { + if ( getSuperType() != null ) { + return getSuperType().getVersionAttribute(); + } + } + return versionAttribute; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/ManagedTypeMetadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/ManagedTypeMetadata.java new file mode 100644 index 000000000000..d925fb12b1a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/ManagedTypeMetadata.java @@ -0,0 +1,821 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import javax.persistence.AccessType; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.EmbeddedAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute; +import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute; +import org.hibernate.metamodel.source.internal.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * Models metadata about what JPA calls a {@link javax.persistence.metamodel.ManagedType}. + *

      + * Concretely, may be:

        + *
      • + * IdentifiableTypeMetadata
          + *
        • EntityTypeMetadata
        • + *
        • MappedSuperclassTypeMetadata
        • + *
        + *
      • + *
      • + * EmbeddableTypeMetadata + *
      • + *
      + * + * @author Hardy Ferentschik + * @author Steve Ebersole + * @author Brett Meyer + */ +public abstract class ManagedTypeMetadata implements OverrideAndConverterCollector { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ManagedTypeMetadata.class ); + + private final JavaTypeDescriptor javaTypeDescriptor; + private final EntityBindingContext localBindingContext; + + private final ManagedTypeMetadata superType; + private Set subclasses; + private final AttributePath attributePathBase; + private final AttributeRole attributeRoleBase; + + private final AccessType classLevelAccessType; + private final String explicitClassLevelAccessorStrategy; + private final String customTuplizerClassName; + + private Map persistentAttributeMap; + + + /** + * This form is intended for construction of the root of an entity hierarchy, + * and its MappedSuperclasses + * + * @param javaTypeDescriptor Metadata for the Entity/MappedSuperclass + * @param defaultAccessType The default AccessType for the entity hierarchy + * @param bindingContext The binding context + */ + public ManagedTypeMetadata( + JavaTypeDescriptor javaTypeDescriptor, + AccessType defaultAccessType, + boolean isRootEntity, + AnnotationBindingContext bindingContext) { + this.javaTypeDescriptor = javaTypeDescriptor; + this.localBindingContext = new EntityBindingContext( bindingContext, this ); + + this.classLevelAccessType = determineAccessType( javaTypeDescriptor, defaultAccessType ); + this.explicitClassLevelAccessorStrategy = determineExplicitAccessorStrategy( + javaTypeDescriptor, + null + ); + + this.customTuplizerClassName = determineCustomTuplizer( javaTypeDescriptor ); + + // walk up + this.superType = walkRootSuperclasses( javaTypeDescriptor, defaultAccessType, bindingContext ); + if ( superType != null ) { + superType.addSubclass( this ); + } + + if ( isRootEntity ) { + // walk down + walkSubclasses( javaTypeDescriptor, (IdentifiableTypeMetadata) this, defaultAccessType, bindingContext ); + } + + this.attributeRoleBase = new AttributeRole( javaTypeDescriptor.getName().toString() ); + this.attributePathBase = new AttributePath(); + } + + private String determineCustomTuplizer(JavaTypeDescriptor javaTypeDescriptor) { + final AnnotationInstance tuplizerAnnotation = javaTypeDescriptor.findLocalTypeAnnotation( + HibernateDotNames.TUPLIZER + ); + + if ( tuplizerAnnotation == null ) { + return null; + } + + final AnnotationValue implValue = tuplizerAnnotation.value( "impl" ); + if ( implValue == null ) { + return null; + } + + return StringHelper.nullIfEmpty( implValue.asString() ); + } + + private void addSubclass(ManagedTypeMetadata subclass) { + if ( subclasses == null ) { + subclasses = new HashSet(); + } + subclasses.add( subclass ); + } + + /** + * This form is intended for construction of entity hierarchy subclasses. + * + * @param javaTypeDescriptor Metadata for the Entity/MappedSuperclass + * @param superType Metadata for the super type + * @param defaultAccessType The default AccessType for the entity hierarchy + * @param bindingContext The binding context + */ + public ManagedTypeMetadata( + JavaTypeDescriptor javaTypeDescriptor, + ManagedTypeMetadata superType, + AccessType defaultAccessType, + AnnotationBindingContext bindingContext) { + this.javaTypeDescriptor = javaTypeDescriptor; + this.localBindingContext = new EntityBindingContext( bindingContext, this ); + + this.classLevelAccessType = determineAccessType( javaTypeDescriptor, defaultAccessType ); + + // does the mapping defaults define a default? + // trouble is that the defaults do define a default.. ALL THE TIME + //final String mappingDefault = bindingContext.getMappingDefaults().getPropertyAccessorName(); + //if + this.explicitClassLevelAccessorStrategy = determineExplicitAccessorStrategy( + javaTypeDescriptor, + null + ); + + this.customTuplizerClassName = determineCustomTuplizer( javaTypeDescriptor ); + + this.superType = superType; + + this.attributeRoleBase = new AttributeRole( javaTypeDescriptor.getName().toString() ); + this.attributePathBase = new AttributePath(); + } + + /** + * This form is used to create Embedded references + * + * @param embeddableType The Embeddable descriptor + * @param attributeRoleBase The base for the roles of attributes created *from* here + * @param attributePathBase The base for the paths of attributes created *from* here + * @param defaultAccessType The default AccessType from the context of this Embedded + * @param defaultAccessorStrategy The default accessor strategy from the context of this Embedded + * @param bindingContext The binding context + */ + public ManagedTypeMetadata( + JavaTypeDescriptor embeddableType, + AttributeRole attributeRoleBase, + AttributePath attributePathBase, + AccessType defaultAccessType, + String defaultAccessorStrategy, + AnnotationBindingContext bindingContext) { + this.javaTypeDescriptor = embeddableType; + this.localBindingContext = new EntityBindingContext( bindingContext, this ); + + this.classLevelAccessType = determineAccessType( javaTypeDescriptor, defaultAccessType ); + this.explicitClassLevelAccessorStrategy = determineExplicitAccessorStrategy( + javaTypeDescriptor, + defaultAccessorStrategy + ); + + this.customTuplizerClassName = determineCustomTuplizer( javaTypeDescriptor ); + + this.superType = null; + + this.attributeRoleBase = attributeRoleBase; + this.attributePathBase = attributePathBase; + } + + private static AccessType determineAccessType(JavaTypeDescriptor javaTypeDescriptor, AccessType defaultAccessType) { + final AnnotationInstance localAccessAnnotation = javaTypeDescriptor.findLocalTypeAnnotation( JPADotNames.ACCESS ); + if ( localAccessAnnotation != null ) { + final AnnotationValue accessTypeValue = localAccessAnnotation.value(); + if ( accessTypeValue != null ) { + return AccessType.valueOf( accessTypeValue.asEnum() ); + } + } + + // legacy alert! + // In the absence of a JPA @Access annotation, we interpret our custom + // @AttributeAccessor as indicating access *if* it is "field" or "property" + final AnnotationInstance accessorAnnotation = javaTypeDescriptor.findLocalTypeAnnotation( HibernateDotNames.ATTRIBUTE_ACCESSOR ); + if ( accessorAnnotation != null ) { + final AnnotationValue strategyValue = accessorAnnotation.value(); + if ( strategyValue != null ) { + final String strategyName = strategyValue.asString(); + if ( StringHelper.isNotEmpty( strategyName ) ) { + if ( "field".equals( strategyName ) ) { + return AccessType.FIELD; + } + else if ( "property".equals( strategyName ) ) { + return AccessType.PROPERTY; + } + } + } + } + + return defaultAccessType; + } + + private static String determineExplicitAccessorStrategy( + JavaTypeDescriptor javaTypeDescriptor, + String defaultValue) { + // look for a @AttributeAccessor annotation + final AnnotationInstance attributeAccessorAnnotation = javaTypeDescriptor.findLocalTypeAnnotation( + HibernateDotNames.ATTRIBUTE_ACCESSOR + ); + if ( attributeAccessorAnnotation != null ) { + String explicitAccessorStrategy = attributeAccessorAnnotation.value().asString(); + if ( StringHelper.isEmpty( explicitAccessorStrategy ) ) { + LOG.warnf( + "Class [%s] specified @AttributeAccessor with empty value", + javaTypeDescriptor.getName() + ); + } + else { + return explicitAccessorStrategy; + } + } + + final AnnotationInstance localAccessAnnotation = javaTypeDescriptor.findLocalTypeAnnotation( JPADotNames.ACCESS ); + if ( localAccessAnnotation != null ) { + final AnnotationValue accessTypeValue = localAccessAnnotation.value(); + if ( accessTypeValue != null ) { + return AccessType.valueOf( accessTypeValue.asEnum() ).name().toLowerCase(); + } + } + + return defaultValue; + } + + private IdentifiableTypeMetadata walkRootSuperclasses( + JavaTypeDescriptor type, + AccessType defaultAccessType, + AnnotationBindingContext context) { + if ( !ClassDescriptor.class.isInstance( type ) ) { + return null; + } + + final ClassDescriptor superType = ( (ClassDescriptor) type ).getSuperType(); + + if ( superType == null ) { + // no super type + return null; + } + + // make triple sure there is no @Entity annotation + if ( isEntity( superType ) ) { + throw new MappingException( + String.format( + Locale.ENGLISH, + "Unexpected @Entity [%s] as MappedSuperclass of entity hierarchy", + type.getName() + ), + new Origin( SourceType.ANNOTATION, superType.getName().toString() ) + ); + } + else if ( isMappedSuperclass( superType ) ) { + return new MappedSuperclassTypeMetadata( superType, defaultAccessType, context ); + } + else { + // otherwise, we might have an "intermediate" subclass + if ( superType.getSuperType() != null ) { + return walkRootSuperclasses( superType, defaultAccessType, context ); + } + else { + return null; + } + } + } + + private void walkSubclasses( + JavaTypeDescriptor javaTypeDescriptor, + IdentifiableTypeMetadata superType, + AccessType defaultAccessType, + AnnotationBindingContext bindingContext) { + // ask Jandex for all the known *direct* subclasses of `superType` + // and iterate them to create the subclass metadata + final Collection classInfos = bindingContext.getJandexAccess() + .getIndex() + .getKnownDirectSubclasses( javaTypeDescriptor.getName() ); + + for ( ClassInfo classInfo : classInfos ) { + final ClassDescriptor subclassTypeDescriptor = (ClassDescriptor) bindingContext.getJavaTypeDescriptorRepository().getType( classInfo.name() ); + + final IdentifiableTypeMetadata subclassMeta; + if ( isMappedSuperclass( javaTypeDescriptor ) ) { + subclassMeta = new MappedSuperclassTypeMetadata( subclassTypeDescriptor, superType, defaultAccessType, bindingContext ); + } + else { + subclassMeta = new EntityTypeMetadata( subclassTypeDescriptor, superType, defaultAccessType, bindingContext ); + } + + ( (ManagedTypeMetadata) superType ).addSubclass( subclassMeta ); + walkSubclasses( subclassTypeDescriptor, subclassMeta, defaultAccessType, bindingContext ); + } + } + + private boolean isMappedSuperclass(JavaTypeDescriptor javaTypeDescriptor) { + return javaTypeDescriptor.findLocalTypeAnnotation( JPADotNames.MAPPED_SUPERCLASS ) != null; + } + + private boolean isEntity(JavaTypeDescriptor javaTypeDescriptor) { + return javaTypeDescriptor.findLocalTypeAnnotation( JPADotNames.ENTITY ) != null; + } + + public AttributeRole getAttributeRoleBase() { + return attributeRoleBase; + } + + public AttributePath getAttributePathBase() { + return attributePathBase; + } + + public JavaTypeDescriptor getJavaTypeDescriptor() { + return javaTypeDescriptor; + } + + + public String getName() { + return javaTypeDescriptor.getName().toString(); + } + + public ManagedTypeMetadata getSuperType() { + return superType; + } + + public Set getSubclasses() { + return subclasses == null ? Collections.emptySet() : subclasses; + } + + public EntityBindingContext getLocalBindingContext() { + return localBindingContext; + } + + public boolean isAbstract() { + return Modifier.isAbstract( javaTypeDescriptor.getModifiers() ); + } + + public Map getPersistentAttributeMap() { + collectAttributesIfNeeded(); + return persistentAttributeMap; + } + + protected void collectAttributesIfNeeded() { + if ( persistentAttributeMap == null ) { + persistentAttributeMap = new HashMap(); + // TODO: This probably isn't the best place for this. Walking and creating the ManagedTypeMetadatas, + // for the entire subclass tree, including subclasses that are not an @Entity/@MappedSuperclass/@Embeddable, + // is entirely necessary. But, we need to skip processing the attributes in this case. Cleaner way to do + // it in the new architecture? + if (isEntity( javaTypeDescriptor ) + || isMappedSuperclass( javaTypeDescriptor ) + || isEmbeddableType( javaTypeDescriptor )) { + collectPersistentAttributes(); + } + } + } + + public String getCustomTuplizerClassName() { + return customTuplizerClassName; + } + + @Override + public String toString() { + return "ManagedTypeMetadata{javaType=" + javaTypeDescriptor.getName().toString() + "}"; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // attribute handling + + /** + * Collect all persistent attributes for this managed type + */ + private void collectPersistentAttributes() { + // Call the strategy responsible for resolving the members that identify a persistent attribute + final List backingMembers = localBindingContext.getBuildingOptions() + .getPersistentAttributeMemberResolver() + .resolveAttributesMembers( getJavaTypeDescriptor(), classLevelAccessType, localBindingContext ); + + for ( MemberDescriptor backingMember : backingMembers ) { + final AccessType accessType = determineAttributeAccessType( backingMember ); + final String attributeName; + if ( FieldDescriptor.class.isInstance( backingMember ) ) { + attributeName = backingMember.getName(); + } + else if ( MethodDescriptor.class.isInstance( backingMember ) ) { + final MethodDescriptor methodDescriptor = (MethodDescriptor) backingMember; + attributeName = ReflectHelper.getPropertyNameFromGetterMethod( methodDescriptor.getName() ); + } + else { + throw localBindingContext.makeMappingException( + "Backing member for a persistent attribute needs to be either a field or (getter) method : " + + backingMember.toLoggableForm() + ); + } + + createPersistentAttribute( attributeName, backingMember, accessType ); + } + } + + private AccessType determineAttributeAccessType(MemberDescriptor backingMember) { + final AnnotationInstance explicitAccessAnnotation = backingMember.getAnnotations().get( JPADotNames.ACCESS ); + if ( explicitAccessAnnotation != null ) { + return localBindingContext.getJandexAccess().getTypedValueExtractor( AccessType.class ) + .extract( explicitAccessAnnotation, "value" ); + } + + return classLevelAccessType; + } + + private void createPersistentAttribute(String attributeName, MemberDescriptor member, AccessType accessType) { + final String accessorStrategy = determineAttributeLevelAccessorStrategy( member, accessType ); + + final JavaTypeDescriptor collectionElementType = AnnotationParserHelper.resolveCollectionElementType( + member, + getLocalBindingContext() + ); + + AttributeCategorization attributeCategory = determineAttributeCategorization( + member, + member.getType().getErasedType() + ); + + switch ( attributeCategory ) { + case BASIC: { + final BasicAttribute attr = new BasicAttribute( + ManagedTypeMetadata.this, + attributeName, + attributePathBase.append( attributeName ), + attributeRoleBase.append( attributeName ), + member, + accessType, + accessorStrategy + ); + categorizeAttribute( attr ); + break; + } + case EMBEDDED: { + // NOTE that this models the Embedded, not the Embeddable! + final EmbeddedAttribute attr = new EmbeddedAttribute( + ManagedTypeMetadata.this, + attributeName, + attributePathBase.append( attributeName ), + attributeRoleBase.append( attributeName ), + member, + accessType, + accessorStrategy + ); + categorizeAttribute( attr ); + break; + } + case TO_ONE: { + final SingularAssociationAttribute attr = new SingularAssociationAttribute( + ManagedTypeMetadata.this, + attributeName, + attributePathBase.append( attributeName ), + attributeRoleBase.append( attributeName ), + member, + determineToOneNature( member ), + accessType, + accessorStrategy + ); + categorizeAttribute( attr ); + break; + } + case PLURAL: { + final JavaTypeDescriptor mapKeyType = AnnotationParserHelper.resolveMapKeyType( + member, + getLocalBindingContext() + ); + PluralAttribute attr = new PluralAttribute( + ManagedTypeMetadata.this, + attributeName, + attributePathBase.append( attributeName ), + attributeRoleBase.append( attributeName ), + member, + determinePluralAttributeNature( member, collectionElementType ), + collectionElementType, + mapKeyType, + accessType, + accessorStrategy + ); + categorizeAttribute( attr ); + break; + } + case ANY : {} + case MANY_TO_ANY: {} + } + } + + private PersistentAttribute.Nature determineToOneNature(MemberDescriptor member) { + final AnnotationInstance oneToOne = member.getAnnotations().get( JPADotNames.ONE_TO_ONE ); + final AnnotationInstance manyToOne = member.getAnnotations().get( JPADotNames.MANY_TO_ONE ); + if ( oneToOne != null ) { + return PersistentAttribute.Nature.ONE_TO_ONE; + } + + if ( manyToOne != null ) { + return PersistentAttribute.Nature.MANY_TO_ONE; + } + + throw getLocalBindingContext().makeMappingException( + "Could not determine Nature of TO_ONE attribute : " + member.getName() + ); + } + + private PersistentAttribute.Nature determinePluralAttributeNature( + MemberDescriptor member, + JavaTypeDescriptor collectionElementType) { + final boolean isCollectionElementTypeEmbeddable = collectionElementType != null + && isEmbeddableType( collectionElementType ); + + final AnnotationInstance oneToMany = member.getAnnotations().get( JPADotNames.ONE_TO_MANY ); + if ( oneToMany != null ) { + return PersistentAttribute.Nature.ONE_TO_MANY; + } + + final AnnotationInstance manyToMany = member.getAnnotations().get( JPADotNames.MANY_TO_MANY ); + if ( manyToMany != null ) { + return PersistentAttribute.Nature.MANY_TO_MANY; + } + + final AnnotationInstance elementCollection = member.getAnnotations().get( JPADotNames.ELEMENT_COLLECTION ); + if ( elementCollection != null ) { + if ( isCollectionElementTypeEmbeddable ) { + return PersistentAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE; + } + else { + return PersistentAttribute.Nature.ELEMENT_COLLECTION_BASIC; + } + } + + if ( member.getAnnotations().containsKey( JPADotNames.TEMPORAL ) + || member.getAnnotations().containsKey( JPADotNames.LOB ) + || member.getAnnotations().containsKey( JPADotNames.ENUMERATED ) + || member.getAnnotations().containsKey( HibernateDotNames.TYPE ) ) { + return PersistentAttribute.Nature.ELEMENT_COLLECTION_BASIC; + } + + if ( member.getAnnotations().containsKey( HibernateDotNames.COLLECTION_ID ) + || member.getAnnotations().containsKey( HibernateDotNames.COLLECTION_TYPE ) + || member.getAnnotations().containsKey( HibernateDotNames.LIST_INDEX_BASE ) + || member.getAnnotations().containsKey( HibernateDotNames.MAP_KEY_TYPE ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_CLASS ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_COLUMN ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMN ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMNS ) ) { + if ( isCollectionElementTypeEmbeddable ) { + return AbstractPersistentAttribute.Nature.ELEMENT_COLLECTION_EMBEDDABLE; + } + else { + return AbstractPersistentAttribute.Nature.ELEMENT_COLLECTION_BASIC; + } + } + + throw getLocalBindingContext().makeMappingException( + "Could not determine Nature of PLURAL attribute : " + member.getName() + ); + } + + protected void categorizeAttribute(PersistentAttribute attr) { + persistentAttributeMap.put( attr.getName(), attr ); + } + + private String determineAttributeLevelAccessorStrategy(MemberDescriptor member, AccessType accessType) { + // first and foremost, does the attribute define a local accessor strategy + final AnnotationInstance attributeAccessorAnnotation = member.getAnnotations().get( + HibernateDotNames.ATTRIBUTE_ACCESSOR + ); + if ( attributeAccessorAnnotation != null ) { + String explicitAccessorStrategy = attributeAccessorAnnotation.value().asString(); + if ( StringHelper.isEmpty( explicitAccessorStrategy ) ) { + LOG.warnf( "Attribute [%s] specified @AttributeAccessor with empty value", member ); + } + else { + return explicitAccessorStrategy; + } + } + + // finally use the attribute AccessType as default... + return accessType.name().toLowerCase(); + } + + /** + * Represents a rough categorization of type of attributes + */ + private static enum AttributeCategorization { + BASIC, + EMBEDDED, + TO_ONE, + PLURAL, + ANY, + MANY_TO_ANY + } + + private AttributeCategorization determineAttributeCategorization( + MemberDescriptor member, + JavaTypeDescriptor attributeType) { + + EnumSet categories = EnumSet.noneOf( AttributeCategorization.class ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // first, look for explicit nature annotations + + final AnnotationInstance basic = member.getAnnotations().get( JPADotNames.BASIC ); + if ( basic != null ) { + categories.add( AttributeCategorization.BASIC ); + } + + final AnnotationInstance embeddedId = member.getAnnotations().get( JPADotNames.EMBEDDED_ID ); + final AnnotationInstance embedded = member.getAnnotations().get( JPADotNames.EMBEDDED ); + if ( embeddedId != null || embedded != null ) { + categories.add( AttributeCategorization.EMBEDDED ); + } + + final AnnotationInstance any = member.getAnnotations().get( HibernateDotNames.ANY ); + if ( any != null ) { + categories.add( AttributeCategorization.ANY ); + } + + final AnnotationInstance oneToOne = member.getAnnotations().get( JPADotNames.ONE_TO_ONE ); + final AnnotationInstance manyToOne = member.getAnnotations().get( JPADotNames.MANY_TO_ONE ); + if ( oneToOne != null || manyToOne != null ) { + categories.add( AttributeCategorization.TO_ONE ); + } + + final AnnotationInstance oneToMany = member.getAnnotations().get( JPADotNames.ONE_TO_MANY ); + final AnnotationInstance manyToMany = member.getAnnotations().get( JPADotNames.MANY_TO_MANY ); + final AnnotationInstance elementCollection = member.getAnnotations().get( JPADotNames.ELEMENT_COLLECTION ); + if ( oneToMany != null || manyToMany != null || elementCollection != null ) { + categories.add( AttributeCategorization.PLURAL ); + } + + final AnnotationInstance manyToAny = member.getAnnotations().get( HibernateDotNames.MANY_TO_ANY ); + if ( manyToAny != null ) { + categories.add( AttributeCategorization.MANY_TO_ANY ); + } + + + // For backward compatibility, we're allowing attributes of an + // @Embeddable type to leave off @Embedded. Check the type's + // annotations. (see HHH-7678) + // However, it's important to ignore this if the field is + // annotated with @EmbeddedId. + if ( embedded == null && embeddedId == null ) { + if ( isEmbeddableType( attributeType ) ) { + LOG.warnf( + "Class %s was annotated as @Embeddable. However a persistent attribute [%s] " + + "of this type was found that did not contain the @Embedded (or @EmbeddedId) annotation. " + + "This may cause compatibility issues", + attributeType.getName(), + member.toLoggableForm() + ); + categories.add( AttributeCategorization.EMBEDDED ); + } + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // then we look at annotations that can be used to infer natures + + if ( member.getAnnotations().containsKey( JPADotNames.TEMPORAL ) + || member.getAnnotations().containsKey( JPADotNames.LOB ) + || member.getAnnotations().containsKey( JPADotNames.ENUMERATED ) + || member.getAnnotations().containsKey( HibernateDotNames.TYPE ) ) { + // technically these could describe the elements of a "element collection" + // but without requiring the @ElementCollection annotation we + // run into problems mapping things like our "materialized LOB" + // support where @Lob might be combined with an array + // + // All in all, supporting that inference would require a lot of checks. + // Not sure its worth the effort. For future reference the checks would + // be along the lines of: + // in order for this to indicate a persistent (element) collection + // we'd have to unequivocally know the collection element type (or + // array component type) and that type would need to be consistent + // with the inferred type. For example, given a collection marked + // @Lob, in order for us to interpret that as indicating a + // LOB-based ElementCollection we would need to be able to verify + // that the elements of the Collection are in fact Lobs. + if ( elementCollection == null ) { + categories.add( AttributeCategorization.BASIC ); + } + } + + if ( member.getAnnotations().containsKey( HibernateDotNames.COLLECTION_ID ) + || member.getAnnotations().containsKey( HibernateDotNames.COLLECTION_TYPE ) + || member.getAnnotations().containsKey( HibernateDotNames.LIST_INDEX_BASE ) + || member.getAnnotations().containsKey( HibernateDotNames.MAP_KEY_TYPE ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_CLASS ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_COLUMN ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMN ) + || member.getAnnotations().containsKey( JPADotNames.MAP_KEY_JOIN_COLUMNS ) ) { + categories.add( AttributeCategorization.PLURAL ); + } + + // todo : other "inferences"? + + int size = categories.size(); + switch ( size ) { + case 0: { + return AttributeCategorization.BASIC; + } + case 1: { + return categories.iterator().next(); + } + default: { + throw getLocalBindingContext().makeMappingException( + "More than one attribute type was discovered for attribute " + member.getName() + + " : " + categories.toString() + ); + } + } + + } + + protected boolean isEmbeddableType(JavaTypeDescriptor descriptor) { + return descriptor.findTypeAnnotation( JPADotNames.EMBEDDABLE ) != null; + } + + + // NOTE : the idea here is gto route this call back to "the base", + // the assumption being that all *relevant* converters have previously + // been normalized to the base + public abstract AttributeConversionInfo locateConversionInfo(AttributePath attributePath); + + public abstract AttributeOverride locateAttributeOverride(AttributePath attributePath); + + public abstract AssociationOverride locateAssociationOverride(AttributePath attributePath); + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Stuff affecting attributes built from this managed type. + + public boolean canAttributesBeInsertable() { + return true; + } + + public boolean canAttributesBeUpdatable() { + return true; + } + + public NaturalIdMutability getContainerNaturalIdMutability() { + return NaturalIdMutability.NOT_NATURAL_ID; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/MappedSuperclassTypeMetadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/MappedSuperclassTypeMetadata.java new file mode 100644 index 000000000000..bb398835dd86 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/MappedSuperclassTypeMetadata.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import javax.persistence.AccessType; + +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; + +/** + * Represents the information about an entity annotated with {@code @MappedSuperclass}. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class MappedSuperclassTypeMetadata extends IdentifiableTypeMetadata { + /** + * This form is intended for cases where the MappedSuperclasses is part + * of the root super tree. + * + * @param javaTypeDescriptor The descriptor for the type annotated as MappedSuperclass + * @param defaultAccessType The default AccessType for he hierarchy + * @param context The binding context + */ + public MappedSuperclassTypeMetadata( + ClassDescriptor javaTypeDescriptor, + AccessType defaultAccessType, + AnnotationBindingContext context) { + super( javaTypeDescriptor, defaultAccessType, false, context ); + } + + /** + * This form is intended for cases where the MappedSuperclasses is part + * of the root subclass tree. + * + * @param javaTypeDescriptor The descriptor for the type annotated as MappedSuperclass + * @param superType The metadata representing the super type + * @param defaultAccessType The default AccessType for he hierarchy + * @param context The binding context + */ + public MappedSuperclassTypeMetadata( + ClassDescriptor javaTypeDescriptor, + IdentifiableTypeMetadata superType, + AccessType defaultAccessType, + AnnotationBindingContext context) { + super( javaTypeDescriptor, superType, defaultAccessType, context ); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/RootEntityTypeMetadata.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/RootEntityTypeMetadata.java new file mode 100644 index 000000000000..9c746205f3a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/RootEntityTypeMetadata.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.entity; + +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.source.internal.annotations.util.ConverterAndOverridesHelper; +import org.hibernate.metamodel.spi.AttributePath; + +import org.jboss.jandex.AnnotationInstance; + +import static org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames.ROW_ID; + +/** + * Representation of metadata (configured via annotations or orm.xml) attached + * to an Entity that is the root of a persistence hierarchy. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + * @author Brett Meyer + */ +public class RootEntityTypeMetadata extends EntityTypeMetadata { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( RootEntityTypeMetadata.class ); + + private final String rowId; + + public RootEntityTypeMetadata( + JavaTypeDescriptor javaTypeDescriptor, + AccessType defaultHierarchyAccessType, + AnnotationBindingContext context) { + super( javaTypeDescriptor, defaultHierarchyAccessType, context ); + + // ROWID + final AnnotationInstance rowIdAnnotation = javaTypeDescriptor.findTypeAnnotation( ROW_ID ); + this.rowId = rowIdAnnotation != null && rowIdAnnotation.value() != null + ? rowIdAnnotation.value().asString() + : null; + } + + @Override + protected void collectConversionInfo() { + super.collectConversionInfo(); + } + + @Override + protected void collectAttributeOverrides() { + collectAttributeOverrides( this ); + } + + private void collectAttributeOverrides(IdentifiableTypeMetadata type) { + // subclasses first, since they have precedence + ConverterAndOverridesHelper.INSTANCE.processAttributeOverrides( + new AttributePath(), + type, + this, + getLocalBindingContext() + ); + + if ( type.getSuperType() != null ) { + collectAttributeOverrides( type.getSuperType() ); + } + } + + @Override + protected void collectAssociationOverrides() { + super.collectAssociationOverrides(); + } + + @Override + protected List determinePrimaryKeyJoinColumns() { + List results = super.determinePrimaryKeyJoinColumns(); + if ( CollectionHelper.isNotEmpty( results ) ) { + LOG.invalidPrimaryKeyJoinColumnAnnotation(); + } + return null; + } + + public String getRowId() { + return rowId; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/package.html new file mode 100755 index 000000000000..2d0629a27494 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/entity/package.html @@ -0,0 +1,33 @@ + + + + + +

      + This package contains classes related to mapped entities and their hierarchy structure. +

      + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/FetchProfileProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/FetchProfileProcessor.java new file mode 100644 index 000000000000..118dd597cec1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/FetchProfileProcessor.java @@ -0,0 +1,113 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.global; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.MappingException; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.FetchProfiles; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.FetchProfile.Fetch; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.jboss.jandex.AnnotationInstance; + +/** + * Binds fetch profiles found in annotations. + * + * @author Hardy Ferentschik + */ +public class FetchProfileProcessor { + + private FetchProfileProcessor() { + } + + /** + * Binds all {@link FetchProfiles} and {@link org.hibernate.annotations.FetchProfile} annotations to the supplied metadata. + * + * @param bindingContext the context for annotation binding + */ + public static void bind(AnnotationBindingContext bindingContext) { + + Collection annotations = bindingContext.getJandexAccess() + .getIndex() + .getAnnotations( HibernateDotNames.FETCH_PROFILE ); + for ( AnnotationInstance fetchProfile : annotations ) { + bind( bindingContext, fetchProfile ); + } + + annotations = bindingContext.getJandexAccess().getIndex().getAnnotations( HibernateDotNames.FETCH_PROFILES ); + for ( AnnotationInstance fetchProfiles : annotations ) { + AnnotationInstance[] fetchProfileAnnotations = JandexHelper.getValue( + fetchProfiles, + "value", + AnnotationInstance[].class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance fetchProfile : fetchProfileAnnotations ) { + bind( bindingContext, fetchProfile ); + } + } + } + + private static void bind(AnnotationBindingContext bindingContext, AnnotationInstance fetchProfile) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + String name = JandexHelper.getValue( fetchProfile, "name", String.class, classLoaderService); + Set fetches = new HashSet(); + AnnotationInstance[] overrideAnnotations = JandexHelper.getValue( + fetchProfile, + "fetchOverrides", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance override : overrideAnnotations ) { + FetchMode fetchMode = JandexHelper.getEnumValue( override, "mode", FetchMode.class, classLoaderService ); + if ( !fetchMode.equals( org.hibernate.annotations.FetchMode.JOIN ) ) { + throw new MappingException( "Only FetchMode.JOIN is currently supported" ); + } + + final String entityName = JandexHelper.getValue( override, "entity", String.class, classLoaderService ); + final String associationName = JandexHelper.getValue( override, "association", String.class, classLoaderService ); + + EntityBinding entityBinding = bindingContext.getMetadataCollector().getEntityBinding( entityName ); + if ( entityBinding == null ) { + throw new MappingException( "FetchProfile " + name + " references an unknown entity: " + entityName ); + } + Attribute attributeBinding = entityBinding.getAttributeContainer().locateAttribute( associationName ); + if ( attributeBinding == null ) { + throw new MappingException( "FetchProfile " + name + " references an unknown association: " + associationName ); + } + + fetches.add( new Fetch( entityName, associationName, fetchMode.toString().toLowerCase() ) ); + } + bindingContext.getMetadataCollector().addFetchProfile( new FetchProfile( name, fetches ) ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/IdGeneratorProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/IdGeneratorProcessor.java new file mode 100644 index 000000000000..082e7138e383 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/IdGeneratorProcessor.java @@ -0,0 +1,278 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.global; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.GenerationType; +import javax.persistence.SequenceGenerator; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.GenericGenerators; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.SequenceHiLoGenerator; +import org.hibernate.id.TableHiLoGenerator; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.id.enhanced.TableGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.logging.Logger; + +/** + * Binds {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and + * {@link GenericGenerators} annotations. + * + * @author Hardy Ferentschik + */ +public class IdGeneratorProcessor { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + IdGeneratorProcessor.class.getName() + ); + + private IdGeneratorProcessor() { + } + + /** + * Binds all {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and + * {@link GenericGenerators} annotations to the supplied metadata. + * + * @param bindingContext the context for annotation binding + */ + public static Iterable extractGlobalIdentifierGeneratorSources(AnnotationBindingContext bindingContext) { + List identifierGeneratorSources = new ArrayList(); + Collection annotations = bindingContext.getJandexAccess() + .getIndex() + .getAnnotations( JPADotNames.SEQUENCE_GENERATOR ); + for ( AnnotationInstance generator : annotations ) { + bindSequenceGenerator( generator, identifierGeneratorSources, bindingContext ); + } + + annotations = bindingContext.getJandexAccess().getIndex().getAnnotations( JPADotNames.TABLE_GENERATOR ); + for ( AnnotationInstance generator : annotations ) { + bindTableGenerator( generator, identifierGeneratorSources, bindingContext ); + } + + annotations = JandexHelper.getAnnotations( + bindingContext.getJandexAccess().getIndex(), + HibernateDotNames.GENERIC_GENERATOR, + HibernateDotNames.GENERIC_GENERATORS, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance generator : annotations ) { + bindGenericGenerator( generator, identifierGeneratorSources, bindingContext ); + } + return identifierGeneratorSources; + } + + private static void addStringParameter( + final AnnotationInstance annotation, + final String element, + final Map parameters, + final String parameter, + final AnnotationBindingContext bindingContext) { + String string = JandexHelper.getValue( annotation, element, String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class )); + if ( StringHelper.isNotEmpty( string ) ) { + parameters.put( parameter, string ); + } + } + + private static void bindGenericGenerator( + final AnnotationInstance generator, + final List identifierGeneratorSources, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService ); + final Map parameterMap = new HashMap(); + final AnnotationInstance[] parameterAnnotations = JandexHelper.getValue( + generator, + "parameters", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + parameterMap.put( + JandexHelper.getValue( parameterAnnotation, "name", String.class, classLoaderService ), + JandexHelper.getValue( parameterAnnotation, "value", String.class, classLoaderService ) + ); + } + identifierGeneratorSources.add( + new IdentifierGeneratorSourceImpl( + name, + JandexHelper.getValue( generator, "strategy", String.class, classLoaderService ), + parameterMap + ) + ); + LOG.tracef( "Add generic generator with name: %s", name ); + } + + private static void bindSequenceGenerator( + final AnnotationInstance generator, + final List identifierGeneratorSources, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService ); + + final boolean useNewIdentifierGenerators = bindingContext.getBuildingOptions().isUseNewIdentifierGenerators(); + final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( + GenerationType.SEQUENCE, + useNewIdentifierGenerators + ); + + final Map parameterMap = new HashMap(); + addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM, bindingContext ); + + if ( useNewIdentifierGenerators ) { + addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG, bindingContext ); + addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA, bindingContext ); + parameterMap.put( + SequenceStyleGenerator.INCREMENT_PARAM, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) ) + ); + parameterMap.put( + SequenceStyleGenerator.INITIAL_PARAM, + String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class, + classLoaderService ) ) + ); + } + else { + if ( JandexHelper.getValue( generator, "initialValue", Integer.class, classLoaderService ) != 1 ) { + LOG.unsupportedInitialValue( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS ); + } + parameterMap.put( + SequenceHiLoGenerator.MAX_LO, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) - 1 ) + ); + } + identifierGeneratorSources.add( new IdentifierGeneratorSourceImpl( name, strategy, parameterMap ) ); + LOG.tracef( "Add sequence generator with name: %s", name ); + } + + private static void bindTableGenerator( + final AnnotationInstance generator, + final List identifierGeneratorSources, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( generator, "name", String.class, classLoaderService ); + + final boolean useNewIdentifierGenerators = bindingContext.getBuildingOptions().isUseNewIdentifierGenerators(); + final String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( + GenerationType.TABLE, + useNewIdentifierGenerators + ); + + final Map parameterMap = new HashMap(); + addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG, bindingContext ); + addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA, bindingContext ); + + if ( useNewIdentifierGenerators ) { + parameterMap.put( TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); + addStringParameter( generator, "table", parameterMap, TableGenerator.TABLE_PARAM, bindingContext ); + addStringParameter( generator, "pkColumnName", parameterMap, TableGenerator.SEGMENT_COLUMN_PARAM, bindingContext ); + addStringParameter( generator, "pkColumnValue", parameterMap, TableGenerator.SEGMENT_VALUE_PARAM, bindingContext ); + addStringParameter( generator, "valueColumnName", parameterMap, TableGenerator.VALUE_COLUMN_PARAM, bindingContext ); + parameterMap.put( + TableGenerator.INCREMENT_PARAM, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) ) + ); + parameterMap.put( + TableGenerator.INITIAL_PARAM, + String.valueOf( JandexHelper.getValue( generator, "initialValue", Integer.class, + classLoaderService ) + 1 ) + ); + } + else { + addStringParameter( generator, "table", parameterMap, MultipleHiLoPerTableGenerator.ID_TABLE, bindingContext ); + addStringParameter( generator, "pkColumnName", parameterMap, MultipleHiLoPerTableGenerator.PK_COLUMN_NAME, bindingContext ); + addStringParameter( generator, "pkColumnValue", parameterMap, MultipleHiLoPerTableGenerator.PK_VALUE_NAME, bindingContext ); + addStringParameter( + generator, + "valueColumnName", + parameterMap, + MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME, + bindingContext + ); + parameterMap.put( + TableHiLoGenerator.MAX_LO, + String.valueOf( JandexHelper.getValue( generator, "allocationSize", Integer.class, + classLoaderService ) - 1 ) + ); + } + if ( JandexHelper.getValue( generator, "uniqueConstraints", AnnotationInstance[].class, + classLoaderService ).length > 0 ) { + LOG.ignoringTableGeneratorConstraints( name ); + } + identifierGeneratorSources.add( new IdentifierGeneratorSourceImpl( name, strategy, parameterMap ) ); + LOG.tracef( "Add table generator with name: %s", name ); + } + + private static class IdentifierGeneratorSourceImpl implements IdentifierGeneratorSource { + private final String generatorName; + private final String generatorImplementationName; + private final Map parameterMap; + + public IdentifierGeneratorSourceImpl( + String generatorName, + String generatorImplementationName, + Map parameterMap) { + this.generatorName = generatorName; + this.generatorImplementationName = generatorImplementationName; + this.parameterMap = parameterMap; + } + + @Override + public String getGeneratorName() { + return generatorName; + } + + @Override + public String getGeneratorImplementationName() { + return generatorImplementationName; + } + + @Override + public Map getParameters() { + return parameterMap; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/QueryProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/QueryProcessor.java new file mode 100644 index 000000000000..d1e8baa4fd0e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/QueryProcessor.java @@ -0,0 +1,541 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.global; + +import java.util.Collection; +import java.util.HashMap; +import javax.persistence.LockModeType; +import javax.persistence.ParameterMode; + +import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; +import org.hibernate.CacheMode; +import org.hibernate.FlushMode; +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.MappingException; +import org.hibernate.annotations.CacheModeType; +import org.hibernate.annotations.FlushModeType; +import org.hibernate.annotations.QueryHints; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.LockModeConverter; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.NamedStoredProcedureQueryDefinition; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * Handles processing of named queries defined via:
        + *
      • + * {@link javax.persistence.NamedQuery} (and + * {@link javax.persistence.NamedQueries}) + *
      • + *
      • + * {@link javax.persistence.NamedNativeQuery} (and + * {@link javax.persistence.NamedNativeQueries}) + *
      • + *
      • + * {@link javax.persistence.NamedStoredProcedureQuery} (and + * {@link javax.persistence.NamedStoredProcedureQueries}) + *
      • + *
      • + * {@link org.hibernate.annotations.NamedQuery} (and + * {@link org.hibernate.annotations.NamedQueries}) + *
      • + *
      • + * {@link org.hibernate.annotations.NamedNativeQuery} (and + * {@link org.hibernate.annotations.NamedNativeQueries}) + *
      • + *
      + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class QueryProcessor { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryProcessor.class ); + + /** + * Disallow direct instantiation + */ + private QueryProcessor() { + } + + /** + * Main entry point into named query processing + * + * @param bindingContext the context for annotation binding + */ + public static void bind(AnnotationBindingContext bindingContext) { + Collection annotations = JandexHelper.collectionAnnotations( + bindingContext.getJandexAccess().getIndex(), + JPADotNames.NAMED_QUERY, + JPADotNames.NAMED_QUERIES + ); + for ( AnnotationInstance query : annotations ) { + bindNamedQuery( bindingContext, query ); + } + + annotations = JandexHelper.collectionAnnotations( + bindingContext.getJandexAccess().getIndex(), + JPADotNames.NAMED_NATIVE_QUERY, + JPADotNames.NAMED_NATIVE_QUERIES + ); + for ( AnnotationInstance query : annotations ) { + bindNamedNativeQuery( query, bindingContext ); + } + + annotations = JandexHelper.collectionAnnotations( + bindingContext.getJandexAccess().getIndex(), + JPADotNames.NAMED_STORED_PROCEDURE_QUERY, + JPADotNames.NAMED_STORED_PROCEDURE_QUERIES + ); + for ( AnnotationInstance query : annotations ) { + bindNamedStoredProcedureQuery( query, bindingContext ); + } + + annotations = JandexHelper.collectionAnnotations( + bindingContext.getJandexAccess().getIndex(), + HibernateDotNames.NAMED_QUERY, + HibernateDotNames.NAMED_QUERIES + ); + for ( AnnotationInstance query : annotations ) { + bindNamedQuery( bindingContext, query ); + } + + annotations = JandexHelper.collectionAnnotations( + bindingContext.getJandexAccess().getIndex(), + HibernateDotNames.NAMED_NATIVE_QUERY, + HibernateDotNames.NAMED_NATIVE_QUERIES + ); + for ( AnnotationInstance query : annotations ) { + bindNamedNativeQuery( query, bindingContext ); + } + } + + /** + * Binds {@link javax.persistence.NamedQuery} as well as {@link org.hibernate.annotations.NamedQuery}. + */ + private static void bindNamedQuery(AnnotationBindingContext bindingContext, AnnotationInstance annotation) { + final ClassLoaderService classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + final String name = JandexHelper.getValue( annotation, "name", String.class, classLoaderService ); + if ( StringHelper.isEmpty( name ) ) { + throw new AnnotationException( "A named query must have a name when used in class or package level" ); + } + NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder(); + builder.setName( name ); + + final String query = JandexHelper.getValue( annotation, "query", String.class, classLoaderService ); + builder.setQuery( query ); + if ( annotation.name().equals( JPADotNames.NAMED_QUERY ) ) { + bindJPANamedQuery( annotation, builder, name, query, bindingContext ); + } else { + builder.setFlushMode( + getFlushMode( JandexHelper.getEnumValue( annotation, "flushMode", FlushModeType.class, classLoaderService ) ) ) + .setCacheable( JandexHelper.getValue( annotation, "cacheable", Boolean.class, classLoaderService ) ) + .setCacheRegion( defaultToNull( JandexHelper.getValue( annotation, "cacheRegion", String.class, classLoaderService ) ) ) + .setFetchSize( defaultToNull( JandexHelper.getValue( annotation, "fetchSize", Integer.class, classLoaderService ) ) ) + .setTimeout( defaultToNull( JandexHelper.getValue( annotation, "timeout", Integer.class, classLoaderService ) ) ) + .setComment( JandexHelper.getValue( annotation, "comment", String.class, classLoaderService ) ) + .setCacheMode( getCacheMode( JandexHelper.getValue( annotation, "cacheMode", CacheModeType.class, classLoaderService ) ) ) + .setReadOnly( JandexHelper.getValue( annotation, "readOnly", Boolean.class, classLoaderService ) ); + } + + + bindingContext.getMetadataCollector().addNamedQuery(builder.createNamedQueryDefinition()); + LOG.debugf( "Binding named query: %s => %s", name, query ); + } + + public static FlushMode getFlushMode(FlushModeType flushModeType) { + FlushMode flushMode; + switch ( flushModeType ) { + case ALWAYS: + flushMode = FlushMode.ALWAYS; + break; + case AUTO: + flushMode = FlushMode.AUTO; + break; + case COMMIT: + flushMode = FlushMode.COMMIT; + break; + case MANUAL: + flushMode = FlushMode.MANUAL; + break; + case PERSISTENCE_CONTEXT: + flushMode = null; + break; + default: + throw new AssertionFailure( "Unknown flushModeType: " + flushModeType ); + } + return flushMode; + } + private static CacheMode getCacheMode(CacheModeType cacheModeType) { + switch ( cacheModeType ) { + case GET: + return CacheMode.GET; + case IGNORE: + return CacheMode.IGNORE; + case NORMAL: + return CacheMode.NORMAL; + case PUT: + return CacheMode.PUT; + case REFRESH: + return CacheMode.REFRESH; + default: + throw new AssertionFailure( "Unknown cacheModeType: " + cacheModeType ); + } + } + + + private static void bindJPANamedQuery( + AnnotationInstance annotation, + NamedQueryDefinitionBuilder builder, + String name, + String query, + AnnotationBindingContext bindingContext){ + final ClassLoaderService classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class, + classLoaderService ); + + String cacheRegion = getString( hints, QueryHints.CACHE_REGION, bindingContext ); + if ( StringHelper.isEmpty( cacheRegion ) ) { + cacheRegion = null; + } + + Integer timeout = getTimeout( hints, query, bindingContext ); + if ( timeout != null && timeout < 0 ) { + timeout = null; + } + //TODO this 'javax.persistence.lock.timeout' has been mvoed to {@code AvailableSettings} in master + //we should change this when we merge this branch back. + Integer lockTimeout = getInteger( hints, "javax.persistence.lock.timeout" , query, bindingContext ); + lockTimeout = defaultToNull( lockTimeout ); + + LockOptions lockOptions = new LockOptions( LockModeConverter.convertToLockMode( JandexHelper.getEnumValue( + annotation, + "lockMode", + LockModeType.class, + classLoaderService + ) ) ); + if ( lockTimeout != null ) { + lockOptions.setTimeOut( lockTimeout ); + } + + builder.setCacheable( getBoolean( hints, QueryHints.CACHEABLE, name, bindingContext ) ) + .setCacheRegion( cacheRegion ) + .setTimeout( timeout ) + .setLockOptions( lockOptions ) + .setFetchSize( defaultToNull( getInteger( hints, QueryHints.FETCH_SIZE, name, bindingContext ) ) ) + .setFlushMode( getFlushMode( hints, QueryHints.FLUSH_MODE, name, bindingContext ) ) + .setCacheMode( getCacheMode( hints, QueryHints.CACHE_MODE, name, bindingContext ) ) + .setReadOnly( getBoolean( hints, QueryHints.READ_ONLY, name, bindingContext ) ) + .setComment( defaultToNull( getString( hints, QueryHints.COMMENT, bindingContext ) ) ) + .setParameterTypes( null ); + } + + private static void bindNamedNativeQuery(AnnotationInstance annotation, AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + String name = JandexHelper.getValue( annotation, "name", String.class, classLoaderService ); + if ( StringHelper.isEmpty( name ) ) { + throw new AnnotationException( "A named native query must have a name when used in class or package level" ); + } + + String query = JandexHelper.getValue( annotation, "query", String.class, classLoaderService ); + + String resultSetMapping = JandexHelper.getValue( annotation, "resultSetMapping", String.class, classLoaderService ); + + AnnotationInstance[] hints = JandexHelper.getValue( annotation, "hints", AnnotationInstance[].class, classLoaderService ); + + boolean cacheable = getBoolean( hints, "org.hibernate.cacheable", name, bindingContext ); + String cacheRegion = getString( hints, QueryHints.CACHE_REGION, bindingContext ); + if ( StringHelper.isEmpty( cacheRegion ) ) { + cacheRegion = null; + } + + Integer timeout = getTimeout( hints, query, bindingContext ); + if ( timeout != null && timeout < 0 ) { + timeout = null; + } + + Integer fetchSize = getInteger( hints, QueryHints.FETCH_SIZE, name, bindingContext ); + if ( fetchSize != null && fetchSize < 0 ) { + fetchSize = null; + } + + FlushMode flushMode = getFlushMode( hints, QueryHints.FLUSH_MODE, name, bindingContext ); + CacheMode cacheMode = getCacheMode( hints, QueryHints.CACHE_MODE, name, bindingContext ); + + boolean readOnly = getBoolean( hints, QueryHints.READ_ONLY, name, bindingContext ); + + String comment = getString( hints, QueryHints.COMMENT, bindingContext ); + if ( StringHelper.isEmpty( comment ) ) { + comment = null; + } + + boolean callable = getBoolean( hints, QueryHints.CALLABLE, name, bindingContext ); + NamedSQLQueryDefinition def; + if ( StringHelper.isNotEmpty( resultSetMapping ) ) { + boolean resultSetMappingExists = bindingContext.getMetadataCollector().getResultSetMappingDefinitions().containsKey( resultSetMapping ); + if ( !resultSetMappingExists ) { + throw new MappingException( + String.format( + "Named SQL Query [%s] referenced an non-existent result set mapping [%s] ", + name, + resultSetMapping + ) + ); + } + def = new NamedSQLQueryDefinitionBuilder().setName( name ) + .setQuery( query ) + .setResultSetRef( + resultSetMapping + ) + .setQuerySpaces( null ) + .setCacheable( cacheable ) + .setCacheRegion( cacheRegion ) + .setTimeout( timeout ) + .setFetchSize( fetchSize ) + .setFlushMode( flushMode ) + .setCacheMode( cacheMode ) + .setReadOnly( readOnly ) + .setComment( comment ) + .setParameterTypes( null ) + .setCallable( callable ) + .createNamedQueryDefinition(); + } + else { + AnnotationValue annotationValue = annotation.value( "resultClass" ); + NativeSQLQueryRootReturn[] queryRoots; + if ( annotationValue == null ) { + // pure native scalar query + queryRoots = new NativeSQLQueryRootReturn[0]; + } + else { + queryRoots = new NativeSQLQueryRootReturn[] { + new NativeSQLQueryRootReturn( + "alias1", + annotationValue.asString(), + new HashMap(), + LockMode.READ + ) + }; + } + def = new NamedSQLQueryDefinitionBuilder().setName( name ) + .setQuery( query ) + .setQueryReturns( queryRoots ) + .setQuerySpaces( null ) + .setCacheable( cacheable ) + .setCacheRegion( cacheRegion ) + .setTimeout( timeout ) + .setFetchSize( fetchSize ) + .setFlushMode( flushMode ) + .setCacheMode( cacheMode ) + .setReadOnly( readOnly ) + .setComment( comment ) + .setParameterTypes( null ) + .setCallable( callable ) + .createNamedQueryDefinition(); + } + bindingContext.getMetadataCollector().addNamedNativeQuery( def ); + LOG.debugf( "Binding named native query: %s => %s", name, query ); + } + + private static void bindNamedStoredProcedureQuery( + AnnotationInstance query, + AnnotationBindingContext bindingContext) { + final String name = query.value( "name" ).asString(); + final String procedureName = query.value( "procedureName" ).asString(); + LOG.debugf( "Starting binding of @NamedStoredProcedureQuery(name=%s, procedureName=%s)", name, procedureName ); + NamedStoredProcedureQueryDefinition.Builder builder = new NamedStoredProcedureQueryDefinition.Builder( + name, + procedureName + ); + + final AnnotationInstance[] parameterAnnotations = JandexHelper.extractAnnotationsValue( + query, + "parameters" + ); + if ( parameterAnnotations != null && parameterAnnotations.length > 0 ) { + for ( AnnotationInstance parameterAnnotation : parameterAnnotations ) { + final AnnotationValue pNameValue = parameterAnnotation.value( "name" ); + final String pName; + if ( pNameValue == null ) { + pName = null; + } + else { + pName = StringHelper.nullIfEmpty( pNameValue.asString() ); + } + + final AnnotationValue pModeValue = parameterAnnotation.value( "mode" ); + final ParameterMode pMode; + if ( pModeValue == null ) { + pMode = ParameterMode.IN; + } + else { + final String pModeName = StringHelper.nullIfEmpty( pModeValue.asEnum() ); + if ( pModeName == null ) { + pMode = ParameterMode.IN; + } + else { + pMode = ParameterMode.valueOf( pModeName ); + } + } + + final AnnotationValue javaTypeValue = parameterAnnotation.value( "type" ); + final String pJavaType; + if ( javaTypeValue == null ) { + pJavaType = null; + } + else { + pJavaType = StringHelper.nullIfEmpty( javaTypeValue.asString() ); + } + + builder.addParameter( pName, pMode, pJavaType ); + } + } + + final AnnotationInstance[] hintAnnotations = JandexHelper.extractAnnotationsValue( + query, + "hints" + ); + if ( hintAnnotations != null && hintAnnotations.length > 0 ) { + for ( AnnotationInstance hintAnnotation : hintAnnotations ) { + builder.addHint( + hintAnnotation.value( "name" ).asString(), + hintAnnotation.value( "value" ).asString() + ); + } + } + + final AnnotationValue resultClassesValue = query.value( "resultClasses" ); + if ( resultClassesValue != null ) { + final String[] resultClassNames = resultClassesValue.asStringArray(); + if ( resultClassNames != null ) { + for ( String resultClassName : resultClassNames ) { + builder.addResultClassName( resultClassName ); + } + } + } + + final AnnotationValue resultSetMappingsValue = query.value( "resultSetMappings" ); + if ( resultSetMappingsValue != null ) { + final String[] resultSetMappingNames = resultSetMappingsValue.asStringArray(); + if ( resultSetMappingNames != null ) { + for ( String resultSetMappingName : resultSetMappingNames ) { + builder.addResultSetMappingName( resultSetMappingName ); + } + } + } + + bindingContext.getMetadataCollector().addNamedStoredProcedureQueryDefinition( + builder.buildDefinition() + ); + } + + private static boolean getBoolean(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null || val.equalsIgnoreCase( "false" ) ) { + return false; + } + if ( val.equalsIgnoreCase( "true" ) ) { + return true; + } + throw new AnnotationException( "Not a boolean in hint: " + query + ":" + element ); + } + + private static CacheMode getCacheMode(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null ) { + return null; + } + try { + return CacheMode.valueOf( val.toUpperCase() ); + } + catch ( IllegalArgumentException e ) { + throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + element ); + } + } + + private static FlushMode getFlushMode(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null ) { + return null; + } + try { + return FlushMode.valueOf( val.toUpperCase() ); + } + catch ( IllegalArgumentException e ) { + throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + element ); + } + } + + private static Integer getInteger(AnnotationInstance[] hints, String element, String query, AnnotationBindingContext bindingContext) { + String val = getString( hints, element, bindingContext ); + if ( val == null ) { + return null; + } + try { + return Integer.decode( val ); + } + catch ( NumberFormatException nfe ) { + throw new AnnotationException( "Not an integer in hint: " + query + ":" + element, nfe ); + } + } + + private static String getString(AnnotationInstance[] hints, String element, AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + for ( AnnotationInstance hint : hints ) { + if ( element.equals( JandexHelper.getValue( hint, "name", String.class, classLoaderService ) ) ) { + return JandexHelper.getValue( hint, "value", String.class, classLoaderService ); + } + } + return null; + } + + private static Integer getTimeout(AnnotationInstance[] hints, String query, AnnotationBindingContext bindingContext) { + Integer timeout = getInteger( hints, QueryHints.TIMEOUT_JPA, query, bindingContext ); + if ( timeout == null ) { + return getInteger( hints, QueryHints.TIMEOUT_HIBERNATE, query, bindingContext ); // timeout is already in seconds + } + return ( ( timeout + 500 ) / 1000 ); // convert milliseconds to seconds (rounded) + } + + private static String defaultToNull( String s ) { + return StringHelper.isEmpty( s ) ? null : s; + } + + private static Integer defaultToNull( Integer i ) { + return i == null || i < 0 ? null : i; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/SqlResultSetProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/SqlResultSetProcessor.java new file mode 100644 index 000000000000..321e743a2226 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/SqlResultSetProcessor.java @@ -0,0 +1,416 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.global; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.LockMode; +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryConstructorReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.SQL_RESULT_SET_MAPPING; +import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.SQL_RESULT_SET_MAPPINGS; + +/** + * Handles processing of SQL ResultSet mappings as defined via + * {@link javax.persistence.SqlResultSetMapping} and + * {@link javax.persistence.SqlResultSetMappings} annotations, including + * their related annotations:
        + *
      • + * {@link javax.persistence.EntityResult} (and + * {@link javax.persistence.FieldResult}) + *
      • + *
      • + * {@link javax.persistence.ColumnResult} + *
      • + *
      • + * {@link javax.persistence.ConstructorResult} + *
      • + *
      + * + * @author Strong Liu + * @author Steve Ebersole + */ +public class SqlResultSetProcessor { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryProcessor.class ); + + /** + * Disallow direct instantiation. + */ + private SqlResultSetProcessor() { + } + + /** + * Main entry point into processing SQL ResultSet mappings + * + * @param bindingContext The binding context + */ + public static void bind(AnnotationBindingContext bindingContext) { + // singular form + { + final Collection sqlResultSetMappingAnnotations = + bindingContext.getJandexAccess().getIndex().getAnnotations( SQL_RESULT_SET_MAPPING ); + for ( final AnnotationInstance sqlResultSetMappingAnnotation : sqlResultSetMappingAnnotations ) { + bindSqlResultSetMapping( sqlResultSetMappingAnnotation, bindingContext ); + } + } + + // plural form + { + final Collection sqlResultSetMappingsAnnotations = + bindingContext.getJandexAccess().getIndex().getAnnotations( SQL_RESULT_SET_MAPPINGS ); + for ( final AnnotationInstance sqlResultSetMappingsAnnotationInstance : sqlResultSetMappingsAnnotations ) { + final AnnotationInstance[] sqlResultSetMappingAnnotations = JandexHelper.extractAnnotationsValue( + sqlResultSetMappingsAnnotationInstance, + "value" + ); + for ( AnnotationInstance sqlResultSetMappingAnnotation : sqlResultSetMappingAnnotations ) { + bindSqlResultSetMapping( sqlResultSetMappingAnnotation, bindingContext ); + } + } + } + } + + private static int entityAliasIndex = 0; + + private static void bindSqlResultSetMapping(AnnotationInstance annotation, AnnotationBindingContext bindingContext) { + entityAliasIndex = 0; + + // `name` is required... + final String name = annotation.value( "name" ).asString(); + LOG.debugf( "Binding @SqlResultSetMapping(name=%s)", name ); + final ResultSetMappingDefinition definition = new ResultSetMappingDefinition( name ); + + final AnnotationInstance[] entityResults = JandexHelper.extractAnnotationsValue( + annotation, + "entities" + ); + if ( entityResults != null && entityResults.length > 0 ) { + for ( AnnotationInstance entityResult : entityResults ) { + bindEntityResult( entityResult, definition, bindingContext ); + } + } + + final AnnotationInstance[] columnResults = JandexHelper.extractAnnotationsValue( + annotation, + "columns" + ); + if ( columnResults != null && columnResults.length > 0 ) { + for ( AnnotationInstance columnResult : columnResults ) { + bindColumnResult( columnResult, definition, bindingContext ); + } + } + + final AnnotationInstance[] constructorResults = JandexHelper.extractAnnotationsValue( + annotation, + "classes" + ); + if ( constructorResults != null && constructorResults.length > 0 ) { + for ( AnnotationInstance constructorResult : constructorResults ) { + bindConstructorResult( constructorResult, definition, bindingContext ); + } + } + + bindingContext.getMetadataCollector().addResultSetMapping( definition ); + } + + private static void bindEntityResult( + final AnnotationInstance entityResult, + final ResultSetMappingDefinition definition, + final AnnotationBindingContext bindingContext) { + final String className = entityResult.value( "entityClass" ).asString(); + final EntityBinding targetEntityBinding = bindingContext.getMetadataCollector().getEntityBinding( className ); + if ( targetEntityBinding == null ) { + throw new MappingException( + String.format( + "Entity [%s] not found in SqlResultMapping [%s]", + className, + definition.getName() + ) + ); + } + + final Map propertyResults = new HashMap(); + + final AnnotationValue discriminatorColumnValue = entityResult.value( "discriminatorColumn" ); + if ( discriminatorColumnValue != null ) { + final String discriminatorColumn = discriminatorColumnValue.asString(); + if ( StringHelper.isNotEmpty( discriminatorColumn ) ) { + propertyResults.put( + "class", + new String[] { normalize( discriminatorColumn, bindingContext ) } + ); + + } + } + + List fieldResultList = reorderFieldResult( + bindingContext, + entityResult, + targetEntityBinding, + definition.getName() + ); + + for ( final FieldResult fieldResult : fieldResultList ) { + insert( fieldResult.column, StringHelper.root( fieldResult.name ), propertyResults ); + } + + final NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn( + "alias" + entityAliasIndex++, + targetEntityBinding.getEntityName(), + propertyResults, + LockMode.READ + ); + definition.addQueryReturn( result ); + } + + private static String normalize(String name, AnnotationBindingContext bindingContext) { + return bindingContext.getMetadataCollector() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( name ); + } + + //todo see org.hibernate.cfg.annotations.ResultsetMappingSecondPass#getSubPropertyIterator + private static List reorderFieldResult( + AnnotationBindingContext bindingContext, + AnnotationInstance entityResult, + EntityBinding entityBinding, + String resultSetMappingDefinitionName) { + final AnnotationInstance[] fieldResultAnnotationInstances = JandexHelper.extractAnnotationsValue( + entityResult, + "fields" + ); + + final List results = new ArrayList( fieldResultAnnotationInstances.length ); + final List propertyNames = new ArrayList(); + final Set uniqueReturnProperty = new HashSet(); + + for ( final AnnotationInstance fieldResult : fieldResultAnnotationInstances ) { + final String name = fieldResult.value( "name" ).asString(); + if ( !uniqueReturnProperty.add( name ) ) { + throw new MappingException( + "duplicate @FieldResult for property " + name + + " on @Entity " + entityBinding.getEntityName() + + " in " + resultSetMappingDefinitionName + ); + } + if ( "class".equals( name ) ) { + throw new MappingException( + "class is not a valid property name to use in a @FieldResult, " + + "use @EntityResult(discriminatorColumn) instead" + ); + } + + final String column = fieldResult.value( "column" ).asString(); + final String quotingNormalizedColumnName = normalize( column, bindingContext ); + if ( name.contains( "." ) ) { + int dotIndex = name.lastIndexOf( '.' ); + String reducedName = name.substring( 0, dotIndex ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( reducedName ); + Iterable attributeBindings = null; + if ( EmbeddedAttributeBinding.class.isInstance( attributeBinding ) ) { + EmbeddedAttributeBinding embeddedAttributeBinding = EmbeddedAttributeBinding.class.cast( + attributeBinding + ); + attributeBindings = embeddedAttributeBinding.getEmbeddableBinding().attributeBindings(); + + } + else if ( ManyToOneAttributeBinding.class.isInstance( attributeBinding ) ) { + ManyToOneAttributeBinding manyToOneAttributeBinding = ManyToOneAttributeBinding.class.cast( + attributeBinding + ); + EntityBinding referencedEntityBinding = manyToOneAttributeBinding.getReferencedEntityBinding(); + Set referencingAttributeBindings = manyToOneAttributeBinding.getEntityReferencingAttributeBindings(); + + if ( CollectionHelper.isNotEmpty( referencingAttributeBindings ) ) { + attributeBindings = referencingAttributeBindings; + } + else { +// EntityIdentifierNature entityIdentifierNature= referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getNature(); +// switch ( entityIdentifierNature ) { +// case SIMPLE: +// throw new MappingException( +// "dotted notation reference neither a component nor a many/one to one" +// ); +// case AGGREGATED_COMPOSITE: +// case COMPOSITE: +// referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().isSingleAttribute();//.isIdentifierMapper(); +// } + //todo check if this logic is correct + SingularAttributeBinding identifierAttributeBinding = referencedEntityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding(); + if ( EmbeddedAttributeBinding.class.isInstance( identifierAttributeBinding ) ) { + attributeBindings = EmbeddedAttributeBinding.class.cast( identifierAttributeBinding ) + .getEmbeddableBinding() + .attributeBindings(); + } + else { + throw new MappingException( + "dotted notation reference neither a component nor a many/one to one" + ); + } + } + + + } + else { + throw new MappingException( "dotted notation reference neither a component nor a many/one to one" ); + } + List followers = getFollowers( attributeBindings, reducedName, name ); + int index = results.size(); + int followersSize = followers.size(); + for ( int loop = 0; loop < followersSize; loop++ ) { + String follower = followers.get( loop ); + int currentIndex = getIndexOfFirstMatchingProperty( propertyNames, follower ); + index = currentIndex != -1 && currentIndex < index ? currentIndex : index; + } + propertyNames.add( index, name ); + results.add( index, new FieldResult( name, quotingNormalizedColumnName ) ); + } + else { + propertyNames.add( name ); + results.add( new FieldResult( name, quotingNormalizedColumnName ) ); + } + + } + return results; + } + + private static int getIndexOfFirstMatchingProperty(List propertyNames, String follower) { + int propertySize = propertyNames.size(); + for ( int propIndex = 0; propIndex < propertySize; propIndex++ ) { + if ( ( propertyNames.get( propIndex ) ).startsWith( follower ) ) { + return propIndex; + } + } + return -1; + } + + private static class FieldResult { + String name; + String column; + + private FieldResult(String column, String name) { + this.column = column; + this.name = name; + } + } + + private static List getFollowers(Iterable attributeBindings, String reducedName, String name) { + boolean hasFollowers = false; + List followers = new ArrayList(); + for ( final AttributeBinding attributeBinding : attributeBindings ) { + String currentPropertyName = attributeBinding.getAttribute().getName(); + String currentName = reducedName + '.' + currentPropertyName; + if ( hasFollowers ) { + followers.add( currentName ); + } + if ( name.equals( currentName ) ) { + hasFollowers = true; + } + } + return followers; + } + + + private static void insert(String key, String value, Map map) { + if ( map.containsKey( key ) ) { + String[] oldValues = map.get( key ); + String[] values = Arrays.copyOf( oldValues, oldValues.length + 1 ); + values[oldValues.length] = value; + map.put( key, values ); + } + else { + map.put( key, new String[] { value } ); + } + } + + private static void bindColumnResult( + AnnotationInstance columnResult, + ResultSetMappingDefinition definition, + AnnotationBindingContext bindingContext) { + definition.addQueryReturn( extractColumnResult( columnResult, bindingContext ) ); + } + + private static NativeSQLQueryScalarReturn extractColumnResult( + AnnotationInstance columnResult, + AnnotationBindingContext bindingContext) { + // `name` is required + final String name = columnResult.value( "name" ).asString(); + final String normalizedName = normalize( name, bindingContext ); + //todo TYPE + return new NativeSQLQueryScalarReturn( normalizedName, null ); + } + + private static void bindConstructorResult( + AnnotationInstance constructorResult, + ResultSetMappingDefinition definition, + AnnotationBindingContext bindingContext) { + final Class classToConstruct = bindingContext.getServiceRegistry() + .getService( ClassLoaderService.class ) + .classForName( constructorResult.value( "targetClass" ).asString() ); + + final List columns = new ArrayList(); + final AnnotationInstance[] columnResults = JandexHelper.extractAnnotationsValue( + constructorResult, + "columns" + ); + if ( columnResults != null && columnResults.length > 0 ) { + for ( AnnotationInstance columnResult : columnResults ) { + columns.add( extractColumnResult( columnResult, bindingContext ) ); + } + } + + definition.addQueryReturn( + new NativeSQLQueryConstructorReturn( classToConstruct, columns ) + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/TableProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/TableProcessor.java new file mode 100644 index 000000000000..61c2fdf83275 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/global/TableProcessor.java @@ -0,0 +1,156 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.global; + +import java.util.Collection; + +import org.hibernate.MappingException; +import org.hibernate.annotations.FetchMode; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.util.AnnotationParserHelper; +import org.hibernate.metamodel.source.internal.annotations.util.EnumConversionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Binds table related information. This binder is called after the entities are bound. + * + * @author Hardy Ferentschik + */ +public class TableProcessor { + + private TableProcessor() { + } + + /** + * Binds {@link org.hibernate.annotations.Tables} and {@link org.hibernate.annotations.Table} annotations to the supplied + * metadata. + * + * @param bindingContext the context for annotation binding + */ + public static void bind(AnnotationBindingContext bindingContext) { + Collection annotations = bindingContext.getJandexAccess().getIndex().getAnnotations( HibernateDotNames.TABLE ); + for ( AnnotationInstance tableAnnotation : annotations ) { + bind( bindingContext, tableAnnotation ); + } + + annotations = bindingContext.getJandexAccess().getIndex().getAnnotations( HibernateDotNames.TABLES ); + for ( AnnotationInstance tables : annotations ) { + for ( AnnotationInstance table : JandexHelper.getValue( tables, "value", AnnotationInstance[].class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ) ) { + bind( bindingContext, table ); + } + } + } + + private static void bind(AnnotationBindingContext bindingContext, AnnotationInstance tableAnnotation) { + InFlightMetadataCollector metadataCollector = bindingContext.getMetadataCollector(); + String tableName = JandexHelper.getValue( tableAnnotation, "appliesTo", String.class, + bindingContext.getServiceRegistry().getService( ClassLoaderService.class ) ); + ObjectName objectName = ObjectName.parse( tableName ); + Schema schema = metadataCollector.getDatabase().getSchema( objectName.getCatalog(), objectName.getSchema() ); + Table table = schema.locateTable( objectName.getName() ); + if ( table != null ) { + boolean isSecondaryTable = metadataCollector.getSecondaryTables().containsKey( table.getLogicalName() ); + bindHibernateTableAnnotation( table, tableAnnotation,isSecondaryTable, bindingContext ); + } + else { + throw new MappingException( "Can't find table[" + tableName + "] from Annotation @Table" ); + } + } + + private static void bindHibernateTableAnnotation( + final Table table, + final AnnotationInstance tableAnnotation, + final boolean isSecondaryTable, + final AnnotationBindingContext bindingContext) { + final ClassLoaderService classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class ); + String comment = JandexHelper.getValue( tableAnnotation, "comment", String.class, + classLoaderService ); + if ( StringHelper.isNotEmpty( comment ) ) { + table.addComment( comment.trim() ); + } + if ( !isSecondaryTable ) { + return; + } + SecondaryTable secondaryTable = bindingContext.getMetadataCollector().getSecondaryTables().get( table.getLogicalName() ); + if ( tableAnnotation.value( "fetch" ) != null ) { + FetchMode fetchMode = JandexHelper.getEnumValue( tableAnnotation, "fetch", FetchMode.class, + classLoaderService ); + secondaryTable.setFetchStyle( EnumConversionHelper.annotationFetchModeToFetchStyle( fetchMode ) ); + } + if ( tableAnnotation.value( "inverse" ) != null ) { + secondaryTable.setInverse( tableAnnotation.value( "inverse" ).asBoolean() ); + } + if ( tableAnnotation.value( "optional" ) != null ) { + secondaryTable.setOptional( tableAnnotation.value( "optional" ).asBoolean() ); + } + + if ( tableAnnotation.value( "sqlInsert" ) != null ) { + secondaryTable.setCustomInsert( + AnnotationParserHelper.createCustomSQL( + tableAnnotation.value( "sqlInsert" ) + .asNested() + ) + ); + } + if ( tableAnnotation.value( "sqlUpdate" ) != null ) { + secondaryTable.setCustomUpdate( + AnnotationParserHelper.createCustomSQL( + tableAnnotation.value( "sqlUpdate" ) + .asNested() + ) + ); + + } + if ( tableAnnotation.value( "sqlDelete" ) != null ) { + secondaryTable.setCustomDelete( + AnnotationParserHelper.createCustomSQL( + tableAnnotation.value( "sqlDelete" ) + .asNested() + ) + ); + } + // TODO: ForeignKey is not binded right now, because constrint name is not modifyable after it is set + // another option would be create something like tableDefinition and look up it when we bind table / secondary table + +// if ( tableAnnotation.value( "foreignKey" ) != null ) { +// AnnotationInstance foreignKeyAnnotation = tableAnnotation.value( "foreignKey" ).asNested(); +// if ( foreignKeyAnnotation.value( "name" ) != null ) { +// secondaryTable.getForeignKeyReference().setName( foreignKeyAnnotation.value( "name" ).asString() ); +// } +// } + + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/package.html new file mode 100755 index 000000000000..2891a8165f98 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/package.html @@ -0,0 +1,34 @@ + + + + + +

      + This package contains the implementations of the source interfaces defined in + org.hibernate.metamodel.spi.source +

      + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/AnnotationParserHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/AnnotationParserHelper.java new file mode 100644 index 000000000000..dd68b48793b8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/AnnotationParserHelper.java @@ -0,0 +1,199 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.util.List; +import java.util.Map; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; +import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.CustomSQL; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Some annotation processing is identical between entity and attribute level (aka you can place the annotation on + * entity as well as attribute level. This class tries to avoid code duplication for these cases. + * + * @author Hardy Ferentschik + */ +public class AnnotationParserHelper { + + // should not be instantiated + private AnnotationParserHelper() { + + } + + + public static CustomSQL processCustomSqlAnnotation( + DotName annotationName, + Map> annotations, + ClassInfo target) { + final AnnotationInstance sqlAnnotation = JandexHelper.getSingleAnnotation( annotations, annotationName, target ); + + return createCustomSQL( sqlAnnotation ); + } + + public static CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation) { + if ( customSqlAnnotation == null ) { + return null; + } + + final String sql = customSqlAnnotation.value( "sql" ).asString(); + final boolean isCallable = customSqlAnnotation.value( "callable" ) != null + && customSqlAnnotation.value( "callable" ).asBoolean(); + + final ExecuteUpdateResultCheckStyle checkStyle = customSqlAnnotation.value( "check" ) == null + ? isCallable + ? ExecuteUpdateResultCheckStyle.NONE + : ExecuteUpdateResultCheckStyle.COUNT + : ExecuteUpdateResultCheckStyle.valueOf( customSqlAnnotation.value( "check" ).asEnum() ); + + return new CustomSQL( sql, isCallable, checkStyle ); + } + + public static JavaTypeDescriptor resolveCollectionElementType( + MemberDescriptor member, + EntityBindingContext context) { + final AnnotationInstance annotation; + final String targetElementName; + + final AnnotationInstance oneToManyAnnotation = member.getAnnotations().get( JPADotNames.ONE_TO_MANY ); + final AnnotationInstance manyToManyAnnotation = member.getAnnotations().get( JPADotNames.MANY_TO_MANY ); + final AnnotationInstance elementCollectionAnnotation = member.getAnnotations().get( JPADotNames.ELEMENT_COLLECTION ); + + int nonNullCount = countNonNull( oneToManyAnnotation, manyToManyAnnotation, elementCollectionAnnotation ); + + if ( nonNullCount > 1 ) { + throw context.makeMappingException( + "Attribute [" + member.toString() + + "] may contain only one of @OneToMany, @ManyToMany, @ElementCollection" + ); + } + + if ( oneToManyAnnotation != null ) { + annotation = oneToManyAnnotation; + targetElementName = "targetEntity"; + } + else if ( manyToManyAnnotation != null ) { + annotation = manyToManyAnnotation; + targetElementName = "targetEntity"; + } + else if ( elementCollectionAnnotation != null ) { + annotation = elementCollectionAnnotation; + targetElementName = "targetClass"; + } + else { + annotation = null; + targetElementName = null; + } + + if ( annotation != null && annotation.value( targetElementName ) != null ) { + final String typeName = JandexHelper.getValue( + annotation, + targetElementName, + String.class, + context.getServiceRegistry().getService( ClassLoaderService.class ) + ); + return context.getJavaTypeDescriptorRepository().getType( + context.getJavaTypeDescriptorRepository().buildName( typeName ) + ); + } + + if ( ArrayDescriptor.class.isInstance( member.getType().getErasedType() ) ) { + return ( (ArrayDescriptor) member.getType().getErasedType() ).getComponentType(); + } + + if ( member.getType().getResolvedParameterTypes().isEmpty() ) { + return null; // no generic at all + } + + // for non-maps, the element type is the first resolved parameter type. + // For maps, the second + + final JavaTypeDescriptor attributeType = member.getType().getErasedType(); + if ( context.getJavaTypeDescriptorRepository().jdkMapDescriptor().isAssignableFrom( attributeType ) ) { + return member.getType().getResolvedParameterTypes().get( 1 ); + } + else if ( context.getJavaTypeDescriptorRepository().jdkCollectionDescriptor().isAssignableFrom( attributeType ) ) { + return member.getType().getResolvedParameterTypes().get( 0 ); + } + + return null; + } + + private static int countNonNull(Object... things) { + if ( things == null ) { + throw new IllegalArgumentException( "Things passed to count cannot be null" ); + } + + int count = 0; + for ( Object thing : things ) { + if ( thing != null ) { + count++; + } + } + return count; + } + + public static JavaTypeDescriptor resolveMapKeyType( + MemberDescriptor member, + EntityBindingContext localBindingContext) { + final JavaTypeDescriptor attributeType = member.getType().getErasedType(); + final JavaTypeDescriptor jdkMapType = localBindingContext.getJavaTypeDescriptorRepository().jdkMapDescriptor(); + + JavaTypeDescriptor mapKeyType = null; + if ( jdkMapType.isAssignableFrom( attributeType ) + && !member.getType().getResolvedParameterTypes().isEmpty()) { + mapKeyType = member.getType().getResolvedParameterTypes().get( 0 ); + } + + return mapKeyType; + } + + public static NaturalIdMutability determineNaturalIdMutability( + ManagedTypeMetadata container, + MemberDescriptor member) { + final AnnotationInstance naturalIdAnnotation = member.getAnnotations().get( HibernateDotNames.NATURAL_ID ); + if ( naturalIdAnnotation == null ) { + return container.getContainerNaturalIdMutability(); + } + + final boolean mutable = naturalIdAnnotation.value( "mutable" ) != null + && naturalIdAnnotation.value( "mutable" ).asBoolean(); + return mutable + ? NaturalIdMutability.MUTABLE + : NaturalIdMutability.IMMUTABLE; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/AssociationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/AssociationHelper.java new file mode 100644 index 000000000000..a9ef8271ed5b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/AssociationHelper.java @@ -0,0 +1,415 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.FetchType; + +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.LazyToOneOption; +import org.hibernate.annotations.NotFoundAction; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.FetchStyle; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.annotations.attribute.Column; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * A helper with utilities for working with associations + * + * @author Steve Ebersole + */ +public class AssociationHelper { + private static final CoreMessageLogger log = CoreLogging.messageLogger( AssociationHelper.class ); + + /** + * Singleton access + */ + public static final AssociationHelper INSTANCE = new AssociationHelper(); + + private AssociationHelper() { + } + + + /** + * Determine the concrete "target type" name + * + * @param backingMember The attribute member + * @param associationAnnotation The annotation that identifies the "association" + * @param defaultTargetType The default type for the target. For singular attributes, this is the + * attribute type; for plural attributes it is the element type. + * @param context The binding context + * + * @return The concrete type name + */ + public String determineTarget( + MemberDescriptor backingMember, + AnnotationInstance associationAnnotation, + JavaTypeDescriptor defaultTargetType, + EntityBindingContext context) { + final AnnotationInstance targetAnnotation = backingMember.getAnnotations().get( HibernateDotNames.TARGET ); + if ( targetAnnotation != null ) { + return targetAnnotation.value().asString(); + } + + final AnnotationValue targetEntityValue = associationAnnotation.value( "targetEntity" ); + if ( targetEntityValue != null ) { + return targetEntityValue.asString(); + } + + if ( defaultTargetType == null ) { + throw context.makeMappingException( + "Could not determine target for association : " + backingMember.toString() + ); + } + + return defaultTargetType.getName().toString(); + } + + /** + * Determine the name of the attribute that is the other side of this association, which + * contains mapping metadata. + * + * @param associationAnnotation The annotation that identifies the "association" + * + * @return The specified mapped-by attribute name, or {@code null} if none specified + */ + public String determineMappedByAttributeName(AnnotationInstance associationAnnotation) { + if ( associationAnnotation == null ) { + return null; + } + + final AnnotationValue mappedByAnnotationValue = associationAnnotation.value( "mappedBy" ); + if ( mappedByAnnotationValue == null ) { + return null; + } + + return mappedByAnnotationValue.asString(); + } + + /** + * Given a member that is fetchable, determine the indicated FetchStyle + * + * @param backingMember The fetchable attribute member + * + * @return The indicated FetchStyle, or {@code null} if no indication was given + */ + public FetchStyle determineFetchStyle(MemberDescriptor backingMember) { + final AnnotationInstance fetchAnnotation = backingMember.getAnnotations().get( HibernateDotNames.FETCH ); + if ( fetchAnnotation == null ) { + return null; + } + + final org.hibernate.annotations.FetchMode annotationFetchMode = org.hibernate.annotations.FetchMode.valueOf( + fetchAnnotation.value().asEnum() + ); + return EnumConversionHelper.annotationFetchModeToFetchStyle( annotationFetchMode ); + } + + /** + * Determine whether the given (fetchable?) association is considered lazy. + * + * @param associationAnnotation The annotation that identifies the "association" + * @param lazyAnnotation The Hibernate-specific lazy annotation for attributes of the given nature. Generally + * {@link org.hibernate.annotations.LazyCollection} or {@link org.hibernate.annotations.LazyToOne} + * @param backingMember The fetchable attribute member + * @param fetchStyle The specified fetch style + * + * @return whether its considered lazy, duh :) + */ + public boolean determineWhetherIsLazy( + AnnotationInstance associationAnnotation, + AnnotationInstance lazyAnnotation, + MemberDescriptor backingMember, + FetchStyle fetchStyle, + boolean isCollection) { + + // first precedence + // - join fetches cannot be lazy : fetch style + if ( fetchStyle != null ) { + if ( fetchStyle == FetchStyle.JOIN ) { + return false; + } + } + + // second precedence + // - join fetches cannot be lazy : fetch annotation + final AnnotationInstance fetchAnnotation = backingMember.getAnnotations().get( + HibernateDotNames.FETCH + ); + if ( fetchAnnotation != null ) { + if ( FetchMode.valueOf( fetchAnnotation.value().asEnum() ) == FetchMode.JOIN ) { + return false; + } + } + + // 3rd precedence + final AnnotationValue fetchValue = associationAnnotation.value( "fetch" ); + if ( fetchValue != null ) { + return FetchType.LAZY == FetchType.valueOf( fetchValue.asEnum() ); + } + + // 4th precedence + if ( lazyAnnotation != null ) { + final AnnotationValue value = lazyAnnotation.value(); + if ( value != null ) { + return !"FALSE".equals( value.asEnum() ); + } + } + + // by default collections are lazy, to-ones are not + return isCollection; + } + + + public boolean determineOptionality(AnnotationInstance associationAnnotation) { + // todo : is this only valid for singular association attributes? + + boolean optional = true; + + AnnotationValue optionalValue = associationAnnotation.value( "optional" ); + if ( optionalValue != null ) { + optional = optionalValue.asBoolean(); + } + + return optional; + } + + public boolean determineWhetherToUnwrapProxy(MemberDescriptor backingMember) { + final AnnotationInstance lazyToOne = backingMember.getAnnotations().get( HibernateDotNames.LAZY_TO_ONE ); + return lazyToOne != null && LazyToOneOption.valueOf( lazyToOne.value().asEnum() ) == LazyToOneOption.NO_PROXY; + + } + + public Set determineCascadeTypes(AnnotationInstance associationAnnotation) { + Set cascadeTypes = new HashSet(); + AnnotationValue cascadeValue = associationAnnotation.value( "cascade" ); + if ( cascadeValue != null ) { + String[] cascades = cascadeValue.asEnumArray(); + for ( String s : cascades ) { + cascadeTypes.add( Enum.valueOf( CascadeType.class, s ) ); + } + } + return cascadeTypes; + } + + public Set determineHibernateCascadeTypes(MemberDescriptor backingMember) { + final AnnotationInstance cascadeAnnotation = backingMember.getAnnotations().get( HibernateDotNames.CASCADE ); + + if ( cascadeAnnotation != null ) { + final AnnotationValue cascadeValue = cascadeAnnotation.value(); + if ( cascadeValue != null ) { + final String[] cascades = cascadeValue.asEnumArray(); + if ( cascades != null && cascades.length > 0 ) { + final Set cascadeTypes + = new HashSet(); + for ( String cascade : cascades ) { + cascadeTypes.add( + org.hibernate.annotations.CascadeType.valueOf( cascade ) + ); + } + return cascadeTypes; + } + } + } + + return Collections.emptySet(); + } + + @SuppressWarnings("SimplifiableIfStatement") + public boolean determineOrphanRemoval(AnnotationInstance associationAnnotation) { + final AnnotationValue orphanRemovalValue = associationAnnotation.value( "orphanRemoval" ); + if ( orphanRemovalValue != null ) { + return orphanRemovalValue.asBoolean(); + } + return false; + } + + public String determineMapsId( + MemberDescriptor member, + PersistentAttribute.Nature attributeNature, + EntityBindingContext localBindingContext) { + final AnnotationInstance mapsIdAnnotation = member.getAnnotations().get( JPADotNames.MAPS_ID ); + if ( mapsIdAnnotation == null ) { + return null; + } + + // only valid for to-one associations + if ( !PersistentAttribute.Nature.MANY_TO_ONE.equals( attributeNature ) + && !PersistentAttribute.Nature.MANY_TO_ONE.equals( attributeNature ) ) { + throw localBindingContext.makeMappingException( + "@MapsId can only be specified on a many-to-one or one-to-one " + + "associations, property: " + member.toString() + ); + } + return mapsIdAnnotation.value() == null + ? null + : mapsIdAnnotation.value().asString(); + } + + public boolean determineWhetherToIgnoreNotFound(MemberDescriptor backingMember) { + final AnnotationInstance notFoundAnnotation = backingMember.getAnnotations().get( + HibernateDotNames.NOT_FOUND + ); + if ( notFoundAnnotation != null ) { + final AnnotationValue actionValue = notFoundAnnotation.value( "action" ); + if ( actionValue != null ) { + return NotFoundAction.valueOf( actionValue.asEnum() ) == NotFoundAction.IGNORE; + } + } + + return false; + } + + + + public void processJoinColumnAnnotations( + MemberDescriptor backingMember, + ArrayList joinColumnValues, + EntityBindingContext context) { + final ClassLoaderService classLoaderService = context.getServiceRegistry().getService( ClassLoaderService.class ); + + final Collection joinColumnAnnotations = JandexHelper.getCombinedAnnotations( + backingMember.getAnnotations(), + JPADotNames.JOIN_COLUMN, + JPADotNames.JOIN_COLUMNS, + classLoaderService + ); + for ( AnnotationInstance joinColumnAnnotation : joinColumnAnnotations ) { + joinColumnValues.add( new Column( joinColumnAnnotation ) ); + } + + // @JoinColumn as part of @CollectionTable + AnnotationInstance collectionTableAnnotation = backingMember.getAnnotations().get( + JPADotNames.COLLECTION_TABLE + ); + if ( collectionTableAnnotation != null ) { + final AnnotationInstance[] joinColumnsList = JandexHelper.getValue( + collectionTableAnnotation, + "joinColumns", + AnnotationInstance[].class, + classLoaderService + ); + for ( AnnotationInstance annotation : joinColumnsList ) { + joinColumnValues.add( new Column( annotation ) ); + } + } + } + + public void processJoinTableAnnotations( + MemberDescriptor backingMember, + ArrayList joinColumnValues, + ArrayList inverseJoinColumnValues, + EntityBindingContext context) { + // @JoinColumn as part of @JoinTable + final AnnotationInstance joinTableAnnotation = backingMember.getAnnotations().get( + JPADotNames.JOIN_TABLE + ); + + if ( joinTableAnnotation == null ) { + return; + } + + // first process the `joinColumns` attribute + final AnnotationInstance[] joinColumns = JandexHelper.getValue( + joinTableAnnotation, + "joinColumns", + AnnotationInstance[].class, + context.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance annotation : joinColumns ) { + joinColumnValues.add( new Column( annotation ) ); + } + + // then the `inverseJoinColumns` attribute + final AnnotationInstance[] inverseJoinColumns = JandexHelper.getValue( + joinTableAnnotation, + "inverseJoinColumns", + AnnotationInstance[].class, + context.getServiceRegistry().getService( ClassLoaderService.class ) + ); + for ( AnnotationInstance annotation : inverseJoinColumns ) { + inverseJoinColumnValues.add( new Column( annotation ) ); + } + } + + public AnnotationInstance extractExplicitJoinTable(MemberDescriptor backingMember, EntityBindingContext context) { + final AnnotationInstance collectionTableAnnotation = backingMember.getAnnotations().get( + JPADotNames.COLLECTION_TABLE + ); + final AnnotationInstance joinTableAnnotation = backingMember.getAnnotations().get( + JPADotNames.JOIN_TABLE + ); + + if ( collectionTableAnnotation != null && joinTableAnnotation != null ) { + throw context.makeMappingException( + log.collectionTableAndJoinTableUsedTogether( + context.getOrigin().getName(), + backingMember.getName() + ) + ); + } + + if ( collectionTableAnnotation != null ) { + if ( backingMember.getAnnotations().get( JPADotNames.ELEMENT_COLLECTION ) == null ) { + throw context.makeMappingException( + log.collectionTableWithoutElementCollection( + context.getOrigin().getName(), + backingMember.getName() + ) + ); + } + return collectionTableAnnotation; + } + + if ( joinTableAnnotation != null ) { + if ( backingMember.getAnnotations().get( JPADotNames.ONE_TO_ONE ) == null + && backingMember.getAnnotations().get( JPADotNames.ONE_TO_MANY ) == null + && backingMember.getAnnotations().get( JPADotNames.MANY_TO_MANY ) == null + && backingMember.getAnnotations().get( JPADotNames.MANY_TO_ONE ) == null) { + throw context.makeMappingException( + log.joinTableForNonAssociationAttribute( + context.getOrigin().getName(), + backingMember.getName() + ) + ); + } + return joinTableAnnotation; + } + + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/ConverterAndOverridesHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/ConverterAndOverridesHelper.java new file mode 100644 index 000000000000..afead838afbd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/ConverterAndOverridesHelper.java @@ -0,0 +1,300 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.util.regex.Pattern; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.source.internal.AttributeConversionInfo; +import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride; +import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector; +import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.spi.AttributePath; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; + +/** + * Helper for working with AttributeConverters, AttributeOverrides and AssociationOverrides + * + * @author Steve Ebersole + */ +public class ConverterAndOverridesHelper { + private static final Logger log = Logger.getLogger( ConverterAndOverridesHelper.class ); + + /** + * Singleton access + */ + public static final ConverterAndOverridesHelper INSTANCE = new ConverterAndOverridesHelper(); + + private ConverterAndOverridesHelper() { + } + + + /** + * Process Convert/Converts annotations found on the member for an attribute. + * + * @param path The path to the attribute + * @param nature The attribute nature + * @param backingMember The descriptor for the Java member backing the attribute + * @param container The attribute container (where converters are collected) + * @param context The binding context + */ + public void processConverters( + AttributePath path, + PersistentAttribute.Nature nature, + MemberDescriptor backingMember, + OverrideAndConverterCollector container, + EntityBindingContext context) { + { + final AnnotationInstance convertAnnotation = backingMember.getAnnotations().get( JPADotNames.CONVERT ); + if ( convertAnnotation != null ) { + processConverter( convertAnnotation, path, nature, container, backingMember, context ); + } + } + + { + final AnnotationInstance convertsAnnotation = backingMember.getAnnotations().get( JPADotNames.CONVERTS ); + if ( convertsAnnotation != null ) { + final AnnotationInstance[] convertAnnotations = JandexHelper.extractAnnotationsValue( + convertsAnnotation, + "value" + ); + for ( AnnotationInstance convertAnnotation : convertAnnotations ) { + processConverter( convertAnnotation, path, nature, container, backingMember, context ); + } + } + } + } + + private void processConverter( + AnnotationInstance convertAnnotation, + AttributePath path, + PersistentAttribute.Nature nature, + OverrideAndConverterCollector container, + MemberDescriptor backingMember, + EntityBindingContext context) { + final AttributeConversionInfo conversionInfo; + + final AnnotationValue isDisabledValue = convertAnnotation.value( "disableConversion" ); + final boolean isDisabled = isDisabledValue != null && isDisabledValue.asBoolean(); + if ( isDisabled ) { + // no need to even touch the class + conversionInfo = new AttributeConversionInfo( false, null ); + } + else { + final AnnotationValue converterClassNameValue = convertAnnotation.value( "converter" ); + // if `converterValue` is null, not sure this annotation really serves any purpose... + String converterClassName = converterClassNameValue == null + ? null + : converterClassNameValue.asString(); + if ( "void".equals( converterClassName ) ) { + converterClassName = null; + } + + if ( converterClassName == null ) { + // again, at this point not really sure what purpose this annotation serves + + return; + } + conversionInfo = new AttributeConversionInfo( + true, + (ClassDescriptor) context.getJavaTypeDescriptorRepository().getType( + DotName.createSimple( converterClassName ) + ) + ); + } + + final AnnotationValue specifiedNameValue = convertAnnotation.value( "attributeName" ); + final String specifiedName = specifiedNameValue == null + ? null + : StringHelper.nullIfEmpty( specifiedNameValue.asString() ); + + if ( specifiedName == null ) { + // No attribute name was specified. According to the spec, this is + // ok (in fact expected) if the attribute is basic in nature + if ( nature != PersistentAttribute.Nature.BASIC + && nature != PersistentAttribute.Nature.ELEMENT_COLLECTION_BASIC ) { + // now here we CAN throw the exception + throw context.makeMappingException( + "Found @Convert with no `attributeName` specified on a non-basic attribute : " + backingMember.toString() + ); + } + container.registerConverter( path, conversionInfo ); + } + else { + // An attribute name was specified. Technically we should make + // sure that the attribute is NOT basic in nature. Collections are + // a bit difficult here since the element/map-key could be basic while + // the converter refers to the other which is non-basic + if ( nature == PersistentAttribute.Nature.BASIC ) { + log.debugf( + "Found @Convert with `attributeName` specified (%s) on a non-basic attribute : %s", + specifiedName, + backingMember.toString() + ); + } + container.registerConverter( buildAttributePath( path, specifiedName ), conversionInfo ); + } + } + + private AttributePath buildAttributePath(AttributePath base, String specifiedName) { + assert base != null; + assert specifiedName != null; + + // these names can contain paths themselves... + AttributePath pathSoFar = base; + for ( String pathPart : specifiedName.split( Pattern.quote( "." ) ) ) { + pathSoFar = pathSoFar.append( pathPart ); + } + + return pathSoFar; + } + + + /** + * Process AttributeConverter (plus plural) annotations found on the member for an attribute. + * + * @param path The path to the attribute + * @param backingMember The descriptor for the Java member backing the attribute + * @param container The attribute container (where overrides are collected) + * @param context The binding context + */ + public void processAttributeOverrides( + AttributePath path, + MemberDescriptor backingMember, + OverrideAndConverterCollector container, + EntityBindingContext context) { + processAttributeOverrides( + path, + backingMember.getAnnotations().get( JPADotNames.ATTRIBUTE_OVERRIDE ), + backingMember.getAnnotations().get( JPADotNames.ATTRIBUTE_OVERRIDES ), + container, + context + ); + } + + private void processAttributeOverrides( + AttributePath path, + AnnotationInstance singular, + AnnotationInstance plural, + OverrideAndConverterCollector container, + EntityBindingContext context) { + if ( singular != null ) { + processAttributeOverride( singular, path, container, context ); + } + + if ( plural != null ) { + final AnnotationInstance[] overrideAnnotations = JandexHelper.extractAnnotationsValue( + plural, + "value" + ); + for ( AnnotationInstance overrideAnnotation : overrideAnnotations ) { + processAttributeOverride( overrideAnnotation, path, container, context ); + } + } + + } + + private void processAttributeOverride( + AnnotationInstance overrideAnnotation, + AttributePath path, + OverrideAndConverterCollector container, + EntityBindingContext context) { + // the name is required... + final String specifiedPath = overrideAnnotation.value( "name" ).asString(); + container.registerAttributeOverride( + buildAttributePath( path, specifiedPath ), + new AttributeOverride( path.getFullPath(), overrideAnnotation, context ) + ); + } + + public void processAssociationOverrides( + AttributePath path, + MemberDescriptor backingMember, + OverrideAndConverterCollector container, + EntityBindingContext context) { + { + final AnnotationInstance overrideAnnotation = backingMember.getAnnotations().get( JPADotNames.ASSOCIATION_OVERRIDE ); + if ( overrideAnnotation != null ) { + processAssociationOverride( overrideAnnotation, path, container, context ); + } + } + + { + final AnnotationInstance overridesAnnotation = backingMember.getAnnotations().get( JPADotNames.ASSOCIATION_OVERRIDES ); + if ( overridesAnnotation != null ) { + final AnnotationInstance[] overrideAnnotations = JandexHelper.extractAnnotationsValue( + overridesAnnotation, + "value" + ); + for ( AnnotationInstance overrideAnnotation : overrideAnnotations ) { + processAssociationOverride( overrideAnnotation, path, container, context ); + } + } + } + } + + private void processAssociationOverride( + AnnotationInstance overrideAnnotation, + AttributePath path, + OverrideAndConverterCollector container, + EntityBindingContext context) { + // the name is required... + final String specifiedPath = overrideAnnotation.value( "name" ).asString(); + container.registerAssociationOverride( + buildAttributePath( path, specifiedPath ), + new AssociationOverride( path.getFullPath(), overrideAnnotation, context ) + ); + } + + /** + * Process AttributeConverter (plus plural) annotations found on the class. + * + * @param attributePath The path to the attribute + * @param typeMetadata The descriptor for the Java member backing the attribute + * @param container The attribute container (where overrides are collected) + * @param context The binding context + */ + public void processAttributeOverrides( + AttributePath attributePath, + ManagedTypeMetadata typeMetadata, + OverrideAndConverterCollector container, + EntityBindingContext context) { + processAttributeOverrides( + attributePath, + typeMetadata.getJavaTypeDescriptor().findLocalTypeAnnotation( JPADotNames.ATTRIBUTE_OVERRIDE ), + typeMetadata.getJavaTypeDescriptor().findLocalTypeAnnotation( JPADotNames.ATTRIBUTE_OVERRIDES ), + container, + context + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/EntityHierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/EntityHierarchyBuilder.java new file mode 100644 index 000000000000..54a93ed619ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/EntityHierarchyBuilder.java @@ -0,0 +1,338 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.AccessType; + +import org.hibernate.AnnotationException; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.reflite.spi.ClassDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.EntityHierarchySourceImpl; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.IdentifiableTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.ManagedTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.MappedSuperclassTypeMetadata; +import org.hibernate.metamodel.source.internal.annotations.entity.RootEntityTypeMetadata; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; +import org.jboss.logging.Logger; + +/** + * Given a Jandex annotation index, processes all classes with JPA relevant + * annotations and builds a more-easily consumed forms of them as a "hierarchy" + * representation. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + * @author Strong Liu + */ +public class EntityHierarchyBuilder { + private static final Logger LOG = Logger.getLogger( EntityHierarchyBuilder.class ); + + private final AnnotationBindingContext bindingContext; + + private final Set allKnownMappedSuperclassClassNames = new HashSet(); + + /** + * Pre-processes the annotated entities from the index and create a set of entity hierarchies which can be bound + * to the metamodel. + * + * @param bindingContext The binding context, giving access to needed services and information + * + * @return a set of {@code EntityHierarchySource} instances. + */ + public static Set createEntityHierarchies(AnnotationBindingContext bindingContext) { + return new EntityHierarchyBuilder( bindingContext ).process(); + } + + /** + * Constructs a EntityHierarchyBuilder. While all calls flow into this class statically via + * {@link #createEntityHierarchies}, internally each call to that method creates an instance + * used to hold instance state representing that parse. + * + * @param bindingContext Access to needed services and information + */ + private EntityHierarchyBuilder(AnnotationBindingContext bindingContext) { + this.bindingContext = bindingContext; + } + + + /** + * Pre-processes the annotated entities from the index and create a set of entity hierarchies which can be bound + * to the metamodel. + * + * @return a set of {@code EntityHierarchySource} instances. + */ + public Set process() { + final Set rootEntityDescriptors = findHierarchyRootDescriptors(); + final Set roots = new HashSet(); + final Set hierarchies = new HashSet(); + + for ( JavaTypeDescriptor rootDescriptor : rootEntityDescriptors ) { + final AccessType defaultAccessType = determineDefaultAccessTypeForHierarchy( rootDescriptor ); + final RootEntityTypeMetadata root = new RootEntityTypeMetadata( rootDescriptor, defaultAccessType, bindingContext ); + roots.add( root ); + final EntityHierarchySourceImpl hierarchy = new EntityHierarchySourceImpl( root, determineInheritanceType( root ) ); + hierarchies.add( hierarchy ); + } + + // At this point we have built all EntityClass and MappedSuperclass instances. + // All entities that are considered a root are grouped in the 'roots' collection + // Additionally we know of any unprocessed MappedSuperclass classes via + // 'allKnownMappedSuperclassClassNames' - 'processedMappedSuperclassClassNames' + + warnAboutUnusedMappedSuperclasses( roots ); + + return hierarchies; + } + + /** + * Collect ClassDescriptor for all "root entities" + *

      + * At the same time, populates allKnownMappedSuperclassClassNames based on all + * encountered MappedSuperclass descriptors. + *

      + * At the same time, makes sure that the JavaTypeDescriptorRepository is primed with all known classes + * according to Jandex + * + * @return JavaTypeDescriptor for all @Entity and @MappedSuperclass classes. + */ + private Set findHierarchyRootDescriptors() { + final Set collectedDescriptors = new HashSet(); + + final JavaTypeDescriptorRepository repo = bindingContext.getJavaTypeDescriptorRepository(); + for ( ClassInfo classInfo : bindingContext.getJandexAccess().getIndex().getKnownClasses() ) { + final JavaTypeDescriptor descriptor = repo.getType( repo.buildName( classInfo.name().toString() ) ); + if ( descriptor == null ) { + continue; + } + + if ( descriptor.findLocalTypeAnnotation( JPADotNames.MAPPED_SUPERCLASS ) != null ) { + allKnownMappedSuperclassClassNames.add( classInfo.name() ); + continue; + } + + if ( descriptor.findLocalTypeAnnotation( JPADotNames.ENTITY ) == null ) { + continue; + } + + if ( isRoot( descriptor ) ) { + collectedDescriptors.add( descriptor ); + } + } + + return collectedDescriptors; + } + + private boolean isRoot(JavaTypeDescriptor descriptor) { + // perform a series of opt-out checks against the super-type hierarchy + + // an entity is considered a root of the hierarchy if: + // 1) it has no super-types + // 2) its super types contain no entities (MappedSuperclasses are allowed) + + if ( !ClassDescriptor.class.isInstance( descriptor ) ) { + return true; + } + + ClassDescriptor current = ( (ClassDescriptor) descriptor ).getSuperType(); + while ( current != null ) { + if ( current.findLocalTypeAnnotation( JPADotNames.ENTITY ) != null ) { + return false; + } + current = current.getSuperType(); + } + + // if we hit no opt-outs we have a root + return true; + } + + private AccessType determineDefaultAccessTypeForHierarchy(JavaTypeDescriptor root) { + JavaTypeDescriptor current = root; + while ( current != null ) { + final AnnotationInstance access = current.findLocalTypeAnnotation( JPADotNames.ACCESS ); + if ( access != null ) { + return AccessType.valueOf( access.value().asEnum() ); + } + + final Collection embeddedIdAnnotations = current.findLocalAnnotations( + JPADotNames.EMBEDDED_ID + ); + if ( CollectionHelper.isNotEmpty( embeddedIdAnnotations ) ) { + return determineAccessTypeByIdPlacement( current, embeddedIdAnnotations ); + } + + final Collection idAnnotations = current.findLocalAnnotations( + JPADotNames.ID + ); + if ( CollectionHelper.isNotEmpty( idAnnotations ) ) { + return determineAccessTypeByIdPlacement( current, idAnnotations ); + } + + if ( ClassDescriptor.class.isInstance( current ) ) { + current = ( (ClassDescriptor) current ).getSuperType(); + } + else { + current = null; + } + } + + throw makeMappingException( + "Unable to locate identifier attribute for class hierarchy to determine default AccessType", + root + ); + } + + private static AnnotationException makeMappingException(String message, JavaTypeDescriptor typeDescriptor) { + return new AnnotationException( + message, + new Origin( SourceType.ANNOTATION, typeDescriptor.getName().toString() ) + ); + } + + private static AccessType determineAccessTypeByIdPlacement( + JavaTypeDescriptor descriptor, + Collection idAnnotations) { + AccessType accessType = null; + for ( AnnotationInstance annotation : idAnnotations ) { + AccessType tmpAccessType; + if ( annotation.target() instanceof FieldInfo ) { + tmpAccessType = AccessType.FIELD; + } + else if ( annotation.target() instanceof MethodInfo ) { + tmpAccessType = AccessType.PROPERTY; + } + else { + throw makeMappingException( + "Invalid placement of @" + annotation.name().toString() + " annotation. Target was " + + annotation.target() + "; expecting field or method", + descriptor + ); + } + + if ( accessType == null ) { + accessType = tmpAccessType; + } + else { + if ( !accessType.equals( tmpAccessType ) ) { + throw makeMappingException( + "Inconsistent placement of @" + annotation.name().toString() + " annotation on class", + descriptor + ); + } + } + } + return accessType; + } + + private InheritanceType determineInheritanceType(EntityTypeMetadata root) { + if ( root.getSubclasses().isEmpty() ) { + // I make an assumption here that *any* subclasses are a indicator of + // "persistent inheritance" but that is not strictly true. Really its any + // subclasses that are Entity (MappedSuperclass does not count). + return InheritanceType.NO_INHERITANCE; + } + + InheritanceType inheritanceType = root.getLocallyDefinedInheritanceType(); + if ( inheritanceType == null ) { + // if we have more than one entity class the default is SINGLE_TABLE + inheritanceType = InheritanceType.SINGLE_TABLE; + } + + // Validate that there is no @Inheritance annotation further down the hierarchy + ensureNoInheritanceAnnotationsOnSubclasses( root ); + + return inheritanceType; + } + + private void ensureNoInheritanceAnnotationsOnSubclasses(IdentifiableTypeMetadata clazz) { + for ( ManagedTypeMetadata subclass : clazz.getSubclasses() ) { + final AnnotationInstance inheritanceAnnotation = subclass.getJavaTypeDescriptor() + .findLocalTypeAnnotation( JPADotNames.INHERITANCE ); + if ( inheritanceAnnotation != null ) { + LOG.warnf( + "@javax.persistence.Inheritance was specified on non-root entity [%s]; ignoring...", + clazz.getName() + ); + } + ensureNoInheritanceAnnotationsOnSubclasses( (IdentifiableTypeMetadata) subclass ); + } + } + + private void warnAboutUnusedMappedSuperclasses(Set roots) { + for ( RootEntityTypeMetadata root : roots ) { + walkUp( root ); + walkDown( root ); + } + + // At this point, any left in the allKnownMappedSuperclassClassNames + // collection are unused... + for ( DotName mappedSuperclassName : allKnownMappedSuperclassClassNames ) { + // todo : i18n log message? + LOG.debugf( + "Encountered MappedSuperclass [%s] which was unused in any entity hierarchies", + mappedSuperclassName + ); + } + + allKnownMappedSuperclassClassNames.clear(); + } + + private void walkUp(IdentifiableTypeMetadata type) { + if ( type == null ) { + return; + } + + if ( MappedSuperclassTypeMetadata.class.isInstance( type ) ) { + allKnownMappedSuperclassClassNames.remove( type.getJavaTypeDescriptor().getName() ); + } + + walkUp( type.getSuperType() ); + } + + private void walkDown(ManagedTypeMetadata type) { + for ( ManagedTypeMetadata sub : type.getSubclasses() ) { + if ( MappedSuperclassTypeMetadata.class.isInstance( sub ) ) { + allKnownMappedSuperclassClassNames.remove( sub.getJavaTypeDescriptor().getName() ); + } + + walkDown( sub ); + } + } +} + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/EnumConversionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/EnumConversionHelper.java new file mode 100644 index 000000000000..325450f3f6e8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/EnumConversionHelper.java @@ -0,0 +1,196 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.util.HashSet; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.GenerationType; + +import org.hibernate.AssertionFailure; +import org.hibernate.FetchMode; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext; + +/** + * Helper class which converts between different enum types. + * + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class EnumConversionHelper { + private EnumConversionHelper() { + } + + public static String generationTypeToGeneratorStrategyName(GenerationType generatorEnum, boolean useNewGeneratorMappings) { + switch ( generatorEnum ) { + case IDENTITY: + return "identity"; + case AUTO: + return useNewGeneratorMappings + ? "enhanced-sequence" + : "native"; + case TABLE: + return useNewGeneratorMappings + ? "enhanced-table" + : MultipleHiLoPerTableGenerator.class.getName(); + case SEQUENCE: + return useNewGeneratorMappings + ? "enhanced-sequence" + : "seqhilo"; + } + throw new AssertionFailure( "Unknown GeneratorType: " + generatorEnum ); + } + + public static CascadeStyle cascadeTypeToCascadeStyle(CascadeType cascadeType) { + switch ( cascadeType ) { + case ALL: { + return CascadeStyles.ALL; + } + case PERSIST: { + return CascadeStyles.PERSIST; + } + case MERGE: { + return CascadeStyles.MERGE; + } + case REMOVE: { + return CascadeStyles.DELETE; + } + case REFRESH: { + return CascadeStyles.REFRESH; + } + case DETACH: { + return CascadeStyles.EVICT; + } + default: { + throw new AssertionFailure( "Unknown cascade type" ); + } + } + } + + public static CascadeStyle cascadeTypeToCascadeStyle( + org.hibernate.annotations.CascadeType cascadeType) { + switch ( cascadeType ) { + case ALL: { + return CascadeStyles.ALL; + } + case PERSIST: { + return CascadeStyles.PERSIST; + } + case MERGE: { + return CascadeStyles.MERGE; + } + case REMOVE: { + return CascadeStyles.DELETE; + } + case REFRESH: { + return CascadeStyles.REFRESH; + } + case DETACH: { + return CascadeStyles.EVICT; + } + case DELETE: { + return CascadeStyles.DELETE; + } + case SAVE_UPDATE: { + return CascadeStyles.UPDATE; + } + case REPLICATE: { + return CascadeStyles.REPLICATE; + } + case LOCK: { + return CascadeStyles.LOCK; + } + default: { + throw new AssertionFailure( "Unknown cascade type: " + cascadeType ); + } + } + } + + public static FetchMode annotationFetchModeToHibernateFetchMode(org.hibernate.annotations.FetchMode annotationFetchMode) { + switch ( annotationFetchMode ) { + case JOIN: { + return FetchMode.JOIN; + } + case SELECT: { + return FetchMode.SELECT; + } + case SUBSELECT: { + // todo - is this correct? can the conversion be made w/o any additional information, eg + // todo - association nature + return FetchMode.SELECT; + } + default: { + throw new AssertionFailure( "Unknown fetch mode" ); + } + } + } + + public static FetchStyle annotationFetchModeToFetchStyle(org.hibernate.annotations.FetchMode annotationFetchMode) { + switch ( annotationFetchMode ) { + case JOIN: { + return FetchStyle.JOIN; + } + case SELECT: { + return FetchStyle.SELECT; + } + case SUBSELECT: { + return FetchStyle.SUBSELECT; + } + default: { + throw new AssertionFailure( "Unknown fetch mode" ); + } + } + } + + public static Set cascadeTypeToCascadeStyleSet( + Set cascadeTypes, + Set hibernateCascadeTypes, + EntityBindingContext context) { + Set cascadeStyleSet = new HashSet(); + if ( CollectionHelper.isEmpty( cascadeTypes ) + && CollectionHelper.isEmpty( hibernateCascadeTypes ) ) { + String cascades = context.getMappingDefaults().getCascadeStyle(); + for ( String cascade : StringHelper.split( ",", cascades ) ) { + cascadeStyleSet.add( CascadeStyles.getCascadeStyle( cascade ) ); + } + } + else { + for ( CascadeType cascadeType : cascadeTypes ) { + cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); + } + for ( org.hibernate.annotations.CascadeType cascadeType : hibernateCascadeTypes ) { + cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); + } + } + return cascadeStyleSet; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/HibernateDotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/HibernateDotNames.java similarity index 81% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/HibernateDotNames.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/HibernateDotNames.java index 932b672d00f9..c3cb7e81cce3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/HibernateDotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/HibernateDotNames.java @@ -21,23 +21,25 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.source.internal.annotations.util; -import org.hibernate.annotations.AccessType; import org.hibernate.annotations.Any; import org.hibernate.annotations.AnyMetaDef; import org.hibernate.annotations.AnyMetaDefs; +import org.hibernate.annotations.AttributeAccessor; import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.Cache; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.Check; import org.hibernate.annotations.CollectionId; +import org.hibernate.annotations.CollectionType; import org.hibernate.annotations.ColumnTransformer; import org.hibernate.annotations.ColumnTransformers; import org.hibernate.annotations.Columns; import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.DiscriminatorOptions; -import org.hibernate.annotations.Entity; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchProfile; import org.hibernate.annotations.FetchProfiles; @@ -47,49 +49,56 @@ import org.hibernate.annotations.FilterJoinTable; import org.hibernate.annotations.FilterJoinTables; import org.hibernate.annotations.Filters; -import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Formula; import org.hibernate.annotations.Generated; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerators; import org.hibernate.annotations.Immutable; -import org.hibernate.annotations.Index; -import org.hibernate.annotations.IndexColumn; import org.hibernate.annotations.JoinColumnOrFormula; import org.hibernate.annotations.JoinColumnsOrFormulas; import org.hibernate.annotations.JoinFormula; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyToOne; +import org.hibernate.annotations.ListIndexBase; import org.hibernate.annotations.Loader; import org.hibernate.annotations.ManyToAny; import org.hibernate.annotations.MapKeyType; import org.hibernate.annotations.MetaValue; +import org.hibernate.annotations.MultiTenancy; import org.hibernate.annotations.NamedNativeQueries; import org.hibernate.annotations.NamedNativeQuery; import org.hibernate.annotations.NamedQueries; import org.hibernate.annotations.NamedQuery; import org.hibernate.annotations.NaturalId; +import org.hibernate.annotations.NaturalIdCache; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OptimisticLock; +import org.hibernate.annotations.OptimisticLockType; +import org.hibernate.annotations.OptimisticLocking; import org.hibernate.annotations.OrderBy; import org.hibernate.annotations.ParamDef; import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Parent; import org.hibernate.annotations.Persister; +import org.hibernate.annotations.Polymorphism; import org.hibernate.annotations.Proxy; import org.hibernate.annotations.RowId; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLDeleteAll; import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; -import org.hibernate.annotations.Sort; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.SortComparator; +import org.hibernate.annotations.SortNatural; import org.hibernate.annotations.Source; import org.hibernate.annotations.Subselect; import org.hibernate.annotations.Synchronize; import org.hibernate.annotations.Table; import org.hibernate.annotations.Tables; import org.hibernate.annotations.Target; +import org.hibernate.annotations.TenantColumn; +import org.hibernate.annotations.TenantFormula; import org.hibernate.annotations.Tuplizer; import org.hibernate.annotations.Tuplizers; import org.hibernate.annotations.Type; @@ -106,63 +115,71 @@ * @author Hardy Ferentschik */ public interface HibernateDotNames { - DotName ACCESS_TYPE = DotName.createSimple( AccessType.class.getName() ); DotName ANY = DotName.createSimple( Any.class.getName() ); DotName ANY_META_DEF = DotName.createSimple( AnyMetaDef.class.getName() ); DotName ANY_META_DEFS = DotName.createSimple( AnyMetaDefs.class.getName() ); + DotName ATTRIBUTE_ACCESSOR = DotName.createSimple( AttributeAccessor.class.getName() ); DotName BATCH_SIZE = DotName.createSimple( BatchSize.class.getName() ); DotName CACHE = DotName.createSimple( Cache.class.getName() ); DotName CASCADE = DotName.createSimple( Cascade.class.getName() ); DotName CHECK = DotName.createSimple( Check.class.getName() ); DotName COLLECTION_ID = DotName.createSimple( CollectionId.class.getName() ); + DotName COLLECTION_TYPE = DotName.createSimple( CollectionType.class.getName() ); DotName COLUMNS = DotName.createSimple( Columns.class.getName() ); DotName COLUMN_TRANSFORMER = DotName.createSimple( ColumnTransformer.class.getName() ); DotName COLUMN_TRANSFORMERS = DotName.createSimple( ColumnTransformers.class.getName() ); DotName DISCRIMINATOR_FORMULA = DotName.createSimple( DiscriminatorFormula.class.getName() ); DotName DISCRIMINATOR_OPTIONS = DotName.createSimple( DiscriminatorOptions.class.getName() ); - DotName ENTITY = DotName.createSimple( Entity.class.getName() ); + DotName DYNAMIC_INSERT = DotName.createSimple( DynamicInsert.class.getName() ); + DotName DYNAMIC_UPDATE = DotName.createSimple( DynamicUpdate.class.getName() ); DotName FETCH = DotName.createSimple( Fetch.class.getName() ); DotName FETCH_PROFILE = DotName.createSimple( FetchProfile.class.getName() ); DotName FETCH_PROFILES = DotName.createSimple( FetchProfiles.class.getName() ); + DotName FETCH_OVERRIDE = DotName.createSimple( FetchProfile.FetchOverride.class.getName() ); DotName FILTER = DotName.createSimple( Filter.class.getName() ); + DotName FILTERS = DotName.createSimple( Filters.class.getName() ); DotName FILTER_DEF = DotName.createSimple( FilterDef.class.getName() ); DotName FILTER_DEFS = DotName.createSimple( FilterDefs.class.getName() ); DotName FILTER_JOIN_TABLE = DotName.createSimple( FilterJoinTable.class.getName() ); DotName FILTER_JOIN_TABLES = DotName.createSimple( FilterJoinTables.class.getName() ); - DotName FILTERS = DotName.createSimple( Filters.class.getName() ); - DotName FOREIGN_KEY = DotName.createSimple( ForeignKey.class.getName() ); DotName FORMULA = DotName.createSimple( Formula.class.getName() ); DotName GENERATED = DotName.createSimple( Generated.class.getName() ); DotName GENERIC_GENERATOR = DotName.createSimple( GenericGenerator.class.getName() ); DotName GENERIC_GENERATORS = DotName.createSimple( GenericGenerators.class.getName() ); DotName IMMUTABLE = DotName.createSimple( Immutable.class.getName() ); - DotName INDEX = DotName.createSimple( Index.class.getName() ); - DotName INDEX_COLUMN = DotName.createSimple( IndexColumn.class.getName() ); DotName JOIN_COLUMN_OR_FORMULA = DotName.createSimple( JoinColumnOrFormula.class.getName() ); DotName JOIN_COLUMNS_OR_FORMULAS = DotName.createSimple( JoinColumnsOrFormulas.class.getName() ); DotName JOIN_FORMULA = DotName.createSimple( JoinFormula.class.getName() ); DotName LAZY_COLLECTION = DotName.createSimple( LazyCollection.class.getName() ); DotName LAZY_TO_ONE = DotName.createSimple( LazyToOne.class.getName() ); + DotName LIST_INDEX_BASE = DotName.createSimple( ListIndexBase.class.getName() ); DotName LOADER = DotName.createSimple( Loader.class.getName() ); DotName MANY_TO_ANY = DotName.createSimple( ManyToAny.class.getName() ); DotName MAP_KEY_TYPE = DotName.createSimple( MapKeyType.class.getName() ); DotName META_VALUE = DotName.createSimple( MetaValue.class.getName() ); + DotName MULTI_TENANT = DotName.createSimple( MultiTenancy.class.getName() ); DotName NAMED_NATIVE_QUERIES = DotName.createSimple( NamedNativeQueries.class.getName() ); DotName NAMED_NATIVE_QUERY = DotName.createSimple( NamedNativeQuery.class.getName() ); DotName NAMED_QUERIES = DotName.createSimple( NamedQueries.class.getName() ); DotName NAMED_QUERY = DotName.createSimple( NamedQuery.class.getName() ); DotName NATURAL_ID = DotName.createSimple( NaturalId.class.getName() ); + DotName NATURAL_ID_CACHE = DotName.createSimple( NaturalIdCache.class.getName() ); DotName NOT_FOUND = DotName.createSimple( NotFound.class.getName() ); DotName ON_DELETE = DotName.createSimple( OnDelete.class.getName() ); DotName OPTIMISTIC_LOCK = DotName.createSimple( OptimisticLock.class.getName() ); + DotName OPTIMISTIC_LOCKING = DotName.createSimple( OptimisticLocking.class.getName() ); + DotName OPTIMISTIC_LOCK_TYPE = DotName.createSimple( OptimisticLockType.class.getName() ); DotName ORDER_BY = DotName.createSimple( OrderBy.class.getName() ); DotName PARAM_DEF = DotName.createSimple( ParamDef.class.getName() ); DotName PARAMETER = DotName.createSimple( Parameter.class.getName() ); DotName PARENT = DotName.createSimple( Parent.class.getName() ); DotName PERSISTER = DotName.createSimple( Persister.class.getName() ); + DotName POLYMORPHISM = DotName.createSimple( Polymorphism.class.getName() ); DotName PROXY = DotName.createSimple( Proxy.class.getName() ); DotName ROW_ID = DotName.createSimple( RowId.class.getName() ); - DotName SORT = DotName.createSimple( Sort.class.getName() ); + DotName SELECT_BEFORE_UPDATE = DotName.createSimple( SelectBeforeUpdate.class.getName() ); + DotName SORT_COMPARATOR = DotName.createSimple( SortComparator.class.getName()); + DotName SORT_NATURAL = DotName.createSimple( SortNatural.class.getName() ); DotName SOURCE = DotName.createSimple( Source.class.getName() ); DotName SQL_DELETE = DotName.createSimple( SQLDelete.class.getName() ); DotName SQL_DELETE_ALL = DotName.createSimple( SQLDeleteAll.class.getName() ); @@ -173,6 +190,8 @@ public interface HibernateDotNames { DotName TABLE = DotName.createSimple( Table.class.getName() ); DotName TABLES = DotName.createSimple( Tables.class.getName() ); DotName TARGET = DotName.createSimple( Target.class.getName() ); + DotName TENANT_COLUMN = DotName.createSimple( TenantColumn.class.getName() ); + DotName TENANT_FORMULA = DotName.createSimple( TenantFormula.class.getName() ); DotName TUPLIZER = DotName.createSimple( Tuplizer.class.getName() ); DotName TUPLIZERS = DotName.createSimple( Tuplizers.class.getName() ); DotName TYPE = DotName.createSimple( Type.class.getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JPADotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JPADotNames.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JPADotNames.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JPADotNames.java index 20aa8a30e110..13eb511a8946 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JPADotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JPADotNames.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations; +package org.hibernate.metamodel.source.internal.annotations.util; import javax.persistence.Access; import javax.persistence.AccessType; @@ -37,6 +37,7 @@ import javax.persistence.ColumnResult; import javax.persistence.Convert; import javax.persistence.Converter; +import javax.persistence.Converts; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; @@ -53,10 +54,12 @@ import javax.persistence.ExcludeSuperclassListeners; import javax.persistence.FetchType; import javax.persistence.FieldResult; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.IdClass; +import javax.persistence.Index; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; @@ -75,10 +78,16 @@ import javax.persistence.MapKeyTemporal; import javax.persistence.MappedSuperclass; import javax.persistence.MapsId; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.NamedEntityGraphs; import javax.persistence.NamedNativeQueries; import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; +import javax.persistence.NamedStoredProcedureQueries; +import javax.persistence.NamedStoredProcedureQuery; +import javax.persistence.NamedSubgraph; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.OrderBy; @@ -103,6 +112,7 @@ import javax.persistence.SequenceGenerator; import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMappings; +import javax.persistence.StoredProcedureParameter; import javax.persistence.Table; import javax.persistence.TableGenerator; import javax.persistence.Temporal; @@ -133,6 +143,7 @@ public interface JPADotNames { DotName COLUMN_RESULT = DotName.createSimple( ColumnResult.class.getName() ); DotName CONVERT = DotName.createSimple( Convert.class.getName() ); DotName CONVERTER = DotName.createSimple( Converter.class.getName() ); + DotName CONVERTS = DotName.createSimple( Converts.class.getName() ); DotName DISCRIMINATOR_COLUMN = DotName.createSimple( DiscriminatorColumn.class.getName() ); DotName DISCRIMINATOR_TYPE = DotName.createSimple( DiscriminatorType.class.getName() ); DotName DISCRIMINATOR_VALUE = DotName.createSimple( DiscriminatorValue.class.getName() ); @@ -149,13 +160,15 @@ public interface JPADotNames { DotName EXCLUDE_SUPERCLASS_LISTENERS = DotName.createSimple( ExcludeSuperclassListeners.class.getName() ); DotName FETCH_TYPE = DotName.createSimple( FetchType.class.getName() ); DotName FIELD_RESULT = DotName.createSimple( FieldResult.class.getName() ); + DotName FOREIGNKEY = DotName.createSimple( ForeignKey.class.getName() ); DotName GENERATION_TYPE = DotName.createSimple( GenerationType.class.getName() ); DotName GENERATED_VALUE = DotName.createSimple( GeneratedValue.class.getName() ); DotName ID = DotName.createSimple( Id.class.getName() ); DotName ID_CLASS = DotName.createSimple( IdClass.class.getName() ); + DotName INDEX = DotName.createSimple( Index.class.getName() ); + DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() ); DotName INHERITANCE_TYPE = DotName.createSimple( InheritanceType.class.getName() ); DotName JOIN_COLUMN = DotName.createSimple( JoinColumn.class.getName() ); - DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() ); DotName JOIN_COLUMNS = DotName.createSimple( JoinColumns.class.getName() ); DotName JOIN_TABLE = DotName.createSimple( JoinTable.class.getName() ); DotName LOB = DotName.createSimple( Lob.class.getName() ); @@ -171,10 +184,16 @@ public interface JPADotNames { DotName MAP_KEY_TEMPORAL = DotName.createSimple( MapKeyTemporal.class.getName() ); DotName MAPPED_SUPERCLASS = DotName.createSimple( MappedSuperclass.class.getName() ); DotName MAPS_ID = DotName.createSimple( MapsId.class.getName() ); + DotName NAMED_ATTRIBUTE_NODE = DotName.createSimple( NamedAttributeNode.class.getName() ); + DotName NAMED_ENTITY_GRAPH = DotName.createSimple( NamedEntityGraph.class.getName() ); + DotName NAMED_ENTITY_GRAPHS = DotName.createSimple( NamedEntityGraphs.class.getName() ); DotName NAMED_NATIVE_QUERIES = DotName.createSimple( NamedNativeQueries.class.getName() ); DotName NAMED_NATIVE_QUERY = DotName.createSimple( NamedNativeQuery.class.getName() ); DotName NAMED_QUERIES = DotName.createSimple( NamedQueries.class.getName() ); DotName NAMED_QUERY = DotName.createSimple( NamedQuery.class.getName() ); + DotName NAMED_STORED_PROCEDURE_QUERIES = DotName.createSimple( NamedStoredProcedureQueries.class.getName() ); + DotName NAMED_STORED_PROCEDURE_QUERY = DotName.createSimple( NamedStoredProcedureQuery.class.getName() ); + DotName NAMED_SUB_GRAPH = DotName.createSimple( NamedSubgraph.class.getName() ); DotName ONE_TO_MANY = DotName.createSimple( OneToMany.class.getName() ); DotName ONE_TO_ONE = DotName.createSimple( OneToOne.class.getName() ); DotName ORDER_BY = DotName.createSimple( OrderBy.class.getName() ); @@ -199,6 +218,7 @@ public interface JPADotNames { DotName SEQUENCE_GENERATOR = DotName.createSimple( SequenceGenerator.class.getName() ); DotName SQL_RESULT_SET_MAPPING = DotName.createSimple( SqlResultSetMapping.class.getName() ); DotName SQL_RESULT_SET_MAPPINGS = DotName.createSimple( SqlResultSetMappings.class.getName() ); + DotName STORED_PROCEDURE_PARAMETER = DotName.createSimple( StoredProcedureParameter.class.getName() ); DotName TABLE = DotName.createSimple( Table.class.getName() ); DotName TABLE_GENERATOR = DotName.createSimple( TableGenerator.class.getName() ); DotName TEMPORAL = DotName.createSimple( Temporal.class.getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JPAListenerHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JPAListenerHelper.java new file mode 100644 index 000000000000..036d5dbe00ec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JPAListenerHelper.java @@ -0,0 +1,442 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import javax.persistence.PostLoad; +import javax.persistence.PostPersist; +import javax.persistence.PostRemove; +import javax.persistence.PostUpdate; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; +import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.Type; +import org.jboss.logging.Logger; + +/** + * Helper for working with JPA callbacks/listeners + * + * @author Steve Ebersole + * @author Strong Liu + */ +public class JPAListenerHelper { + private static final Logger log = Logger.getLogger( JPAListenerHelper.class ); + + /** + * Find the name of the method in the class (described by the descriptor) that + * is annotated with the given lifecycle callback annotation. + * + * @param javaTypeDescriptor The descriptor for the class in which to find + * the lifecycle callback method + * @param eventType The type of lifecycle callback to look for + * @param listener Is the {@code javaTypeDescriptor} a listener, as opposed to + * an Entity/MappedSuperclass? Used here to validate method signatures. + * + * @return The name of the callback method, or {@code null} indicating none was found + */ + public static String findCallback(JavaTypeDescriptor javaTypeDescriptor, DotName eventType, boolean listener) { + final Collection listenerAnnotations = javaTypeDescriptor.getJandexClassInfo() + .annotations() + .get( eventType ); + if ( listenerAnnotations == null || listenerAnnotations.isEmpty() ) { + return null; + } + + // todo : these log messages on skip really should be warn, which means i18n message logging + + for ( AnnotationInstance listenerAnnotation : listenerAnnotations ) { + if ( !MethodInfo.class.isInstance( listenerAnnotation.target() ) ) { + log.debugf( + "Skipping callback annotation [%s] for class [%s] as it was " + + "applied to target other than a method : %s", + eventType, + javaTypeDescriptor.getName().toString(), + listenerAnnotation.target() + ); + continue; + } + + final MethodInfo methodInfo = (MethodInfo) listenerAnnotation.target(); + + // validate return is `void` + // NOTE : we do NOT skip here, just a warning + if ( methodInfo.returnType().kind() != Type.Kind.VOID ) { + log.debugf( + "Callback annotation [%s] on class [%s] was applied to method [%s] with a non-void return type", + eventType, + javaTypeDescriptor.getName().toString(), + methodInfo.name() + ); + } + + // validate arguments + if ( listener ) { + // should have a single argument + if ( methodInfo.args().length != 1 ) { + log.debugf( + "Callback annotation [%s] on listener class [%s] was applied to method [%s] " + + "which does not define a single-arg signature [%s]", + eventType, + javaTypeDescriptor.getName().toString(), + methodInfo.name(), + methodInfo.args().length + ); + continue; + } + } + else { + // should have no arguments + if ( methodInfo.args().length != 0 ) { + log.debugf( + "Callback annotation [%s] on entity class [%s] was applied to method [%s] " + + "which does not define a no-arg signature [%s]", + eventType, + javaTypeDescriptor.getName().toString(), + methodInfo.name(), + methodInfo.args().length + ); + continue; + } + } + + // if we did not opt-out above (with a continue statement) then we found it... + return ( (MethodInfo) listenerAnnotation.target() ).name(); + } + + return null; + } + + private static final Map, DotName> EVENT_TYPE; + + static { + EVENT_TYPE = new HashMap, DotName>( 7 ); + EVENT_TYPE.put( PrePersist.class, JPADotNames.PRE_PERSIST ); + EVENT_TYPE.put( PreRemove.class, JPADotNames.PRE_REMOVE ); + EVENT_TYPE.put( PreUpdate.class, JPADotNames.PRE_UPDATE ); + EVENT_TYPE.put( PostLoad.class, JPADotNames.POST_LOAD ); + EVENT_TYPE.put( PostPersist.class, JPADotNames.POST_PERSIST ); + EVENT_TYPE.put( PostRemove.class, JPADotNames.POST_REMOVE ); + EVENT_TYPE.put( PostUpdate.class, JPADotNames.POST_UPDATE ); + + } + +// private final EntityTypeMetadata entityTypeMetadata; +// private final EntityBindingContext context; +// private final List mappingClassHierarchy; +// +// public JPAListenerHelper(EntityTypeMetadata entityTypeMetadata) { +// this.entityTypeMetadata = entityTypeMetadata; +// this.context = entityTypeMetadata.getLocalBindingContext(); +// this.mappingClassHierarchy = buildHierarchy(); +// } +// +// private List buildHierarchy() { +// List list = new ArrayList(); +// list.add( entityTypeMetadata ); +// if ( !excludeSuperClassListeners( entityTypeMetadata.getClassInfo() ) ) { +// for ( MappedSuperclassTypeMetadata mappedSuperclassTypeMetadata : entityTypeMetadata.getMappedSuperclassTypeMetadatas() ) { +// list.add( mappedSuperclassTypeMetadata ); +// if ( excludeSuperClassListeners( mappedSuperclassTypeMetadata.getClassInfo() ) ) { +// break; +// } +// +// } +// } +// return list; +// } +// +// private List findAllEntityListeners() { +// List result = new ArrayList(); +// for ( final ManagedTypeMetadata managedTypeMetadata : mappingClassHierarchy ) { +// List list = managedTypeMetadata.getClassInfo() +// .annotations() +// .get( JPADotNames.ENTITY_LISTENERS ); +// if ( CollectionHelper.isNotEmpty( list ) ) { +// result.addAll( list ); +// } +// } +// return result; +// } +// +// +// public List bindJPAListeners() { +// final List callbackClassList = new ArrayList(); +// bindEntityCallbackEvents( callbackClassList ); +// bindEntityListeners( callbackClassList ); +// bindDefaultListeners( callbackClassList ); +// return callbackClassList; +// } +// +// private void bindEntityCallbackEvents(List callbackClassList) { +// Map overrideMethodCheck = new HashMap(); +// for ( final ManagedTypeMetadata managedTypeMetadata : mappingClassHierarchy ) { +// try { +// internalProcessCallbacks( +// managedTypeMetadata.getClassInfo(), +// callbackClassList, +// false, +// false, +// overrideMethodCheck +// ); +// } +// catch ( PersistenceException error ) { +// throw new PersistenceException( error.getMessage() + "entity listener " + managedTypeMetadata.getName() ); +// } +// } +// } +// +// private void bindEntityListeners(List callbackClassList) { +// List entityListenerAnnotations = findAllEntityListeners(); +// for ( AnnotationInstance annotation : entityListenerAnnotations ) { +// Type[] types = annotation.value().asClassArray(); +// for ( int i = types.length - 1; i >= 0; i-- ) { +// String callbackClassName = types[i].name().toString(); +// try { +// processJpaCallbacks( callbackClassName, true, callbackClassList, null ); +// } +// catch ( PersistenceException error ) { +// throw new PersistenceException( error.getMessage() + "entity listener " + callbackClassName ); +// } +// } +// } +// } +// +// private void processJpaCallbacks( +// final String instanceCallbackClassName, +// final boolean isListener, +// final List callbackClassList, +// final Map overrideMethodCheck) { +// final ClassInfo callbackClassInfo = findClassInfoByName( instanceCallbackClassName ); +// internalProcessCallbacks( callbackClassInfo, callbackClassList, isListener, false, overrideMethodCheck ); +// } +// +// +// private void bindDefaultListeners(final List callbackClassList) { +// // Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded) +// +// Collection defaultEntityListenerAnnotations = context +// .getIndex() +// .getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); +// for ( AnnotationInstance annotation : defaultEntityListenerAnnotations ) { +// for ( Type callbackClass : annotation.value().asClassArray() ) { +// String callbackClassName = callbackClass.name().toString(); +// ClassInfo callbackClassInfo = findClassInfoByName( callbackClassName ); +// try { +// processDefaultJpaCallbacks( callbackClassInfo, callbackClassList ); +// } +// catch ( PersistenceException error ) { +// throw new PersistenceException( error.getMessage() + "default entity listener " + callbackClassName ); +// } +// } +// } +// } +// +// private static boolean excludeDefaultListeners(ClassInfo classInfo) { +// return classInfo.annotations().containsKey( JPADotNames.EXCLUDE_DEFAULT_LISTENERS ); +// } +// +// private static boolean excludeSuperClassListeners(ClassInfo classInfo) { +// return classInfo.annotations().containsKey( JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ); +// } +// +// private static boolean isNotRootObject(DotName name) { +// return name != null && !JandexHelper.OBJECT.equals( name ); +// } +// +// private void processDefaultJpaCallbacks( +// final ClassInfo callbackClassInfo, +// final List jpaCallbackClassList) { +// if ( excludeDefaultListeners( callbackClassInfo ) ) { +// return; +// } +// // Process superclass first if available and not excluded +// if ( !excludeSuperClassListeners( callbackClassInfo ) ) { +// DotName superName = callbackClassInfo.superName(); +// if ( isNotRootObject( superName ) ) { +// processDefaultJpaCallbacks( findClassInfoByName( superName.toString() ), jpaCallbackClassList ); +// } +// } +// internalProcessCallbacks( callbackClassInfo, jpaCallbackClassList, true, true, null ); +// } +// +// private ClassInfo findClassInfoByName(String name) { +// ClassInfo classInfo = context.getClassInfo( name ); +// if ( classInfo == null ) { +// JandexHelper.throwNotIndexException( name ); +// } +// return classInfo; +// } +// +// private void internalProcessCallbacks( +// final ClassInfo callbackClassInfo, +// final List callbackClassList, +// final boolean isListener, +// final boolean isDefault, +// final Map overrideMethodCheck) { +// final Map, String> callbacksByType = new HashMap, String>( 7 ); +// createCallback( +// PrePersist.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// createCallback( +// PreRemove.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// createCallback( +// PreUpdate.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// createCallback( +// PostLoad.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// createCallback( +// PostPersist.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// createCallback( +// PostRemove.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// createCallback( +// PostUpdate.class, callbacksByType, callbackClassInfo, isListener, isDefault, overrideMethodCheck +// ); +// if ( !callbacksByType.isEmpty() ) { +// final String name = callbackClassInfo.name().toString(); +// final JpaCallbackSource callbackSource = new JpaCallbackSourceImpl( name, callbacksByType, isListener ); +// callbackClassList.add( 0, callbackSource ); +// } +// } +// +// +// /** +// * @param callbackTypeClass Lifecycle event type class, like {@link javax.persistence.PrePersist}, +// * {@link javax.persistence.PreRemove}, {@link javax.persistence.PreUpdate}, {@link javax.persistence.PostLoad}, +// * {@link javax.persistence.PostPersist}, {@link javax.persistence.PostRemove}, {@link javax.persistence.PostUpdate}. +// * @param callbacksByClass A map that keyed by the {@param callbackTypeClass} and value is callback method name. +// * @param callbackClassInfo Jandex ClassInfo of callback method's container, should be either entity/mapped superclass or entity listener class. +// * @param isListener Is this callback method defined in an entity listener class or not. +// */ +// private void createCallback( +// final Class callbackTypeClass, +// final Map, String> callbacksByClass, +// final ClassInfo callbackClassInfo, +// final boolean isListener, +// final boolean isDefault, +// final Map overrideMethodCheck) { +// +// final Collection annotationInstances; +// if ( isDefault ) { +// annotationInstances = context.getIndex().getAnnotations( EVENT_TYPE.get( callbackTypeClass ) ); +// } +// else { +// List temp = callbackClassInfo.annotations().get( EVENT_TYPE.get( callbackTypeClass ) ); +// annotationInstances = temp != null ? temp : Collections.EMPTY_LIST; +// } +// +// //there should be only one callback method per callbackType, isn't it? +// //so only one callbackAnnotation? +// for ( AnnotationInstance callbackAnnotation : annotationInstances ) { +// MethodInfo methodInfo = (MethodInfo) callbackAnnotation.target(); +// validateMethod( methodInfo, callbackTypeClass, callbacksByClass, isListener ); +// final String name = methodInfo.name(); +// if ( overrideMethodCheck != null && overrideMethodCheck.containsKey( name ) ) { +// continue; +// } +// else if ( overrideMethodCheck != null ) { +// overrideMethodCheck.put( name, null ); +// } +// if ( !isDefault ) { +// callbacksByClass.put( callbackTypeClass, name ); +// } +// else if ( methodInfo.declaringClass().name().equals( callbackClassInfo.name() ) ) { +// if ( methodInfo.args().length != 1 ) { +// throw new PersistenceException( +// String.format( +// "Callback method %s must have exactly one argument defined as either Object or %s in ", +// name, +// entityTypeMetadata.getName() +// ) +// ); +// } +// callbacksByClass.put( callbackTypeClass, name ); +// } +// } +// } +// +// +// /** +// * Applying JPA Spec rules to validate listener callback method mapping. +// * +// * @param methodInfo The lifecycle callback method. +// * @param callbackTypeClass Lifecycle event type class, like {@link javax.persistence.PrePersist}, +// * {@link javax.persistence.PreRemove}, {@link javax.persistence.PreUpdate}, {@link javax.persistence.PostLoad}, +// * {@link javax.persistence.PostPersist}, {@link javax.persistence.PostRemove}, {@link javax.persistence.PostUpdate}. +// * @param callbacksByClass A map that keyed by the {@param callbackTypeClass} and value is callback method name. +// * @param isListener Is this callback method defined in an entity listener class or not. +// */ +// private void validateMethod( +// MethodInfo methodInfo, +// Class callbackTypeClass, +// Map, String> callbacksByClass, +// boolean isListener) { +// final String name = methodInfo.name(); +// +// if ( methodInfo.returnType().kind() != Type.Kind.VOID ) { +// throw new PersistenceException( "Callback method " + name + " must have a void return type in " ); +// } +// if ( Modifier.isStatic( methodInfo.flags() ) || Modifier.isFinal( methodInfo.flags() ) ) { +// throw new PersistenceException( "Callback method " + name + " must not be static or final in " ); +// } +// Type[] argTypes = methodInfo.args(); +// +// if ( isListener ) { +// if ( argTypes.length != 1 ) { +// throw new PersistenceException( "Callback method " + name + " must have exactly one argument in " ); +// } +// String argTypeName = argTypes[0].name().toString(); +// if ( !argTypeName.equals( Object.class.getName() ) && !argTypeName.equals( entityTypeMetadata.getName() ) ) { +// Class typeClass = entityTypeMetadata.getLocalBindingContext().locateClassByName( argTypeName ); +// if ( !typeClass.isAssignableFrom( entityTypeMetadata.getConfiguredClass() ) ) { +// throw new PersistenceException( +// "The argument for callback method " + name + +// " must be defined as either Object or " + entityTypeMetadata.getName() + " in " +// ); +// } +// } +// } +// else if ( argTypes.length != 0 ) { +// throw new PersistenceException( "Callback method " + name + " must have no arguments in " ); +// } +// if ( callbacksByClass.containsKey( callbackTypeClass ) ) { +// throw new PersistenceException( +// "Only one method may be annotated as a " + callbackTypeClass.getSimpleName() + +// " callback method in " +// ); +// } +// +// } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JandexHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JandexHelper.java new file mode 100644 index 000000000000..5d0a981ea15a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/JandexHelper.java @@ -0,0 +1,736 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.annotations.util; + +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.HibernateException; +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.type.PrimitiveWrapperHelper; +import org.hibernate.metamodel.source.internal.annotations.TypedValueExtractor; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.service.ServiceRegistry; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; +import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.Type; + +/** + * Utility methods for working with the jandex annotation index. + * + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public class JandexHelper { + private static final Map DEFAULT_VALUES_BY_ELEMENT = new HashMap(); + + public static final DotName OBJECT = DotName.createSimple( Object.class.getName() ); + +// todo : consider making JandexHelper non-static, resolved from the AnnotationBindingContext +// private final ClassLoaderService classLoaderService; +// +// private JandexHelper(BindingContext context) { +// this.classLoaderService = context.getServiceRegistry().getService( ClassLoaderService.class ); +// } + + + + + + + + + + + + + + + + + + + /** + * Retrieves a jandex annotation element value. If the value is {@code null}, the default value specified in the + * annotation class is retrieved instead. + *

      + * The following types are supported:

        + *
      • Byte
      • + *
      • Short
      • + *
      • Integer
      • + *
      • Character
      • + *
      • Float
      • + *
      • Double
      • + *
      • Long
      • + *
      • Boolean
      • + *
      • String
      • + *
      • AnnotationInstance
      • + *
      + * There are two special cases. {@code Class} parameters should be retrieved as strings (and then can later be + * loaded) and enumerated values should be retrieved via {@link #getEnumValue}. + *

      + * + * @param annotation The annotation containing the attribute whose value we are to extract + * @param attributeName The name of the attribute whose value we are to extract + * @param type The type we are to return the extracted value in; see the list of supported types above. + * @param classLoaderService The ClassLoaderService; used to resolve default + * values defined on the annotation class. + * + * @return the value if not {@code null}, else the default value if not + * {@code null}, else {@code null}. + * + * @throws AssertionFailure in case the specified {@code type} is a class instance or the specified type causes a {@code ClassCastException} + * when retrieving the value. + */ + @SuppressWarnings("unchecked") + public static T getValue( + AnnotationInstance annotation, + String attributeName, + Class type, + ClassLoaderService classLoaderService) throws AssertionFailure { + if ( Class.class.equals( type ) ) { + throw new AssertionFailure( + "Annotation parameters of type Class should be retrieved as strings (fully qualified class names)" + ); + } + + // todo : we should seriously consider mapping type to appropriate AnnotationValue.asXYZ calls + + if ( type.isPrimitive() ) { + type = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( type ).getWrapperClass(); + } + + AnnotationValue annotationValue = annotation.value( attributeName ); + + try { + // Jandex only reads stuff that is actually in the bytecode. If + // an annotation usage does not include a defaulted attribute, + // Jandex reports the missing attribute inclusion as the returned + // AnnotationValue being {@code null} (quite nice actually). + // + // todo : couldn't null here indicate that the attributeName does + // not name an existing attribute on the annotation? + if ( annotationValue != null ) { + // the attribute was included in the annotation usage, so extract + // its typed value and return it + return explicitAnnotationParameter( annotationValue, type ); + } + else { + // Here the attribute was left off. So we look at the + // annotation class to see what its default value is. + return defaultAnnotationParameter( + getDefaultValue( annotation, attributeName, classLoaderService ), + type + ); + } + } + catch ( ClassCastException e ) { + throw new AssertionFailure( + String.format( + "the annotation property [%s] of annotation [@%s] is not of type %s", + attributeName, + annotation.name(), + type.getName() + ) + ); + } + } + + public static Collection collectionAnnotations( + final IndexView indexView, + final DotName singularDotName, + final DotName pluralDotName) { + final List results = new ArrayList(); + + results.addAll( indexView.getAnnotations( singularDotName ) ); + + final Collection pluralAnnotations = indexView.getAnnotations( pluralDotName ); + for ( AnnotationInstance plural : pluralAnnotations ) { + final AnnotationInstance[] singulars = extractAnnotationsValue( plural, "value" ); + results.addAll( Arrays.asList( singulars ) ); + } + return results; + + } + + /** + * Simplified form of {@link #getValue} for dealing with extracting + * an annotation attribute value which is itself an annotation + */ + public static AnnotationInstance extractAnnotationValue(AnnotationInstance annotation, String name) { + final AnnotationValue annotationValue = annotation.value( name ); + return annotationValue == null + ? null + : explicitAnnotationParameter( annotationValue, AnnotationInstance.class ); + } + + /** + * Simplified form of {@link #getValue} for dealing with extracting + * an annotation attribute value which is itself an arrays of annotations + */ + public static AnnotationInstance[] extractAnnotationsValue(AnnotationInstance annotation, String name) { + final AnnotationValue annotationValue = annotation.value( name ); + return annotationValue == null + ? new AnnotationInstance[0] + : explicitAnnotationParameter( annotationValue, AnnotationInstance[].class ); + } + + /** + * Retrieves a jandex annotation element value, converting it to the supplied enumerated type. If the value is + * null, the default value specified in the annotation class is retrieved instead. + * + * @param an enumerated type + * @param annotation the annotation containing the enumerated element with the supplied name + * @param element the name of the enumerated element value to be retrieve + * @param type the type to which to convert the value before being returned + * @param classLoaderService ClassLoaderService + * + * @return the value converted to the supplied enumerated type if the value is not null, else the default value if + * not null, else null. + */ + @SuppressWarnings("unchecked") + public static > T getEnumValue(AnnotationInstance annotation, String element, Class type, + ClassLoaderService classLoaderService) { + AnnotationValue val = annotation.value( element ); + if ( val == null ) { + return (T) getDefaultValue( annotation, element, classLoaderService ); + } + return Enum.valueOf( type, val.asEnum() ); + } + + /** + * Expects a method or field annotation target and returns the property name for this target + * + * @param target the annotation target + * + * @return the property name of the target. For a field it is the field name and for a method name it is + * the method name stripped of 'is', 'has' or 'get' + */ + public static String getPropertyName(AnnotationTarget target) { + if ( !( target instanceof MethodInfo || target instanceof FieldInfo ) ) { + throw new AssertionFailure( "Unexpected annotation target " + target.toString() ); + } + + if ( target instanceof FieldInfo ) { + return ( (FieldInfo) target ).name(); + } + else { + final String methodName = ( (MethodInfo) target ).name(); + String propertyName; + if ( methodName.startsWith( "is" ) ) { + propertyName = Introspector.decapitalize( methodName.substring( 2 ) ); + } + else if ( methodName.startsWith( "has" ) ) { + propertyName = Introspector.decapitalize( methodName.substring( 3 ) ); + } + else if ( methodName.startsWith( "get" ) ) { + propertyName = Introspector.decapitalize( methodName.substring( 3 ) ); + } + else { + throw new AssertionFailure( "Expected a method following the Java Bean notation" ); + } + return propertyName; + } + } + + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to retrieve from the class info + * + * @return the list of annotations specified in the class + */ + public static List getAnnotations( + ClassInfo classInfo, DotName annotationName ) { + if ( classInfo.annotations().containsKey( annotationName ) ) { + return classInfo.annotations().get( annotationName ); + } else { + return Collections.emptyList(); + } + } + + + + public static Collection getAnnotations( + final IndexView indexView, + final DotName singularDotName, + final DotName pluralDotName, + final ClassLoaderService classLoaderService + ) { + List annotationInstances = new ArrayList(); + annotationInstances.addAll( indexView.getAnnotations( singularDotName ) ); + + Collection pluralAnnotations = indexView.getAnnotations( pluralDotName ); + for ( AnnotationInstance ann : pluralAnnotations ) { + AnnotationInstance[] typeDefAnnotations = getValue( + ann, + "value", + AnnotationInstance[].class, + classLoaderService + ); + annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) ); + } + return annotationInstances; + } + + public static Collection getAnnotations( + final Map> annotations, + final DotName singularDotName, + final DotName pluralDotName, + final ClassLoaderService classLoaderService) { + return getAnnotations( annotations, singularDotName, pluralDotName, false, classLoaderService ); + } + + public static Collection getAnnotations( + final Map> annotations, + final DotName singularDotName, + final DotName pluralDotName, + final boolean checkSingle, + final ClassLoaderService classLoaderService) { + List annotationInstances = new ArrayList(); + + List list = annotations.get( singularDotName ); + if ( list != null ) { + if ( checkSingle ) { + assertSingularAnnotationInstances( list ); + } + annotationInstances.addAll( list ); + } + Collection pluralAnnotations = annotations.get( pluralDotName ); + if ( pluralAnnotations != null ) { + if ( checkSingle ) { + assertSingularAnnotationInstances( pluralAnnotations ); + } + for ( AnnotationInstance ann : pluralAnnotations ) { + AnnotationInstance[] typeDefAnnotations = getValue( + ann, + "value", + AnnotationInstance[].class, + classLoaderService + ); + annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) ); + } + } + + + return annotationInstances; + } + + public static Collection getCombinedAnnotations( + final Map annotations, + final DotName singularDotName, + final DotName pluralDotName, + final ClassLoaderService classLoaderService) { + List annotationInstances = new ArrayList(); + + final AnnotationInstance singular = annotations.get( singularDotName ); + if ( singular != null ) { + annotationInstances.add( singular ); + } + + final AnnotationInstance plural = annotations.get( pluralDotName ); + if ( plural != null ) { + AnnotationInstance[] typeDefAnnotations = getValue( + plural, + "value", + AnnotationInstance[].class, + classLoaderService + ); + annotationInstances.addAll( Arrays.asList( typeDefAnnotations ) ); + } + + return annotationInstances; + } + + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to retrieve from the class info + * + * @return the single annotation defined on the class or {@code null} in case the annotation is not specified at all + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static AnnotationInstance getSingleAnnotation(ClassInfo classInfo, DotName annotationName) + throws AssertionFailure { + return getSingleAnnotation( classInfo.annotations(), annotationName ); + } + + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to retrieve from the class info + * @param target the annotation target + * + * @return the single annotation defined on the class with the supplied target or {@code null} in case the annotation is not specified at all + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static AnnotationInstance getSingleAnnotation( + ClassInfo classInfo, + DotName annotationName, + Class< ? extends AnnotationTarget > target ) { + List annotationList = classInfo.annotations().get( annotationName ); + if ( annotationList == null ) { + return null; + } + annotationList = new ArrayList< AnnotationInstance >( annotationList ); + for ( Iterator< AnnotationInstance > iter = annotationList.iterator(); iter.hasNext(); ) { + if ( !target.isInstance( iter.next().target() ) ) { + iter.remove(); + } + } + if ( annotationList.isEmpty() ) { + return null; + } + if ( annotationList.size() == 1 ) { + return annotationList.get( 0 ); + } + assertSingularAnnotationInstances( annotationList ); + return null;//only here to make compiler happy + } + + private static void assertSingularAnnotationInstances(Collection annotationInstances) { + if ( annotationInstances.size() > 1 ) { + throw new AssertionFailure( + "Found more than one instance of the annotation " + + annotationInstances.iterator().next().name().toString() + + ". Expected was one." + ); + } + } + + /** + * @param annotations List of annotation instances keyed against their dot name. + * @param annotationName the annotation to retrieve from map + * + * @return the single annotation of the specified dot name or {@code null} in case the annotation is not specified at all + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static AnnotationInstance getSingleAnnotation(Map> annotations, DotName annotationName) + throws AssertionFailure { + return getSingleAnnotation( annotations, annotationName, null ); + } + + /** + * Similar to {@link #getSingleAnnotation(Map, DotName)}, but searches for + * the single annotation on the given target. Useful for annotations that + * can appear both on a Class and Method/Field level. Ex: custom SQL annotations. + * + * @param annotations List of annotation instances keyed against their dot name. + * @param annotationName the annotation to retrieve from map + * @param target the annotation target + * + * @return the single annotation of the specified dot name or {@code null} in case the annotation is not specified at all + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static AnnotationInstance getSingleAnnotation(Map> annotations, + DotName annotationName, AnnotationTarget target) throws AssertionFailure { + List annotationList = annotations.get( annotationName ); + if ( annotationList == null ) { + return null; + } + final List targetedAnnotationList; + if ( target != null ) { + targetedAnnotationList = new ArrayList(); + for ( AnnotationInstance annotation : annotationList ) { + if ( getTargetName( annotation.target() ).equals( getTargetName( target ) ) ) { + targetedAnnotationList.add( annotation ); + } + } + } + else { + targetedAnnotationList = annotationList; + } + if ( targetedAnnotationList.size() == 0 ) { + return null; + } + else if ( targetedAnnotationList.size() == 1 ) { + return targetedAnnotationList.get( 0 ); + } + else { + throw new AssertionFailure( "Found more than one instance of the annotation " + + targetedAnnotationList.get( 0 ).name().toString() + ". Expected was one." ); + } + } + + public static void throwNotIndexException(String className){ + throw new MappingException( + "Class " + className +" is not indexed, probably means this class should be explicitly added " + + "into MatadataSources" + ); + + } + + /** + * @param classInfo the class info from which to retrieve the annotation instance + * @param annotationName the annotation to check + * + * @return returns {@code true} if the annotations contains only a single instance of specified annotation or {@code false} + * otherwise. + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static boolean containsSingleAnnotation( ClassInfo classInfo, DotName annotationName ) { + return containsSingleAnnotation( classInfo.annotations(), annotationName ); + } + + /** + * @param annotations List of annotation instances keyed against their dot name. + * @param annotationName the annotation to check + * + * @return returns {@code true} if the map contains only a single instance of specified annotation or {@code false} otherwise. + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static boolean containsSingleAnnotation( Map> annotations, DotName annotationName ) { + return getSingleAnnotation( annotations, annotationName ) != null; + } + + /** + * Creates a jandex index for the specified classes + * + * @param classLoaderService class loader service + * @param classes the classes to index + * + * @return an annotation repository w/ all the annotation discovered in the specified classes + */ + public static IndexView indexForClass(ClassLoaderService classLoaderService, Class... classes) { + Indexer indexer = new Indexer(); + for ( Class clazz : classes ) { + InputStream stream = classLoaderService.locateResourceStream( + clazz.getName().replace( '.', '/' ) + ".class" + ); + try { + indexer.index( stream ); + } + catch ( IOException e ) { + StringBuilder builder = new StringBuilder(); + builder.append( "[" ); + int count = 0; + for ( Class c : classes ) { + builder.append( c.getName() ); + if ( count < classes.length - 1 ) { + builder.append( "," ); + } + count++; + } + builder.append( "]" ); + throw new HibernateException( "Unable to create annotation index for " + builder.toString() ); + } + } + return indexer.complete(); + } + + public static Map> getMemberAnnotations( + ClassInfo classInfo, String name, ServiceRegistry serviceRegistry ) { + if ( classInfo == null ) { + throw new IllegalArgumentException( "classInfo cannot be null" ); + } + + if ( name == null ) { + throw new IllegalArgumentException( "name cannot be null" ); + } + + // Allow a property name to be used even if the entity uses method access. + // TODO: Is this reliable? Is there a better way to do it? + String getterName = ""; + try { + Class beanClass = serviceRegistry.getService( + ClassLoaderService.class ).classForName( + classInfo.name().toString() ); + Method getter = new PropertyDescriptor(name, beanClass) + .getReadMethod(); + if ( getter != null ) { + getterName = getter.getName(); + } + } catch ( Exception e ) { + // do nothing + } + + Map> annotations = new HashMap>(); + for ( List annotationList : classInfo.annotations().values() ) { + for ( AnnotationInstance instance : annotationList ) { + String targetName = getTargetName( instance.target() ); + if ( targetName != null && ( name.equals( targetName ) + || getterName.equals( targetName ) ) ) { + addAnnotationToMap( instance, annotations ); + } + } + } + return annotations; + } + + private static void addAnnotationToMap(AnnotationInstance instance, Map> annotations) { + DotName dotName = instance.name(); + List list; + if ( annotations.containsKey( dotName ) ) { + list = annotations.get( dotName ); + } + else { + list = new ArrayList(); + annotations.put( dotName, list ); + } + list.add( instance ); + } + + private static Object getDefaultValue(AnnotationInstance annotation, String element, ClassLoaderService classLoaderService) { + //todo : would it be better to lookup each annotation class once and store this info in a Map primarily by the class? + + String name = annotation.name().toString(); + String fqElement = name + '.' + element; + Object val = DEFAULT_VALUES_BY_ELEMENT.get( fqElement ); + if ( val != null ) { + return val; + } + try { + Class returnType = classLoaderService.classForName( name ).getMethod( element ).getReturnType(); + val = classLoaderService.classForName( name ).getMethod( element ).getDefaultValue(); + if ( val != null ) { + if ( val instanceof Class ) { + // Annotation parameters of type Class are handled using Strings + val = ( ( Class ) val ).getName(); + } + if ( Proxy.isProxyClass( val.getClass() ) ) { + // val is a Proxy if the annotation field was itself an annotation. In those cases, we generally + // do not care about the value -- we'd ignore it anyway. Simply return null. + return null; + } + } + DEFAULT_VALUES_BY_ELEMENT.put( fqElement, val ); + return val; + } + catch ( RuntimeException error ) { + throw error; + } + catch ( Exception error ) { + throw new AssertionFailure( + String.format( "The annotation %s does not define a parameter '%s'", name, element ), + error + ); + } + } + + private static T defaultAnnotationParameter(Object defaultValue, Class type) { + if (defaultValue == null) { + return null; + } + + Object returnValue = defaultValue; + + // resolve some mismatches between what's stored in jandex and what the defaults are for annotations + // in case of nested annotation arrays, jandex returns arrays of AnnotationInstances, hence we return + // an empty array of this type here + if ( defaultValue.getClass().isArray() && defaultValue.getClass().getComponentType().isAnnotation() ) { + returnValue = new AnnotationInstance[0]; + } + return type.cast( nullIfUndefined( returnValue, type ) ); + } + + private static T explicitAnnotationParameter(AnnotationValue annotationValue, Class type) { + Object returnValue = annotationValue.value(); + + // if the jandex return type is Type we actually try to retrieve a class parameter + // for our purposes we just return the fqcn of the class + if ( returnValue instanceof Type ) { + returnValue = ( (Type) returnValue ).name().toString(); + } + + // arrays we have to handle explicitly + if ( type.isArray() ) { + AnnotationValue[] values = (AnnotationValue[]) returnValue; + Class componentType = type.getComponentType(); + Object[] arr = (Object[]) Array.newInstance( componentType, values.length ); + for ( int i = 0; i < values.length; i++ ) { + arr[i] = componentType.cast( values[i].value() ); + } + returnValue = arr; + } + else if ( type.isEnum() && String.class.isInstance( returnValue ) ) { + returnValue = Enum.valueOf( (Class) type, (String) returnValue ); + } + return type.cast( nullIfUndefined( returnValue, type ) ); + } + + /** + * Swaps type-specific undefined values with {@code null}. + * + * @param value The value + * @param type The target type + * + * @return {@code null} if value is deemed to UNDEFINED; value itself otherwise. + */ + private static Object nullIfUndefined(Object value, Class type) { + if ( value instanceof Type ) { + value = ( (Type) value ).name().toString(); + if ( void.class.getName().equals( value ) ) { + value = null; + } + } + + if ( String.class.equals( type ) ) { + if ( "".equals( type.cast( value ) ) ) { + value = null; + } + } + return value; + } + + private static String getTargetName(AnnotationTarget target) { + String targetName = null; + if ( target instanceof FieldInfo ) { + targetName = ( (FieldInfo) target ).name(); + } + else if ( target instanceof MethodInfo ) { + targetName = ( (MethodInfo) target ).name(); + } + else if ( target instanceof ClassInfo ) { + targetName = ( (ClassInfo) target ).name().toString(); + } + return targetName; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/package.html new file mode 100755 index 000000000000..2e9418fc1c81 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/annotations/util/package.html @@ -0,0 +1,33 @@ + + + + + +

      + Utility classes for processing the annotation configuration. +

      + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractConstraintSource.java new file mode 100644 index 000000000000..a8abce0c3292 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractConstraintSource.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.spi.ConstraintSource; + +/** + * @author Hardy Ferentschik + */ +class AbstractConstraintSource implements ConstraintSource { + protected final String name; + protected final String tableName; + protected final List columnNames = new ArrayList(); + protected final List orderings = new ArrayList(); + + protected AbstractConstraintSource(String name, String tableName) { + this.name = name; + this.tableName = tableName; + } + + @Override + public String name() { + return name; + } + + @Override + public String getTableName() { + return tableName; + } + + @Override + public List columnNames() { + return columnNames; + } + + public void addColumnName( String columnName ) { + columnNames.add( columnName ); + // TODO: Can HBM have orderings? For now, just add a null -- Binder expects columnNames and + // orderings to be the same size. Find a better data representation... + orderings.add( null ); + } + + public List orderings() { + return orderings; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + AbstractConstraintSource that = (AbstractConstraintSource) o; + + if ( columnNames != null ? !columnNames.equals( that.columnNames ) : that.columnNames != null ) { + return false; + } + if ( orderings != null ? !orderings.equals( that.orderings ) : that.orderings != null ) { + return false; + } + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( tableName != null ? !tableName.equals( that.tableName ) : that.tableName != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( tableName != null ? tableName.hashCode() : 0 ); + result = 31 * result + ( columnNames != null ? columnNames.hashCode() : 0 ); + result = 31 * result + ( orderings != null ? orderings.hashCode() : 0 ); + return result; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEmbeddableJaxbSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEmbeddableJaxbSource.java new file mode 100644 index 000000000000..3ec044ff3c09 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEmbeddableJaxbSource.java @@ -0,0 +1,129 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbAnyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDynamicComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbNestedCompositeElementElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPrimitiveArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertiesElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSetElement; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractEmbeddableJaxbSource implements EmbeddableJaxbSource { + @Override + public List getKeyPropertyElementList() { + return Collections.emptyList(); + } + + @Override + public List getKeyManyToOneElementList() { + return Collections.emptyList(); + } + + @Override + public List getPropertyElementList() { + return Collections.emptyList(); + } + + @Override + public List getManyToOneElementList() { + return Collections.emptyList(); + } + + @Override + public List getOneToOneElementList() { + return Collections.emptyList(); + } + + @Override + public List getComponentElementList() { + return Collections.emptyList(); + } + + @Override + public List getNestedCompositeElementList() { + return Collections.emptyList(); + } + + @Override + public List getDynamicComponentElementList() { + return Collections.emptyList(); + } + + @Override + public List getPropertiesElementList() { + return Collections.emptyList(); + } + + @Override + public List getAnyElementList() { + return Collections.emptyList(); + } + + @Override + public List getMapElementList() { + return Collections.emptyList(); + } + + @Override + public List getSetElementList() { + return Collections.emptyList(); + } + + @Override + public List getListElementList() { + return Collections.emptyList(); + } + + @Override + public List getBagElementList() { + return Collections.emptyList(); + } + + @Override + public List getArrayElementList() { + return Collections.emptyList(); + } + + @Override + public List getPrimitiveArrayElementList() { + return Collections.emptyList(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEmbeddedAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEmbeddedAttributeSourceImpl.java new file mode 100644 index 000000000000..5debfa0644eb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEmbeddedAttributeSourceImpl.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.internal.jaxb.hbm.ComponentSourceElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Common bas class for and mappings. + * + * @author Steve Ebersole + */ +public abstract class AbstractEmbeddedAttributeSourceImpl + extends AbstractHbmSourceNode + implements EmbeddedAttributeSource { + + private final ComponentSourceElement jaxbComponentSourceElement; + private final EmbeddableSourceImpl embeddableSource; + + protected AbstractEmbeddedAttributeSourceImpl( + MappingDocument sourceMappingDocument, + AttributeSourceContainer parentContainer, + AttributeRole attributeRoleBase, + AttributePath attributePathBase, + ComponentSourceElement jaxbComponentSourceElement, + EmbeddableJaxbSource embeddableJaxbSource, + NaturalIdMutability naturalIdMutability, + String logicalTableName) { + super( sourceMappingDocument ); + this.jaxbComponentSourceElement = jaxbComponentSourceElement; + this.embeddableSource = new EmbeddableSourceImpl( + sourceMappingDocument, + attributeRoleBase, + attributePathBase, + embeddableJaxbSource, + logicalTableName, + naturalIdMutability + ); + } + + protected ComponentSourceElement jaxbComponentSourceElement() { + return jaxbComponentSourceElement; + } + + @Override + public EmbeddableSource getEmbeddableSource() { + return embeddableSource; + } + + @Override + public String getName() { + return jaxbComponentSourceElement.getName(); + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.COMPOSITE; + } + + @Override + public HibernateTypeSource getTypeInformation() { + // does not support type information. + return null; + } + + @Override + public String getPropertyAccessorName() { + return jaxbComponentSourceElement.getAccess(); + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return null; + } + + @Override + public Collection getToolingHintSources() { + return jaxbComponentSourceElement.getMeta(); + } + + @Override + public PropertyGeneration getGeneration() { + // todo : is this correct here? + return null; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // relational value source info comes from the individual sub-attributes + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public List relationalValueSources() { + // none, they are defined on the simple sub-attributes + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEntitySourceImpl.java new file mode 100644 index 000000000000..f0a6fd459773 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractEntitySourceImpl.java @@ -0,0 +1,638 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.EntityMode; +import org.hibernate.TruthValue; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbAnyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDynamicComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIdbagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSetElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTuplizerElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JoinElementSource; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.ConstraintSource; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.JpaCallbackSource; +import org.hibernate.metamodel.source.spi.SecondaryTableSource; +import org.hibernate.metamodel.source.spi.SubclassEntitySource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.xml.spi.Origin; + +/** + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Brett Meyer + */ +public abstract class AbstractEntitySourceImpl + extends AbstractHbmSourceNode + implements EntitySource, Helper.InLineViewNameInferrer { + + private final EntityElement entityElement; + private final String className; + private final String entityName; + private final String jpaEntityName; + + private final AttributeRole attributeRoleBase; + private final AttributePath attributePathBase; + + private List subclassEntitySources = new ArrayList(); + + private int inLineViewCount = 0; + + // logically final, but built during 'afterInstantiation' callback + private List attributeSources; + private Set secondaryTableSources; + private final FilterSource[] filterSources; + + private Map constraintMap = new HashMap(); + + protected AbstractEntitySourceImpl(MappingDocument sourceMappingDocument, EntityElement entityElement) { + super( sourceMappingDocument ); + this.entityElement = entityElement; + + this.className = bindingContext().qualifyClassName( entityElement.getName() ); + if ( StringHelper.isNotEmpty( entityElement.getEntityName() ) ) { + this.entityName = entityElement.getEntityName(); + this.jpaEntityName = entityElement.getEntityName(); + } + else { + this.entityName = className; + this.jpaEntityName = StringHelper.unqualify( className ); + } + + this.attributePathBase = new AttributePath(); + this.attributeRoleBase = new AttributeRole( entityName ); + + this.filterSources = buildFilterSources(); + } + + @Override + public String getTypeName() { + return StringHelper.isNotEmpty( className ) ? className : entityName; + } + + @Override + public AttributePath getAttributePathBase() { + return attributePathBase; + } + + @Override + public AttributeRole getAttributeRoleBase() { + return attributeRoleBase; + } + + @Override + public Collection getSubTypes() { + return subclassEntitySources; + } + + private FilterSource[] buildFilterSources() { + //todo for now, i think all EntityElement should support this. + if ( JaxbClassElement.class.isInstance( entityElement() ) ) { + JaxbClassElement jaxbClassElement = JaxbClassElement.class.cast( entityElement() ); + final int size = jaxbClassElement.getFilter().size(); + if ( size == 0 ) { + return null; + } + + FilterSource[] results = new FilterSource[size]; + for ( int i = 0; i < size; i++ ) { + JaxbFilterElement element = jaxbClassElement.getFilter().get( i ); + results[i] = new FilterSourceImpl( sourceMappingDocument(), element ); + } + return results; + } + else { + return null; + } + + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public String inferInLineViewName() { + return entityName + '#' + (++inLineViewCount); + } + + protected void afterInstantiation() { + this.attributeSources = buildAttributeSources(); + this.secondaryTableSources = buildSecondaryTables(); + } + + protected List buildAttributeSources() { + List attributeSources = new ArrayList(); + buildAttributeSources( attributeSources ); + return attributeSources; + } + + protected List buildAttributeSources(List attributeSources) { + return buildAttributeSources( entityElement, attributeSources, null, NaturalIdMutability.NOT_NATURAL_ID ); + } + + protected List buildAttributeSources( + EntityElement element, + List attributeSources, + String logicTalbeName, + NaturalIdMutability naturalIdMutability){ + processPropertyAttributes( attributeSources, element.getProperty(), logicTalbeName, naturalIdMutability ); + processComponentAttributes( + attributeSources, + element.getComponent(), + logicTalbeName, + naturalIdMutability + ); + processDynamicComponentAttributes( + attributeSources, + element.getDynamicComponent(), + logicTalbeName, + naturalIdMutability + ); + processManyToOneAttributes( + attributeSources, + element.getManyToOne(), + logicTalbeName, + naturalIdMutability + ); + processOneToOneAttributes( + attributeSources, + element.getOneToOne(), + logicTalbeName, + naturalIdMutability + ); + processAnyAttributes( + attributeSources, + element.getAny(), + logicTalbeName, + naturalIdMutability + ); + processMapAttributes( attributeSources, element.getMap() ); + processListAttributes( attributeSources, element.getList() ); + processArrayAttributes( attributeSources, element.getArray() ); + processSetAttributes( attributeSources, element.getSet() ); + processIdBagAttributes( attributeSources, element.getIdbag() ); + processBagAttributes( attributeSources, element.getBag() ); + return attributeSources; + } + + protected void processPropertyAttributes( + List results, + List propertyElements, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + for ( JaxbPropertyElement element : propertyElements ) { + results.add( + new PropertyAttributeSourceImpl( + sourceMappingDocument(), + this, + element, + logicalTableName, + naturalIdMutability + ) + ); + + // TODO: Not sure this is the right place to do this. Can index constraints be defined by anything other + // than just a property? Split off into its own process method? + for ( JaxbColumnElement column : element.getColumn() ) { + // An index constraint can happen on the column element or the surrounding property element. + if ( !StringHelper.isEmpty( column.getIndex() ) ) { + addColumnToIndexConstraint( column.getIndex(), logicalTableName, column.getName() ); + } + if ( !StringHelper.isEmpty( element.getIndex() ) ) { + addColumnToIndexConstraint( element.getIndex(), logicalTableName, column.getName() ); + } + } + } + } + + private void addColumnToIndexConstraint(String constraintName, String logicalTableName, String columnName) { + if ( !constraintMap.containsKey( constraintName ) ) { + constraintMap.put( constraintName, new IndexConstraintSourceImpl( constraintName, logicalTableName ) ); + } + ( (AbstractConstraintSource) constraintMap.get( constraintName ) ).addColumnName( columnName ); + } + + protected void processComponentAttributes(List results, + List elements, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + for ( JaxbComponentElement element : elements ) { + results.add( + new EmbeddedAttributeSourceImpl( + sourceMappingDocument(), + this, + element, + naturalIdMutability, + logicalTableName + ) + ); + } + } + + protected void processDynamicComponentAttributes(List results, + List elements, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + // todo : implement + } + + protected void processManyToOneAttributes(List results, + List elements, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + for ( JaxbManyToOneElement element : elements ) { + results.add( + new ManyToOneAttributeSourceImpl( + sourceMappingDocument(), + this, + element, + logicalTableName, + naturalIdMutability + ) + ); + } + } + protected void processOneToOneAttributes(List results, + List elements, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + for ( JaxbOneToOneElement element : elements ) { + results.add( + new OneToOneAttributeSourceImpl( + sourceMappingDocument(), + this, + element, + logicalTableName, + naturalIdMutability + ) + ); + } + } + + protected void processAnyAttributes(List results, + List elements, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + // todo : implement + } + + protected void processMapAttributes(List results, + List propertyElements){ + for ( JaxbMapElement element : propertyElements ) { + results.add( + new MapSourceImpl( + sourceMappingDocument(), + element, this + ) + ); + } + } + protected void processArrayAttributes(List results, + List propertyElements){ + for ( JaxbArrayElement element : propertyElements ) { + results.add( + new ArraySourceImpl( + sourceMappingDocument(), + element, this + ) + ); + } + } + protected void processListAttributes(List results, + List propertyElements){ + for ( JaxbListElement element : propertyElements ) { + results.add( + new ListSourceImpl( + sourceMappingDocument(), + element, this + ) + ); + } + } + protected void processSetAttributes(List results, + List propertyElements){ + for ( JaxbSetElement element : propertyElements ) { + results.add( + new SetSourceImpl( + sourceMappingDocument(), + element, + this + ) + ); + } + } + + protected void processIdBagAttributes( + List results, + List elements){ + for ( JaxbIdbagElement element : elements ) { + results.add( + new IdBagSourceImpl( + sourceMappingDocument(), + element, + this + ) + ); + } + } + + protected void processBagAttributes( + List results, + List propertyElements) { + for ( JaxbBagElement element : propertyElements ) { + results.add( + new BagSourceImpl( + sourceMappingDocument(), + element, + this + ) + ); + } + } + + + private Set buildSecondaryTables() { + if ( ! JoinElementSource.class.isInstance( entityElement ) ) { + return Collections.emptySet(); + } + + final Set secondaryTableSources = new HashSet(); + for ( JaxbJoinElement joinElement : ( (JoinElementSource) entityElement ).getJoin() ) { + final SecondaryTableSourceImpl secondaryTableSource = new SecondaryTableSourceImpl( + sourceMappingDocument(), + joinElement, + this + ); + secondaryTableSources.add( secondaryTableSource ); + + final String logicalTableName = secondaryTableSource.getLogicalTableNameForContainedColumns(); + final NaturalIdMutability naturalIdMutability = NaturalIdMutability.NOT_NATURAL_ID; + processAnyAttributes( + attributeSources, + joinElement.getAny(), + logicalTableName, + naturalIdMutability + ); + processComponentAttributes( + attributeSources, + joinElement.getComponent(), + logicalTableName, + naturalIdMutability + ); + processDynamicComponentAttributes( + attributeSources, + joinElement.getDynamicComponent(), + logicalTableName, + naturalIdMutability + ); + processManyToOneAttributes( + attributeSources, + joinElement.getManyToOne(), + logicalTableName, + naturalIdMutability + ); + processPropertyAttributes( + attributeSources, + joinElement.getProperty(), + logicalTableName, + naturalIdMutability + ); + } + return secondaryTableSources; + } + + protected EntityElement entityElement() { + return entityElement; + } + + @Override + public Origin getOrigin() { + return origin(); + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return bindingContext(); + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + public String getClassName() { + return className; + } + + @Override + public String getJpaEntityName() { + return jpaEntityName; + } + + @Override + public boolean isAbstract() { + return entityElement().isAbstract(); + } + + @Override + public boolean isLazy() { + if(entityElement.isLazy()==null){ + return getLocalBindingContext().getMappingDefaults().areAssociationsLazy(); + } + return entityElement().isLazy(); + } + + @Override + public String getProxy() { + return entityElement.getProxy(); + } + + @Override + public int getBatchSize() { + return entityElement.getBatchSize(); + } + + @Override + public boolean isDynamicInsert() { + return entityElement.isDynamicInsert(); + } + + @Override + public boolean isDynamicUpdate() { + return entityElement.isDynamicUpdate(); + } + + @Override + public boolean isSelectBeforeUpdate() { + return entityElement.isSelectBeforeUpdate(); + } + + protected EntityMode determineEntityMode() { + return StringHelper.isNotEmpty( getClassName() ) ? EntityMode.POJO : EntityMode.MAP; + } + + @Override + public String getCustomTuplizerClassName() { + if ( entityElement.getTuplizer() == null ) { + return null; + } + final EntityMode entityMode = determineEntityMode(); + for ( JaxbTuplizerElement tuplizerElement : entityElement.getTuplizer() ) { + if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode().value() ) ) { + return tuplizerElement.getClazz(); + } + } + return null; + } + + @Override + public String getCustomPersisterClassName() { + return getLocalBindingContext().qualifyClassName( entityElement.getPersister() ); + } + + @Override + public String getCustomLoaderName() { + return entityElement.getLoader() != null ? entityElement.getLoader().getQueryRef() : null; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return Helper.buildCustomSql( entityElement.getSqlInsert() ); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return Helper.buildCustomSql( entityElement.getSqlUpdate() ); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return Helper.buildCustomSql( entityElement.getSqlDelete() ); + } + + @Override + public String[] getSynchronizedTableNames() { + if ( CollectionHelper.isEmpty( entityElement.getSynchronize() ) ) { + return StringHelper.EMPTY_STRINGS; + } + else { + final int size = entityElement.getSynchronize().size(); + final String[] synchronizedTableNames = new String[size]; + for ( int i = 0; i < size; i++ ) { + synchronizedTableNames[i] = entityElement.getSynchronize().get( i ).getTable(); + } + return synchronizedTableNames; + } + } + + @Override + public java.util.Collection getToolingHintSources() { + return entityElement.getMeta(); + } + + @Override + public List attributeSources() { + return attributeSources; + } + + private EntityHierarchySourceImpl entityHierarchy; + + public void injectHierarchy(EntityHierarchySourceImpl entityHierarchy) { + this.entityHierarchy = entityHierarchy; + } + + @Override + public EntityHierarchySource getHierarchy() { + return entityHierarchy; + } + + void add(SubclassEntitySource subclassEntitySource) { + add( (SubclassEntitySourceImpl) subclassEntitySource ); + } + + void add(SubclassEntitySourceImpl subclassEntitySource) { + subclassEntitySource.injectHierarchy( entityHierarchy ); + entityHierarchy.processSubclass( subclassEntitySource ); + subclassEntitySources.add( subclassEntitySource ); + } + + @Override + public Iterable getConstraints() { + return constraintMap.values(); + } + + @Override + public Set getSecondaryTables() { + return secondaryTableSources; + } + + @Override + @SuppressWarnings( {"unchecked"}) + public List getJpaCallbackClasses() { + return Collections.EMPTY_LIST; + } + + @Override + public TruthValue quoteIdentifiersLocalToEntity() { + // HBM does not allow for this + return TruthValue.UNKNOWN; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractHbmSourceNode.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractHbmSourceNode.java new file mode 100644 index 000000000000..9c9a22487cdf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractHbmSourceNode.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; + +/** + * Base class for any and all source objects coming from {@code hbm.xml} parsing. Defines standard access + * back to the {@link MappingDocument} object and the services it provides (namely access to + * {@link HbmBindingContext}). + * + * @author Steve Ebersole + */ +public abstract class AbstractHbmSourceNode { + private final MappingDocument sourceMappingDocument; + + protected AbstractHbmSourceNode(MappingDocument sourceMappingDocument) { + this.sourceMappingDocument = sourceMappingDocument; + } + + protected MappingDocument sourceMappingDocument() { + return sourceMappingDocument; + } + + protected HbmBindingContext bindingContext() { + return sourceMappingDocument().getMappingLocalBindingContext(); + } + + protected Origin origin() { + return sourceMappingDocument().getOrigin(); + } + + protected BindResult mappingRoot() { + return sourceMappingDocument().getJaxbRoot(); + } + + protected JavaTypeDescriptor typeDescriptor(String className) { + return className == null ? + null : + bindingContext().typeDescriptor( className ); + } + + protected MappingException makeMappingException(String message) { + return bindingContext().makeMappingException( message ); + } + + protected MappingException makeMappingException(String message, Exception cause) { + return bindingContext().makeMappingException( message, cause ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractPluralAssociationElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractPluralAssociationElementSourceImpl.java new file mode 100644 index 000000000000..96a22fe376b8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractPluralAssociationElementSourceImpl.java @@ -0,0 +1,72 @@ +/** + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.metamodel.source.spi.AssociationSource; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; + +/** + + * @author Gail Badner + + */ +public abstract class AbstractPluralAssociationElementSourceImpl + extends AbstractHbmSourceNode implements AssociationSource { + + private final PluralAttributeSource pluralAttributeSource; + private final Set ownedAssociationSources = new HashSet( ); + + public AbstractPluralAssociationElementSourceImpl( + MappingDocument mappingDocument, + PluralAttributeSource pluralAttributeSource) { + super( mappingDocument ); + this.pluralAttributeSource = pluralAttributeSource; + } + + @Override + public AttributeSource getAttributeSource() { + return pluralAttributeSource; + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + if ( attributeSource == null ) { + throw new IllegalArgumentException( "attributeSource must be non-null." ); + } + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractPluralAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractPluralAttributeSourceImpl.java new file mode 100644 index 000000000000..a13f1e55fe58 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractPluralAttributeSourceImpl.java @@ -0,0 +1,452 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.PluralAttributeElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.CollectionIdSource; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSource; +import org.hibernate.metamodel.source.spi.PluralAttributeKeySource; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; + +/** + * @author Steve Ebersole + * @author Brett Meyer + */ +public abstract class AbstractPluralAttributeSourceImpl + extends AbstractHbmSourceNode + implements PluralAttributeSource, Helper.InLineViewNameInferrer { + private final PluralAttributeElement pluralAttributeElement; + private final AttributeSourceContainer container; + + private final AttributeRole attributeRole; + private final AttributePath attributePath; + + private final HibernateTypeSource typeInformation; + + private final PluralAttributeKeySource keySource; + private final PluralAttributeElementSource elementSource; + private final Caching caching; + private final FilterSource[] filterSources; + + private JavaTypeDescriptor elementTypeDescriptor; + + protected AbstractPluralAttributeSourceImpl( + MappingDocument sourceMappingDocument, + final PluralAttributeElement pluralAttributeElement, + AttributeSourceContainer container) { + super( sourceMappingDocument ); + this.pluralAttributeElement = pluralAttributeElement; + this.container = container; + + this.attributeRole = container.getAttributeRoleBase().append( pluralAttributeElement.getName() ); + this.attributePath = container.getAttributePathBase().append( pluralAttributeElement.getName() ); + + this.keySource = new PluralAttributeKeySourceImpl( + sourceMappingDocument(), + pluralAttributeElement.getKey(), + container + ); + this.elementSource = interpretElementType(); + + this.caching = Helper.createCaching( pluralAttributeElement.getCache() ); + + this.typeInformation = new HibernateTypeSource() { + @Override + public String getName() { + return pluralAttributeElement.getCollectionType(); + } + + @Override + public Map getParameters() { + return Collections.emptyMap(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + this.filterSources = buildFilterSources(); + } + + private FilterSource[] buildFilterSources() { + final int size = pluralAttributeElement.getFilter().size(); + if ( size == 0 ) { + return null; + } + + FilterSource[] results = new FilterSource[size]; + for ( int i = 0; i < size; i++ ) { + JaxbFilterElement element = pluralAttributeElement.getFilter().get( i ); + results[i] = new FilterSourceImpl( sourceMappingDocument(), element ); + } + return results; + + } + + private PluralAttributeElementSource interpretElementType() { + if ( pluralAttributeElement.getElement() != null ) { + // TODO: Is elementClassReference even needed in this context? + // If so, getType is currently null. +// elementClassReference = makeClassReference(pluralAttributeElement +// .getElement().getType().getName()); + return new PluralAttributeElementSourceBasicImpl( + sourceMappingDocument(), + pluralAttributeElement.getElement() + ); + } + else if ( pluralAttributeElement.getCompositeElement() != null ) { + elementTypeDescriptor = typeDescriptor( + pluralAttributeElement + .getCompositeElement().getClazz() + ); + return new PluralAttributeElementSourceEmbeddedImpl( + sourceMappingDocument(), + this, + pluralAttributeElement.getCompositeElement(), + pluralAttributeElement.getCascade() + ); + } + else if ( pluralAttributeElement.getOneToMany() != null ) { + elementTypeDescriptor = typeDescriptor( + pluralAttributeElement + .getOneToMany().getClazz() + ); + return new PluralAttributeElementSourceOneToManyImpl( + sourceMappingDocument(), + this, + pluralAttributeElement.getOneToMany(), + pluralAttributeElement.getCascade() + ); + } + else if ( pluralAttributeElement.getManyToMany() != null ) { + elementTypeDescriptor = typeDescriptor( + pluralAttributeElement + .getManyToMany().getClazz() + ); + return new PluralAttributeElementSourceManyToManyImpl( + sourceMappingDocument(), + this, + pluralAttributeElement.getManyToMany(), + pluralAttributeElement.getCascade() + ); + } + else if ( pluralAttributeElement.getManyToAny() != null ) { + throw new NotYetImplementedException( "Support for many-to-any not yet implemented" ); +// return Nature.MANY_TO_ANY; + } + else { + throw new MappingException( + "Unexpected collection element type : " + pluralAttributeElement.getName(), + bindingContext().getOrigin() + ); + } + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public PluralAttributeElementSource resolvePluralAttributeElementSource(AttributeSourceResolutionContext context) { + // elementSource is already resolved; nothing to do. + return elementSource; + } + + @Override + public boolean usesJoinTable() { + switch ( elementSource.getNature() ) { + case BASIC: + case AGGREGATE: + case ONE_TO_MANY: + return false; + case MANY_TO_MANY: + return true; + case MANY_TO_ANY: + throw new NotYetImplementedException( + String.format( "%s is not implemented yet.", elementSource.getNature() ) + ); + default: + throw new AssertionFailure( + String.format( + "Unexpected plural attribute element source nature: %s", + elementSource.getNature() + ) + ); + } + } + + public PluralAttributeElement getPluralAttributeElement() { + return pluralAttributeElement; + } + + protected AttributeSourceContainer container() { + return container; + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public PluralAttributeKeySource getKeySource() { + return keySource; + } + + @Override + public PluralAttributeElementSource getElementSource() { + return elementSource; + } + + @Override + public JavaTypeDescriptor getElementTypeDescriptor() { + return elementTypeDescriptor; + } + + @Override + public boolean isMutable() { + return pluralAttributeElement.isMutable(); + } + + @Override + public int getBatchSize() { + return pluralAttributeElement.getBatchSize(); + } + + @Override + public String getMappedBy() { + return null; + } + + @Override + public String inferInLineViewName() { + return getAttributeRole().getFullPath(); + } + + @Override + public CollectionIdSource getCollectionIdSource() { + return null; + } + + @Override + public TableSpecificationSource getCollectionTableSpecificationSource() { + return pluralAttributeElement.getOneToMany() == null ? + Helper.createTableSource( sourceMappingDocument(), pluralAttributeElement, this ) : + null; + } + + @Override + public String getCollectionTableComment() { + return pluralAttributeElement.getComment(); + } + + @Override + public String getCollectionTableCheck() { + return pluralAttributeElement.getCheck(); + } + + @Override + public Caching getCaching() { + return caching; + } + + @Override + public String getWhere() { + return pluralAttributeElement.getWhere(); + } + + @Override + public String getName() { + return pluralAttributeElement.getName(); + } + + @Override + public boolean isSingular() { + return false; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeInformation; + } + + @Override + public String getPropertyAccessorName() { + return pluralAttributeElement.getAccess(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return pluralAttributeElement.isOptimisticLock(); + } + + @Override + public boolean isInverse() { + return pluralAttributeElement.isInverse(); + } + + @Override + public String getCustomPersisterClassName() { + return pluralAttributeElement.getPersister(); + } + + @Override + public String getCustomLoaderName() { + return pluralAttributeElement.getLoader() == null + ? null + : pluralAttributeElement.getLoader().getQueryRef(); + } + + @Override + public CustomSQL getCustomSqlInsert() { + return Helper.buildCustomSql( pluralAttributeElement.getSqlInsert() ); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return Helper.buildCustomSql( pluralAttributeElement.getSqlUpdate() ); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return Helper.buildCustomSql( pluralAttributeElement.getSqlDelete() ); + } + + @Override + public CustomSQL getCustomSqlDeleteAll() { + return Helper.buildCustomSql( pluralAttributeElement.getSqlDeleteAll() ); + } + + @Override + public Collection getToolingHintSources() { + return pluralAttributeElement.getMeta(); + } + + @Override + public FetchTiming getFetchTiming() { + final String fetchSelection = pluralAttributeElement.getFetch() != null ? + pluralAttributeElement.getFetch().value() : + null; + final String lazySelection = pluralAttributeElement.getLazy() != null + ? pluralAttributeElement.getLazy().value() + : null; + final String outerJoinSelection = pluralAttributeElement.getOuterJoin() != null + ? pluralAttributeElement.getOuterJoin().value() + : null; + + if ( lazySelection == null ) { + if ( "join".equals( fetchSelection ) && "true".equals( outerJoinSelection ) ) { + return FetchTiming.IMMEDIATE; + } + else if ( "false".equals( outerJoinSelection ) ) { + return FetchTiming.DELAYED; + } + else { + return bindingContext().getMappingDefaults().areAssociationsLazy() + ? FetchTiming.DELAYED + : FetchTiming.IMMEDIATE; + } + } + else if ( "extra".equals( lazySelection ) ) { + return FetchTiming.EXTRA_LAZY; + } + else if ( "true".equals( lazySelection ) ) { + return FetchTiming.DELAYED; + } + else if ( "false".equals( lazySelection ) ) { + return FetchTiming.IMMEDIATE; + } + + throw new MappingException( + String.format( + "Unexpected lazy selection [%s] on '%s'", + lazySelection, + pluralAttributeElement.getName() + ), + origin() + ); + } + + @Override + public FetchStyle getFetchStyle() { + final String fetchSelection = pluralAttributeElement.getFetch() != null ? + pluralAttributeElement.getFetch().value() : + null; + final String outerJoinSelection = pluralAttributeElement.getOuterJoin() != null + ? pluralAttributeElement.getOuterJoin().value() + : null; + final int batchSize = getBatchSize(); + + if ( fetchSelection == null ) { + if ( outerJoinSelection == null ) { + return batchSize > 1 ? FetchStyle.BATCH : FetchStyle.SELECT; + } + else { + if ( "auto".equals( outerJoinSelection ) ) { + return bindingContext().getMappingDefaults().areAssociationsLazy() + ? FetchStyle.SELECT + : FetchStyle.JOIN; + } + else { + return "true".equals( outerJoinSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; + } + } + } + else { + if ( "subselect".equals( fetchSelection ) ) { + return FetchStyle.SUBSELECT; + } + else { + return "join".equals( fetchSelection ) ? FetchStyle.JOIN : FetchStyle.SELECT; + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractReturnBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractReturnBinder.java new file mode 100644 index 000000000000..9c6977ef8259 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractReturnBinder.java @@ -0,0 +1,135 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.hibernate.LockMode; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.ReturnElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; + +/** + * @author Strong Liu + */ +abstract class AbstractReturnBinder { + protected final InFlightMetadataCollector metadataCollector; + protected final T element; + protected final LocalBindingContext context; + protected final String alias; + protected final LockMode lockMode; + protected List returnPropertyElements; + + AbstractReturnBinder( + final T element, + final int elementIndex, + final LocalBindingContext context, + final InFlightMetadataCollector metadataCollector) { + this.context = context; + this.metadataCollector = metadataCollector; + this.element = element; + this.alias = getAlias( element, elementIndex ); + this.lockMode = Helper.interpretLockMode( element.getLockMode(), context ); + this.returnPropertyElements = element.getReturnProperty(); + } + + private static String getAlias(ReturnElement element, int elementCount) { + return StringHelper.isEmpty( element.getAlias() ) ? "alias_" + elementCount : element.getAlias(); + } + + abstract NativeSQLQueryReturn process(); + + protected void processReturnProperties(ReturnPropertiesCallback callback) { + for ( JaxbReturnPropertyElement propertyElement : returnPropertyElements ) { + callback.process( propertyElement ); + } + } + + static interface ReturnPropertiesCallback { + void process(JaxbReturnPropertyElement propertyElement); + } + + static class ReturnPropertiesCallbackImpl implements ReturnPropertiesCallback { + private final LocalBindingContext bindingContext; + private final String alias; + private final Map propertyResults; + + ReturnPropertiesCallbackImpl( + final String alias, final Map propertyResults, + final LocalBindingContext bindingContext) { + this.alias = alias; + this.bindingContext = bindingContext; + this.propertyResults = propertyResults; + } + + @Override + public void process(final JaxbReturnPropertyElement propertyElement) { + final String name = propertyElement.getName(); + if ( StringHelper.isEmpty( name ) ) { + throw bindingContext.makeMappingException( "Empty return property name on alias " + alias ); + } + if ( name.contains( "." ) ) { + throw bindingContext.makeMappingException( + "dotted notation in or not yet supported" + ); + } + if ( propertyResults.containsKey( name ) ) { + throw bindingContext.makeMappingException( + "duplicate return-property for property " + name + " on alias " + alias + ); + } + final List returnColumnNames = getResultColumns( propertyElement, bindingContext ); + + if ( returnColumnNames.isEmpty() ) { + throw bindingContext.makeMappingException( + "return-property for alias " + alias + " must specify at least one column or return-column name" + ); + } + + propertyResults.put( name, returnColumnNames.toArray( new String[returnColumnNames.size()] ) ); + } + + private static List getResultColumns( + final JaxbReturnPropertyElement propertyresult, final LocalBindingContext context) { + List allResultColumns = new ArrayList(); + if ( propertyresult.getColumn() != null ) { + String column = context.getMetadataCollector().getObjectNameNormalizer() + .normalizeIdentifierQuoting( propertyresult.getColumn() ); + allResultColumns.add( column ); + } + for ( JaxbReturnPropertyElement.JaxbReturnColumn returnColumn : propertyresult.getReturnColumn() ) { + if ( returnColumn.getName() != null ) { + String column = context.getMetadataCollector().getObjectNameNormalizer() + .normalizeIdentifierQuoting( returnColumn.getName() ); + + allResultColumns.add( column ); + } + } + return allResultColumns; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractToOneAttributeSourceImpl.java new file mode 100644 index 000000000000..8589f04f7543 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/AbstractToOneAttributeSourceImpl.java @@ -0,0 +1,272 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.MappedByAssociationSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.ToOneAttributeSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Gail Badner + */ +public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSourceNode implements ToOneAttributeSource{ + private final NaturalIdMutability naturalIdMutability; + private final String propertyRef; + private final Set ownedAssociationSources = new HashSet( ); + + AbstractToOneAttributeSourceImpl( + MappingDocument sourceMappingDocument, + NaturalIdMutability naturalIdMutability, + String propertyRef) { + super( sourceMappingDocument ); + this.naturalIdMutability = naturalIdMutability; + this.propertyRef = propertyRef; + + } + @Override + public HibernateTypeSource getTypeInformation() { + return Helper.TO_ONE_ATTRIBUTE_TYPE_SOURCE; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public PropertyGeneration getGeneration() { + return PropertyGeneration.NEVER; + } + + @Override + public boolean isIgnoreNotFound() { + return false; + } + + @Override + public boolean isLazy() { + return getFetchTiming() != FetchTiming.IMMEDIATE; + } + + protected abstract boolean requiresImmediateFetch(); + protected abstract String getFetchSelectionString(); + protected abstract String getLazySelectionString(); + protected abstract String getOuterJoinSelectionString(); + + @Override + public boolean isUnWrapProxy() { + final String lazySelection = getLazySelectionString(); + return lazySelection != null && lazySelection.equals( "no-proxy" ); + } + + @Override + public FetchTiming getFetchTiming() { + final String lazySelection = getLazySelectionString(); + + if ( lazySelection == null ) { + if ( requiresImmediateFetch() ) { + return FetchTiming.IMMEDIATE; + } + else if ( "join".equals( getFetchSelectionString() ) || "true".equals( getOuterJoinSelectionString() ) ) { + return FetchTiming.IMMEDIATE; + } + else if ( "false".equals( getOuterJoinSelectionString() ) ) { + return FetchTiming.DELAYED; + } + else { + return bindingContext().getMappingDefaults().areAssociationsLazy() + ? FetchTiming.DELAYED + : FetchTiming.IMMEDIATE; + } + } + else if ( "extra".equals( lazySelection ) ) { + // TODO: don't think "extra" is valid here + return FetchTiming.EXTRA_LAZY; + } + else if ( "true".equals( lazySelection ) || "proxy".equals( lazySelection ) || "no-proxy".equals( lazySelection ) ) { + return FetchTiming.DELAYED; + } + else if ( "false".equals( lazySelection ) ) { + return FetchTiming.IMMEDIATE; + } + + throw new MappingException( + String.format( + "Unexpected lazy selection [%s] on '%s'", + lazySelection, + getName() + ), + origin() + ); + } + + @Override + public FetchStyle getFetchStyle() { + // todo : handle batch fetches? + + if ( getFetchSelectionString() == null ) { + if ( requiresImmediateFetch() ) { + return FetchStyle.JOIN; + } + else if ( getOuterJoinSelectionString() == null ) { + return FetchStyle.SELECT; + } + else { + if ( "auto".equals( getOuterJoinSelectionString() ) ) { + return bindingContext().getMappingDefaults().areAssociationsLazy() + ? FetchStyle.SELECT + : FetchStyle.JOIN; + } + else { + return "true".equals( getOuterJoinSelectionString() ) ? FetchStyle.JOIN : FetchStyle.SELECT; + } + } + } + else { + return "join".equals( getFetchSelectionString() ) ? FetchStyle.JOIN : FetchStyle.SELECT; + } + } + + @Override + // TODO: change to return the default name for a single column + public List getDefaultNamingStrategies( + final String entityName, + final String tableName, + final AttributeBinding referencedAttributeBinding) { + if ( EmbeddedAttributeBinding.class.isInstance( referencedAttributeBinding ) ) { + EmbeddedAttributeBinding embeddedAttributeBinding = EmbeddedAttributeBinding.class.cast( + referencedAttributeBinding + ); + List result = new ArrayList(); + for ( final AttributeBinding attributeBinding : embeddedAttributeBinding.getEmbeddableBinding().attributeBindings() ) { + result.addAll( getDefaultNamingStrategies( entityName, tableName, attributeBinding ) ); + } + return result; + } + else { + List result = new ArrayList( 1 ); + result.add( + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.propertyToColumnName( getName() ); + } + } + ); + return result; + } + + } + + @Override + public Set getOwnedAssociationSources() { + return ownedAssociationSources; + } + + @Override + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource) { + ownedAssociationSources.add( attributeSource ); + } + + @Override + public boolean isMappedBy() { + // only applies to annotations + return false; + } + + @Override + public AttributeSource getAttributeSource() { + return this; + } + + @Override + public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { + // nothing to do + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return propertyRef == null + ? null + : new JoinColumnResolutionDelegateImpl( propertyRef ); + } + + public static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final String propertyRef; + + public JoinColumnResolutionDelegateImpl(String propertyRef) { + this.propertyRef = propertyRef; + } + + @Override + public String getReferencedAttributeName() { + return propertyRef; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( propertyRef ); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( propertyRef ); + } + } + + @Override + public boolean createForeignKeyConstraint() { + // TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)? + return true; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ArraySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ArraySourceImpl.java new file mode 100644 index 000000000000..5eb00196b7b1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ArraySourceImpl.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListIndexElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * @author Brett Meyer + */ +public class ArraySourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource { + + private final PluralAttributeSequentialIndexSource indexSource; + + public ArraySourceImpl( + MappingDocument sourceMappingDocument, + JaxbArrayElement arrayElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, arrayElement, container ); + JaxbListIndexElement listIndexElement = arrayElement.getListIndex(); + if ( listIndexElement == null ) { + this.indexSource = new PluralAttributeSequentialIndexSourceImpl( sourceMappingDocument(), arrayElement.getIndex() ); + } else { + this.indexSource = new PluralAttributeSequentialIndexSourceImpl( sourceMappingDocument(), listIndexElement ); + } + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } + + @Override + public JaxbArrayElement getPluralAttributeElement() { + return ( JaxbArrayElement ) super.getPluralAttributeElement(); + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.source.spi.PluralAttributeSource#getNature() + */ + @Override + public PluralAttributeNature getNature() { + return PluralAttributeNature.ARRAY; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/BagSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/BagSourceImpl.java new file mode 100644 index 000000000000..091670e19426 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/BagSourceImpl.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.Orderable; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * @author Steve Ebersole + */ +public class BagSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable { + public BagSourceImpl( + MappingDocument sourceMappingDocument, + JaxbBagElement bagElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, bagElement, container ); + } + + @Override + public PluralAttributeNature getNature() { + return PluralAttributeNature.BAG; + } + + @Override + public JaxbBagElement getPluralAttributeElement() { + return (JaxbBagElement) super.getPluralAttributeElement(); + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getOrder() { + return getPluralAttributeElement().getOrderBy(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ColumnAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ColumnAttributeSourceImpl.java new file mode 100644 index 000000000000..0c06de55142c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ColumnAttributeSourceImpl.java @@ -0,0 +1,148 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.relational.JdbcDataType; + +/** + * Implementation of a {@link ColumnSource} when the column is declared as just the name via the column XML + * attribute. For example, {@code }. + * + * @author Steve Ebersole + */ +class ColumnAttributeSourceImpl + extends AbstractHbmSourceNode + implements ColumnSource { + private final String tableName; + private final String columnName; + private final SizeSource sizeSource; + private TruthValue includedInInsert; + private TruthValue includedInUpdate; + private TruthValue nullable; + + ColumnAttributeSourceImpl( + MappingDocument mappingDocument, + String tableName, + String columnName, + SizeSource sizeSource, + TruthValue includedInInsert, + TruthValue includedInUpdate) { + this( mappingDocument, tableName, columnName, sizeSource, includedInInsert, includedInUpdate, TruthValue.UNKNOWN ); + } + + ColumnAttributeSourceImpl( + MappingDocument mappingDocument, + String tableName, + String columnName, + SizeSource sizeSource, + TruthValue includedInInsert, + TruthValue includedInUpdate, + TruthValue nullable) { + super( mappingDocument ); + this.tableName = tableName; + this.columnName = columnName; + this.sizeSource = sizeSource; + this.includedInInsert = includedInInsert; + this.includedInUpdate = includedInUpdate; + this.nullable = nullable; + } + + @Override + public Nature getNature() { + return Nature.COLUMN; + } + + @Override + public TruthValue isIncludedInInsert() { + return includedInInsert; + } + + @Override + public TruthValue isIncludedInUpdate() { + return includedInUpdate; + } + + @Override + public String getContainingTableName() { + return tableName; + } + + @Override + public String getName() { + return columnName; + } + + @Override + public TruthValue isNullable() { + return nullable; + } + + @Override + public String getDefaultValue() { + return null; + } + + @Override + public String getSqlType() { + return null; + } + + @Override + public JdbcDataType getDatatype() { + return null; + } + + @Override + public SizeSource getSizeSource() { + return sizeSource; + } + + @Override + public String getReadFragment() { + return null; + } + + @Override + public String getWriteFragment() { + return null; + } + + @Override + public boolean isUnique() { + return false; + } + + @Override + public String getCheckCondition() { + return null; + } + + @Override + public String getComment() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ColumnSourceImpl.java new file mode 100644 index 000000000000..2fdfc400e82a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ColumnSourceImpl.java @@ -0,0 +1,143 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.relational.JdbcDataType; + +/** +* @author Steve Ebersole +*/ +class ColumnSourceImpl + extends AbstractHbmSourceNode + implements ColumnSource { + private final String tableName; + private final JaxbColumnElement columnElement; + private final TruthValue includedInInsert; + private final TruthValue includedInUpdate; + private final TruthValue nullable; + + ColumnSourceImpl( + MappingDocument mappingDocument, + String tableName, + JaxbColumnElement columnElement, + TruthValue isIncludedInInsert, + TruthValue isIncludedInUpdate) { + this( mappingDocument, tableName, columnElement, isIncludedInInsert, isIncludedInUpdate, TruthValue.UNKNOWN ); + } + + ColumnSourceImpl( + MappingDocument mappingDocument, + String tableName, + JaxbColumnElement columnElement, + TruthValue isIncludedInInsert, + TruthValue isIncludedInUpdate, + TruthValue nullable) { + super( mappingDocument ); + this.tableName = tableName; + this.columnElement = columnElement; + this.nullable = nullable; + this.includedInInsert = isIncludedInInsert; + this.includedInUpdate = isIncludedInUpdate; + } + + @Override + public Nature getNature() { + return Nature.COLUMN; + } + + @Override + public String getName() { + return columnElement.getName(); + } + + @Override + public TruthValue isNullable() { + return nullable; + } + + @Override + public String getDefaultValue() { + return columnElement.getDefault(); + } + + @Override + public String getSqlType() { + return columnElement.getSqlType(); + } + + @Override + public JdbcDataType getDatatype() { + return null; + } + + @Override + public SizeSource getSizeSource() { + return new SizeSourceImpl( columnElement.getPrecision(), columnElement.getScale(), columnElement.getLength() ); + } + + @Override + public String getReadFragment() { + return columnElement.getRead(); + } + + @Override + public String getWriteFragment() { + return columnElement.getWrite(); + } + + @Override + public boolean isUnique() { + // TODO: should TruthValue be returned instead of boolean? + return columnElement.isUnique() != null && columnElement.isUnique().booleanValue(); + } + + @Override + public String getCheckCondition() { + return columnElement.getCheck(); + } + + @Override + public String getComment() { + return columnElement.getComment(); + } + + @Override + public TruthValue isIncludedInInsert() { + return includedInInsert; + } + + @Override + public TruthValue isIncludedInUpdate() { + return includedInUpdate; + } + + @Override + public String getContainingTableName() { + return tableName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddableJaxbSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddableJaxbSource.java new file mode 100644 index 000000000000..a8e8c6a0b49f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddableJaxbSource.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbAnyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDynamicComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbNestedCompositeElementElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPrimitiveArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertiesElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSetElement; + +/** + * Describes the JAXB source (HBM) for embeddable (composite) information. The + * HBM XML schema unfortunately did not define these consistently between + * {@code } and {@code }, so this contract unifies + * access to this information. + * + * @author Steve Ebersole + */ +public interface EmbeddableJaxbSource { + public String getClazz(); + + public String findParent(); + public String findTuplizer(); + + // todo : ultimately would be nice to remove the distinction between: + // * getKeyPropertyElementList() / getPropertyElementList() + // * getKeyManyToOneElementList() / getManyToOneElementList() + // the difference is really a matter of the "container", not the attribute + + public List getKeyPropertyElementList(); + + public List getKeyManyToOneElementList(); + + public List getPropertyElementList(); + + public List getManyToOneElementList(); + + public List getOneToOneElementList(); + + public List getComponentElementList(); + + public List getNestedCompositeElementList(); + + public List getDynamicComponentElementList(); + + public List getPropertiesElementList(); + + public List getAnyElementList(); + + public List getMapElementList(); + + public List getSetElementList(); + + public List getListElementList(); + + public List getBagElementList(); + + public List getArrayElementList(); + + public List getPrimitiveArrayElementList(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddableSourceImpl.java new file mode 100644 index 000000000000..bdc6b11538e9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddableSourceImpl.java @@ -0,0 +1,308 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbAnyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDynamicComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToManyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbNestedCompositeElementElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToManyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPrimitiveArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSetElement; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * @author Steve Ebersole + */ +public class EmbeddableSourceImpl extends AbstractHbmSourceNode implements EmbeddableSource { + private final EmbeddableJaxbSource embeddableSource; + private final JavaTypeDescriptor typeDescriptor; + + private final AttributeRole attributeRoleBase; + private final AttributePath attributePathBase; + + private final String logicalTableName; + private final NaturalIdMutability naturalIdMutability; + + private final List attributeSources; + + public EmbeddableSourceImpl( + MappingDocument mappingDocument, + AttributeRole attributeRoleBase, + AttributePath attributePathBase, + EmbeddableJaxbSource embeddableJaxbSource, + String logicalTableName, + NaturalIdMutability naturalIdMutability) { + super( mappingDocument ); + this.attributeRoleBase = attributeRoleBase; + this.attributePathBase = attributePathBase; + this.embeddableSource = embeddableJaxbSource; + this.logicalTableName = logicalTableName; + this.naturalIdMutability = naturalIdMutability; + + this.typeDescriptor = typeDescriptor( embeddableJaxbSource.getClazz() ); + + this.attributeSources = buildAttributeSources( embeddableJaxbSource, this ); + } + + @Override + public JavaTypeDescriptor getTypeDescriptor() { + return typeDescriptor; + } + + @Override + public String getParentReferenceAttributeName() { + return embeddableSource.findParent(); + } + + @Override + public String getExplicitTuplizerClassName() { + return embeddableSource.findTuplizer(); + } + + @Override + public AttributePath getAttributePathBase() { + return attributePathBase; + } + + @Override + public AttributeRole getAttributeRoleBase() { + return attributeRoleBase; + } + + @Override + public List attributeSources() { + return attributeSources; + } + + @Override + public LocalBindingContext getLocalBindingContext() { + return bindingContext(); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute building + + protected static List buildAttributeSources( + EmbeddableJaxbSource container, + EmbeddableSourceImpl embeddableSource) { + final List attributeSources = new ArrayList(); + + for ( JaxbPropertyElement element : container.getPropertyElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbManyToOneElement element : container.getManyToOneElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbOneToOneElement element: container.getOneToOneElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbComponentElement element: container.getComponentElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbNestedCompositeElementElement element: container.getNestedCompositeElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbDynamicComponentElement element: container.getDynamicComponentElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource(element) ); + } + + for ( JaxbAnyElement element: container.getAnyElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbMapElement element: container.getMapElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbSetElement element: container.getSetElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + for ( JaxbListElement element: container.getListElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbBagElement element: container.getBagElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbArrayElement element: container.getArrayElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbPrimitiveArrayElement element: container.getPrimitiveArrayElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbKeyPropertyElement element : container.getKeyPropertyElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + for ( JaxbKeyManyToOneElement element : container.getKeyManyToOneElementList() ) { + attributeSources.add( embeddableSource.buildAttributeSource( element ) ); + } + + return attributeSources; + } + + private AttributeSource buildAttributeSource(JaxbKeyPropertyElement element) { + return new IdentifierKeyAttributeSourceImpl( sourceMappingDocument(), this, element ); + } + + private AttributeSource buildAttributeSource(JaxbKeyManyToOneElement element) { + return new IdentifierKeyManyToOneSourceImpl( sourceMappingDocument(), this, element ); + } + + protected SingularAttributeSource buildAttributeSource(JaxbPropertyElement attributeElement) { + return new PropertyAttributeSourceImpl( + sourceMappingDocument(), + this, + attributeElement, + logicalTableName, + naturalIdMutability + ); + } + + protected AttributeSource buildAttributeSource(JaxbComponentElement attributeElement) { + return new EmbeddedAttributeSourceImpl( + sourceMappingDocument(), + this, + attributeElement, + naturalIdMutability, + logicalTableName + ); + } + + private AttributeSource buildAttributeSource(JaxbNestedCompositeElementElement element) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbDynamicComponentElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbManyToOneElement attributeElement) { + return new ManyToOneAttributeSourceImpl( + sourceMappingDocument(), + this, + attributeElement, + logicalTableName, + naturalIdMutability + ); + } + + protected AttributeSource buildAttributeSource(JaxbOneToOneElement attributeElement) { + return new OneToOneAttributeSourceImpl( + sourceMappingDocument(), + this, + attributeElement, + logicalTableName, + naturalIdMutability + ); + } + + protected AttributeSource buildAttributeSource(JaxbAnyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbOneToManyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbManyToManyElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } + + protected AttributeSource buildAttributeSource(JaxbMapElement attributeElement) { + return new MapSourceImpl( + sourceMappingDocument(), + attributeElement, + this + ); + } + protected AttributeSource buildAttributeSource(JaxbSetElement attributeElement) { + return new SetSourceImpl( + sourceMappingDocument(), + attributeElement, + this + ); + } + protected AttributeSource buildAttributeSource(JaxbListElement attributeElement) { + return new ListSourceImpl( + sourceMappingDocument(), + attributeElement, + this + ); + } + protected AttributeSource buildAttributeSource(JaxbBagElement attributeElement) { + return new BagSourceImpl( + sourceMappingDocument(), + attributeElement, + this + ); + } + protected AttributeSource buildAttributeSource(JaxbArrayElement attributeElement) { + return new ArraySourceImpl( + sourceMappingDocument(), + attributeElement, + this + ); + } + protected AttributeSource buildAttributeSource(JaxbPrimitiveArrayElement attributeElement) { + // todo : implement + throw new NotYetImplementedException(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddedAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddedAttributeSourceImpl.java new file mode 100644 index 000000000000..eeb7b2b436b2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EmbeddedAttributeSourceImpl.java @@ -0,0 +1,211 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.EntityMode; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbAnyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDynamicComponentElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPrimitiveArrayElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertiesElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSetElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTuplizerElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * The source information for a singular attribute whose type is composite + * (embedded in JPA terms). + * + * @author Steve Ebersole + */ +class EmbeddedAttributeSourceImpl extends AbstractEmbeddedAttributeSourceImpl { + public EmbeddedAttributeSourceImpl( + MappingDocument sourceMappingDocument, + AttributeSourceContainer parentContainer, + JaxbComponentElement jaxbComponentElement, + NaturalIdMutability naturalIdMutability, + String logicalTableName) { + super( + sourceMappingDocument, + parentContainer, + parentContainer.getAttributeRoleBase().append( jaxbComponentElement.getName() ), + parentContainer.getAttributePathBase().append( jaxbComponentElement.getName() ), + jaxbComponentElement, + new EmbeddableJaxbSourceImpl( jaxbComponentElement ), + naturalIdMutability, + logicalTableName + ); + } + + @Override + protected JaxbComponentElement jaxbComponentSourceElement() { + return (JaxbComponentElement) super.jaxbComponentSourceElement(); + } + + @Override + public boolean isLazy() { + return jaxbComponentSourceElement().isLazy(); + } + + @Override + public AttributePath getAttributePath() { + return getEmbeddableSource().getAttributePathBase(); + } + + @Override + public AttributeRole getAttributeRole() { + return getEmbeddableSource().getAttributeRoleBase(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return jaxbComponentSourceElement().isOptimisticLock(); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return jaxbComponentSourceElement().isInsert(); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return jaxbComponentSourceElement().isUpdate(); + } + + public static class EmbeddableJaxbSourceImpl extends AbstractEmbeddableJaxbSource { + private final JaxbComponentElement jaxbComponentElement; + + public EmbeddableJaxbSourceImpl(JaxbComponentElement jaxbComponentElement) { + this.jaxbComponentElement = jaxbComponentElement; + } + + @Override + public String getClazz() { + return jaxbComponentElement.getClazz(); + } + + @Override + public String findParent() { + return jaxbComponentElement.getParent() == null + ? null + : jaxbComponentElement.getParent().getName(); + } + + @Override + public String findTuplizer() { + if ( jaxbComponentElement.getTuplizer() == null ) { + return null; + } + + final EntityMode entityMode = StringHelper.isEmpty( jaxbComponentElement.getClazz() ) + ? EntityMode.MAP + : EntityMode.POJO; + + for ( JaxbTuplizerElement tuplizerElement : jaxbComponentElement.getTuplizer() ) { + if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode().value() ) ) { + return tuplizerElement.getClazz(); + } + } + return null; + } + + @Override + public List getPropertyElementList() { + return jaxbComponentElement.getProperty(); + } + + @Override + public List getManyToOneElementList() { + return jaxbComponentElement.getManyToOne(); + } + + @Override + public List getOneToOneElementList() { + return jaxbComponentElement.getOneToOne(); + } + + @Override + public List getComponentElementList() { + return jaxbComponentElement.getComponent(); + } + + @Override + public List getDynamicComponentElementList() { + return jaxbComponentElement.getDynamicComponent(); + } + + @Override + public List getPropertiesElementList() { + return jaxbComponentElement.getProperties(); + } + + @Override + public List getAnyElementList() { + return jaxbComponentElement.getAny(); + } + + @Override + public List getMapElementList() { + return jaxbComponentElement.getMap(); + } + + @Override + public List getSetElementList() { + return jaxbComponentElement.getSet(); + } + + @Override + public List getListElementList() { + return jaxbComponentElement.getList(); + } + + @Override + public List getBagElementList() { + return jaxbComponentElement.getBag(); + } + + @Override + public List getArrayElementList() { + return jaxbComponentElement.getArray(); + } + + @Override + public List getPrimitiveArrayElementList() { + return jaxbComponentElement.getPrimitiveArray(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EntityHierarchySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EntityHierarchySourceImpl.java new file mode 100644 index 000000000000..2a60d62bd37d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/EntityHierarchySourceImpl.java @@ -0,0 +1,696 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.hibernate.EntityMode; +import org.hibernate.TruthValue; +import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCompositeIdElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDiscriminatorElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMultiTenancyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPolymorphismAttribute; +import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.DiscriminatorSource; +import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.MultiTenancySource; +import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SimpleIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.source.spi.VersionAttributeSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +import org.jboss.logging.Logger; + +/** + * @author Steve Ebersole + */ +public class EntityHierarchySourceImpl implements EntityHierarchySource { + private static final Logger log = Logger.getLogger( EntityHierarchySourceImpl.class ); + + private final RootEntitySourceImpl rootEntitySource; + private InheritanceType hierarchyInheritanceType = InheritanceType.NO_INHERITANCE; + private final Caching caching; + private final Caching naturalIdCaching; + + public EntityHierarchySourceImpl(RootEntitySourceImpl rootEntitySource) { + this.rootEntitySource = rootEntitySource; + this.rootEntitySource.injectHierarchy( this ); + + this.caching = Helper.createCaching( entityElement().getCache() ); + this.naturalIdCaching = Helper.createNaturalIdCaching( + rootEntitySource.entityElement().getNaturalIdCache() + ); + } + + @Override + public InheritanceType getHierarchyInheritanceType() { + return hierarchyInheritanceType; + } + + @Override + public EntitySource getRoot() { + return rootEntitySource; + } + + public void processSubclass(SubclassEntitySourceImpl subclassEntitySource) { + final InheritanceType inheritanceType = Helper.interpretInheritanceType( subclassEntitySource.entityElement() ); + if ( hierarchyInheritanceType == InheritanceType.NO_INHERITANCE ) { + hierarchyInheritanceType = inheritanceType; + } + else if ( hierarchyInheritanceType != inheritanceType ) { + throw new MappingException( "Mixed inheritance strategies not supported", subclassEntitySource.getOrigin() ); + } + } + + + protected JaxbClassElement entityElement() { + return rootEntitySource.entityElement(); + } + + @Override + public IdentifierSource getIdentifierSource() { + if ( entityElement().getId() == null && entityElement().getCompositeId() == null ) { + throw rootEntitySource.getLocalBindingContext().makeMappingException( + String.format( "Entity [%s] did not define an identifier", rootEntitySource.getEntityName() ) + ); + } + + if ( entityElement().getId() != null ) { + return new SimpleIdentifierSourceImpl(); + } + else { + // if we get here, we should have a composite identifier. Just need to determine if it is aggregated, or not... + if ( StringHelper.isEmpty( entityElement().getCompositeId().getName() ) ) { + if ( entityElement().getCompositeId().isMapped() && + StringHelper.isEmpty( entityElement().getCompositeId().getClazz() ) ) { + throw makeMappingException( "mapped composite identifier must name component class to use." ); + } + return new NonAggregatedCompositeIdentifierSourceImpl(); + } + else { + if ( entityElement().getCompositeId().isMapped() ) { + throw makeMappingException("cannot combine mapped=\"true\" with specified name"); + } + return new AggregatedCompositeIdentifierSourceImpl(); + } + } + } + + protected MappingException makeMappingException(String message) { + return rootEntitySource.bindingContext().makeMappingException( message ); + } + + protected MappingException makeMappingException(String message, Exception cause) { + return rootEntitySource.bindingContext().makeMappingException( message, cause ); + } + + @Override + public VersionAttributeSource getVersionAttributeSource() { + if ( entityElement().getVersion() != null ) { + return new VersionAttributeSourceImpl( + rootEntitySource.sourceMappingDocument(), + rootEntitySource, + entityElement().getVersion() + ); + } + else if ( entityElement().getTimestamp() != null ) { + return new TimestampAttributeSourceImpl( + rootEntitySource.sourceMappingDocument(), + rootEntitySource, + entityElement().getTimestamp() + ); + } + return null; + } + + @Override + public EntityMode getEntityMode() { + return rootEntitySource.determineEntityMode(); + } + + @Override + public boolean isMutable() { + return entityElement().isMutable(); + } + + @Override + public boolean isExplicitPolymorphism() { + return JaxbPolymorphismAttribute.EXPLICIT == entityElement().getPolymorphism(); + } + + @Override + public String getWhere() { + return entityElement().getWhere(); + } + + @Override + public String getRowId() { + return entityElement().getRowid(); + } + + @Override + public OptimisticLockStyle getOptimisticLockStyle() { + final String optimisticLockModeString = Helper.getValue( entityElement().getOptimisticLock().value(), "version" ); + try { + return OptimisticLockStyle.valueOf( optimisticLockModeString.toUpperCase() ); + } + catch ( Exception e ) { + throw new MappingException( + "Unknown optimistic-lock value : " + optimisticLockModeString, + rootEntitySource.sourceMappingDocument().getOrigin() + ); + } + } + + @Override + public Caching getCaching() { + return caching; + } + + @Override + public Caching getNaturalIdCaching() { + return naturalIdCaching; + } + + @Override + public DiscriminatorSource getDiscriminatorSource() { + final JaxbDiscriminatorElement discriminatorElement = entityElement().getDiscriminator(); + if ( discriminatorElement == null ) { + return null; + } + + return new DiscriminatorSource() { + @Override + public RelationalValueSource getDiscriminatorRelationalValueSource() { + SizeSource sizeSource = Helper.createSizeSourceIfMapped( discriminatorElement.getLength(), null, null ); + if ( StringHelper.isNotEmpty( discriminatorElement.getColumnAttribute() ) || sizeSource != null ) { + return new ColumnAttributeSourceImpl( + rootEntitySource.sourceMappingDocument(), + null, // root table + discriminatorElement.getColumnAttribute(), + sizeSource, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isNotNull() ? TruthValue.FALSE : TruthValue.TRUE + ); + } + else if ( StringHelper.isNotEmpty( discriminatorElement.getFormulaAttribute() ) ) { + return new FormulaImpl( + rootEntitySource.sourceMappingDocument(), + null, + discriminatorElement.getFormulaAttribute() + ); + } + else if ( discriminatorElement.getColumn() != null ) { + return new ColumnSourceImpl( + rootEntitySource.sourceMappingDocument(), + null, // root table + discriminatorElement.getColumn(), + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE + ); + } + else if ( StringHelper.isNotEmpty( discriminatorElement.getFormula() ) ) { + return new FormulaImpl( + rootEntitySource.sourceMappingDocument(), + null, + discriminatorElement.getFormula() + ); + } + else { + log.debug( "No source for discriminator column/formula found" ); + return new ColumnAttributeSourceImpl( + rootEntitySource.sourceMappingDocument(), + null, // root table + "class", // the default discriminator column name per-legacy hbm binding + sizeSource, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isInsert() ? TruthValue.TRUE : TruthValue.FALSE, + discriminatorElement.isNotNull() ? TruthValue.FALSE : TruthValue.TRUE + ); +// throw makeMappingException( "could not determine source of discriminator mapping" ); + } + } + + @Override + public String getExplicitHibernateTypeName() { + return discriminatorElement.getType(); + } + + @Override + public boolean isForced() { + return discriminatorElement.isForce(); + } + + @Override + public boolean isInserted() { + return discriminatorElement.isInsert(); + } + }; + } + + @Override + public MultiTenancySource getMultiTenancySource() { + final JaxbMultiTenancyElement jaxbMultiTenancy = entityElement().getMultiTenancy(); + if ( jaxbMultiTenancy == null ) { + return null; + } + + return new MultiTenancySource() { + @Override + public RelationalValueSource getRelationalValueSource() { + + if ( StringHelper.isNotEmpty( jaxbMultiTenancy.getColumnAttribute() ) ) { + return new ColumnAttributeSourceImpl( + rootEntitySource.sourceMappingDocument(), + null, // root table + jaxbMultiTenancy.getColumnAttribute(), + null, + TruthValue.TRUE, + TruthValue.FALSE + ); + } + else if ( StringHelper.isNotEmpty( jaxbMultiTenancy.getFormulaAttribute() ) ) { + return new FormulaImpl( + rootEntitySource.sourceMappingDocument(), + null, + jaxbMultiTenancy.getFormulaAttribute() + ); + } + else if ( jaxbMultiTenancy.getColumn() != null ) { + return new ColumnSourceImpl( + rootEntitySource.sourceMappingDocument(), + null, // root table + jaxbMultiTenancy.getColumn(), + TruthValue.TRUE, + TruthValue.FALSE + ); + } + else if ( StringHelper.isNotEmpty( jaxbMultiTenancy.getFormula() ) ) { + return new FormulaImpl( + rootEntitySource.sourceMappingDocument(), + null, + jaxbMultiTenancy.getFormula() + ); + } + else { + return null; + } + } + + @Override + public boolean isShared() { + return jaxbMultiTenancy.isShared(); + } + + @Override + public boolean bindAsParameter() { + return jaxbMultiTenancy.isBindAsParam(); + } + }; + } + + private class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { + @Override + public SingularAttributeSource getIdentifierAttributeSource() { + return new SingularIdentifierAttributeSourceImpl( sourceMappingDocument(), rootEntitySource, entityElement().getId() ); + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( entityElement().getId().getGenerator() != null ) { + final String generatorName = entityElement().getId().getGenerator().getClazz(); + IdentifierGeneratorDefinition identifierGeneratorDefinition = sourceMappingDocument().getMappingLocalBindingContext() + .getMetadataCollector() + .getIdGenerator( generatorName ); + if ( identifierGeneratorDefinition == null ) { + identifierGeneratorDefinition = new IdentifierGeneratorDefinition( + getEntityName() + generatorName, + generatorName, + Helper.extractParameters( entityElement().getId().getGenerator().getParam() ) + ); + } + return identifierGeneratorDefinition; + } + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.SIMPLE; + } + + @Override + public String getUnsavedValue() { + return entityElement().getId().getUnsavedValue(); + } + + @Override + public Collection getToolingHintSources() { + return entityElement().getId().getMeta(); + } + + @Override + public Class getLookupIdClass() { + return determineJpaIdClass(); + } + + @Override + public String getIdClassPropertyAccessorName() { + return null; + } + } + + private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource { + private final CompositeIdentifierEmbeddedAttributeSourceImpl componentAttributeSource + = new CompositeIdentifierEmbeddedAttributeSourceImpl(); + + @Override + public EmbeddedAttributeSource getIdentifierAttributeSource() { + return componentAttributeSource; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( entityElement().getCompositeId().getGenerator() != null ) { + final String generatorName = entityElement().getCompositeId().getGenerator().getClazz(); + IdentifierGeneratorDefinition identifierGeneratorDefinition = sourceMappingDocument().getMappingLocalBindingContext() + .getMetadataCollector() + .getIdGenerator( generatorName ); + if ( identifierGeneratorDefinition == null ) { + identifierGeneratorDefinition = new IdentifierGeneratorDefinition( + getEntityName() + generatorName, + generatorName, + Helper.extractParameters( entityElement().getCompositeId().getGenerator().getParam() ) + ); + } + return identifierGeneratorDefinition; + } + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return entityElement().getCompositeId().getUnsavedValue().value(); + } + + @Override + public Class getLookupIdClass() { + return determineJpaIdClass(); + } + + @Override + public String getIdClassPropertyAccessorName() { + return null; + } + + @Override + public Collection getToolingHintSources() { + return entityElement().getId().getMeta(); + } + } + + private class CompositeIdentifierEmbeddedAttributeSourceImpl extends AbstractEmbeddedAttributeSourceImpl { + private final List keyPropertyElementList; + private final List keyManyToOneElementList; + + protected CompositeIdentifierEmbeddedAttributeSourceImpl() { + super( + EntityHierarchySourceImpl.this.sourceMappingDocument(), + rootEntitySource, + rootEntitySource.getAttributeRoleBase().append( "id" ), + rootEntitySource.getAttributePathBase().append( "id" ), + entityElement().getCompositeId(), + new EmbeddableJaxbSourceImpl( entityElement().getCompositeId() ), + NaturalIdMutability.NOT_NATURAL_ID, + null + ); + + this.keyPropertyElementList = new ArrayList(); + this.keyManyToOneElementList = new ArrayList(); + + final JaxbCompositeIdElement compositeIdElement = entityElement().getCompositeId(); + for ( final Object obj : compositeIdElement.getKeyPropertyOrKeyManyToOne() ) { + if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) { + keyPropertyElementList.add( JaxbKeyPropertyElement.class.cast( obj ) ); + } + else if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) { + keyManyToOneElementList.add( JaxbKeyManyToOneElement.class.cast( obj ) ); + } + } + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public AttributePath getAttributePath() { + return getEmbeddableSource().getAttributePathBase(); + } + + @Override + public AttributeRole getAttributeRole() { + return getEmbeddableSource().getAttributeRoleBase(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return false; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + } + + + private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource { + @Override + public Class getLookupIdClass() { + return determineJpaIdClass(); + } + + @Override + public String getIdClassPropertyAccessorName() { + return null; + } + + @Override + public List getAttributeSourcesMakingUpIdentifier() { + final List attributeSources = new ArrayList(); + final JaxbCompositeIdElement compositeId = entityElement().getCompositeId(); + final List list = compositeId.getKeyPropertyOrKeyManyToOne(); + for ( final Object obj : list ) { + if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) { + JaxbKeyPropertyElement key = JaxbKeyPropertyElement.class.cast( obj ); + attributeSources.add( + new IdentifierKeyAttributeSourceImpl( + sourceMappingDocument(), + rootEntitySource, + key + ) + ); + } + if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) { + JaxbKeyManyToOneElement key = JaxbKeyManyToOneElement.class.cast( obj ); + attributeSources.add( + new IdentifierKeyManyToOneSourceImpl( + sourceMappingDocument(), + rootEntitySource, + key + ) + ); + } + } + + return attributeSources; + } + + @Override + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) { + // for now, return null. this is that stupid specj bs + return null; + } + + @Override + public IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor() { + if ( entityElement().getCompositeId().getGenerator() != null ) { + final String generatorName = entityElement().getCompositeId().getGenerator().getClazz(); + IdentifierGeneratorDefinition identifierGeneratorDefinition = sourceMappingDocument().getMappingLocalBindingContext() + .getMetadataCollector() + .getIdGenerator( generatorName ); + if ( identifierGeneratorDefinition == null ) { + identifierGeneratorDefinition = new IdentifierGeneratorDefinition( + getEntityName() + generatorName, + generatorName, + Helper.extractParameters( entityElement().getCompositeId().getGenerator().getParam() ) + ); + } + return identifierGeneratorDefinition; + } + return null; + } + + @Override + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; + } + + @Override + public String getUnsavedValue() { + return entityElement().getCompositeId().getUnsavedValue().value(); + } + + @Override + public Collection getToolingHintSources() { + return entityElement().getCompositeId().getMeta(); + } + } + + public static class EmbeddableJaxbSourceImpl extends AbstractEmbeddableJaxbSource { + private final JaxbCompositeIdElement compositeIdElement; + + private final List keyPropertyElementList; + private final List keyManyToOneElementList; + + public EmbeddableJaxbSourceImpl(JaxbCompositeIdElement compositeIdElement) { + this.compositeIdElement = compositeIdElement; + + this.keyPropertyElementList = new ArrayList(); + this.keyManyToOneElementList = new ArrayList(); + + for ( final Object obj : compositeIdElement.getKeyPropertyOrKeyManyToOne() ) { + if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) { + keyPropertyElementList.add( JaxbKeyPropertyElement.class.cast( obj ) ); + } + else if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) { + keyManyToOneElementList.add( JaxbKeyManyToOneElement.class.cast( obj ) ); + } + } + } + + @Override + public String getClazz() { + return compositeIdElement.getClazz(); + } + + @Override + public String findParent() { + return null; + } + + @Override + public String findTuplizer() { + return null; + } + + @Override + public List getKeyPropertyElementList() { + return keyPropertyElementList; + } + + @Override + public List getKeyManyToOneElementList() { + return keyManyToOneElementList; + } + + } + + private Class determineJpaIdClass() { + // this would be a defined with mapped="false" + final JaxbCompositeIdElement compositeId = entityElement().getCompositeId(); + if ( compositeId == null ) { + return null; + } + + if ( !"".equals( compositeId.getName() ) ) { + return null; + } + + if ( compositeId.isMapped() ) { + return null; + } + + if ( compositeId.getClazz() == null ) { + return null; + } + + // todo : do we really want to be loading this? + return rootEntitySource.bindingContext().getClassLoaderAccess().classForName( rootEntitySource.bindingContext().qualifyClassName( compositeId.getClazz() ) + ); + } + + private String getEntityName() { + return rootEntitySource.getEntityName(); + } + + private MappingDocument sourceMappingDocument() { + return rootEntitySource.sourceMappingDocument(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FetchProfileSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FetchProfileSourceImpl.java new file mode 100644 index 000000000000..a242943c1ba7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FetchProfileSourceImpl.java @@ -0,0 +1,94 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFetchProfileElement; +import org.hibernate.metamodel.source.spi.FetchProfileSource; + +/** + * @author Steve Ebersole + */ +public class FetchProfileSourceImpl + extends AbstractHbmSourceNode + implements FetchProfileSource { + + private final String name; + private final List associationOverrideSources; + + public FetchProfileSourceImpl( + MappingDocument mappingDocument, + JaxbFetchProfileElement fetchProfileElement) { + super( mappingDocument ); + this.name = fetchProfileElement.getName(); + this.associationOverrideSources = buildAssociationOverrideSources( fetchProfileElement ); + } + + @Override + public String getName() { + return name; + } + + @Override + public Iterable getAssociationOverrides() { + return associationOverrideSources; + } + + private static List buildAssociationOverrideSources(JaxbFetchProfileElement fetchProfileElement) { + final List associationOverrideSources = new ArrayList(); + for ( JaxbFetchProfileElement.JaxbFetch fetch : fetchProfileElement.getFetch() ) { + associationOverrideSources.add( new AssociationOverrideSourceImpl( fetch ) ); + } + return associationOverrideSources; + } + + private static class AssociationOverrideSourceImpl implements AssociationOverrideSource { + private final String entityName; + private final String attributeName; + private final String fetchMode; + + private AssociationOverrideSourceImpl(JaxbFetchProfileElement.JaxbFetch fetchElement) { + this.entityName = fetchElement.getEntity(); + this.attributeName = fetchElement.getAssociation(); + this.fetchMode = fetchElement.getStyle().value(); + } + + @Override + public String getEntityName() { + return entityName; + } + + @Override + public String getAttributeName() { + return attributeName; + } + + @Override + public String getFetchModeName() { + return fetchMode; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FilterDefinitionSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FilterDefinitionSourceImpl.java new file mode 100644 index 000000000000..6ebdb68f7e01 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FilterDefinitionSourceImpl.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterDefElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterParamElement; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.FilterParameterSource; + +/** + * @author Steve Ebersole + */ +public class FilterDefinitionSourceImpl + extends AbstractHbmSourceNode + implements FilterDefinitionSource { + private final String name; + private final String condition; + private List parameterSources; + + public FilterDefinitionSourceImpl( + MappingDocument mappingDocument, + JaxbFilterDefElement filterDefElement) { + super( mappingDocument ); + this.name = filterDefElement.getName(); + + String conditionAttribute = filterDefElement.getCondition(); + String conditionContent = null; + + final List parameterSources = new ArrayList(); + for ( Object content : filterDefElement.getContent() ) { + if ( String.class.isInstance( content ) ){ + final String str = content.toString(); + if ( !StringHelper.isEmptyOrWhiteSpace( str ) ) { + conditionContent = str.trim(); + } + } + else if ( JAXBElement.class.isInstance( content ) ) { + JAXBElement jaxbElement = JAXBElement.class.cast( content ); + if ( jaxbElement.getDeclaredType() == JaxbFilterParamElement.class ) { + parameterSources.add( + (JaxbFilterParamElement) jaxbElement.getValue() + ); + } + } + else { + parameterSources.add( + ( JaxbFilterParamElement)content + ); + } + } + + this.condition = Helper.coalesce( conditionContent, conditionAttribute ); + this.parameterSources = parameterSources; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public Iterable getParameterSources() { + return parameterSources; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FilterSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FilterSourceImpl.java new file mode 100644 index 000000000000..8f843bc6cfe5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FilterSourceImpl.java @@ -0,0 +1,110 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterAliasMappingType; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterElement; +import org.hibernate.metamodel.source.spi.FilterSource; + +/** + * @author Steve Ebersole + */ +public class FilterSourceImpl + extends AbstractHbmSourceNode + implements FilterSource { + private final String name; + private final String condition; + private final boolean autoAliasInjection; + private final Map aliasTableMap = new HashMap(); + private final Map aliasEntityMap = new HashMap(); + + public FilterSourceImpl( + MappingDocument mappingDocument, + JaxbFilterElement filterElement) { + super( mappingDocument ); + this.name = filterElement.getName(); + + String explicitAutoAliasInjectionSetting = filterElement.getAutoAliasInjection(); + + String conditionAttribute = filterElement.getCondition(); + String conditionContent = null; + + for ( Serializable content : filterElement.getContent() ) { + if ( String.class.isInstance( content ) ) { + final String str = content.toString(); + if ( !StringHelper.isEmptyOrWhiteSpace( str ) ) { + conditionContent = str.trim(); + } + } + else { + final JaxbFilterAliasMappingType aliasMapping = JaxbFilterAliasMappingType.class.cast( content ); + if ( StringHelper.isNotEmpty( aliasMapping.getTable() ) ) { + aliasTableMap.put( aliasMapping.getAlias(), aliasMapping.getTable() ); + } + else if ( StringHelper.isNotEmpty( aliasMapping.getEntity() ) ) { + aliasEntityMap.put( aliasMapping.getAlias(), aliasMapping.getTable() ); + } + else { + throw mappingDocument.getMappingLocalBindingContext() + .makeMappingException( "filter alias must define either table or entity attribute" ); + } + } + } + + this.condition = Helper.coalesce( conditionContent, conditionAttribute ); + this.autoAliasInjection = StringHelper.isNotEmpty( explicitAutoAliasInjectionSetting ) + ? Boolean.valueOf( explicitAutoAliasInjectionSetting ) + : true; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCondition() { + return condition; + } + + @Override + public boolean shouldAutoInjectAliases() { + return autoAliasInjection; + } + + @Override + public Map getAliasToTableMap() { + return aliasTableMap; + } + + @Override + public Map getAliasToEntityMap() { + return aliasEntityMap; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/FormulaImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FormulaImpl.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/FormulaImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FormulaImpl.java index f452491c0eb9..403d9542edf4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/FormulaImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/FormulaImpl.java @@ -21,22 +21,30 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.source.internal.hbm; -import org.hibernate.metamodel.source.binder.DerivedValueSource; +import org.hibernate.metamodel.source.spi.DerivedValueSource; /** * @author Steve Ebersole */ -class FormulaImpl implements DerivedValueSource { +class FormulaImpl + extends AbstractHbmSourceNode + implements DerivedValueSource { private String tableName; private final String expression; - FormulaImpl(String tableName, String expression) { + FormulaImpl(MappingDocument mappingDocument, String tableName, String expression) { + super( mappingDocument ); this.tableName = tableName; this.expression = expression; } + @Override + public Nature getNature() { + return Nature.DERIVED; + } + @Override public String getExpression() { return expression; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HbmBindingContext.java similarity index 79% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmBindingContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HbmBindingContext.java index 4b756a69b76f..08ebaad097ce 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmBindingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HbmBindingContext.java @@ -21,18 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.hbm; +package org.hibernate.metamodel.source.internal.hbm; import java.util.List; -import org.hibernate.internal.jaxb.mapping.hbm.EntityElement; -import org.hibernate.internal.jaxb.mapping.hbm.JaxbFetchProfileElement; -import org.hibernate.metamodel.source.BindingContext; -import org.hibernate.metamodel.source.LocalBindingContext; -import org.hibernate.metamodel.source.MetaAttributeContext; +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFetchProfileElement; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.LocalBindingContext; /** - * Defines features specific to the {@code hbm.xml} variety of a {@link BindingContext} + * Defines features specific to the {@code hbm.xml} variety of a {@link org.hibernate.metamodel.spi.BindingContext} * * @author Steve Ebersole */ @@ -44,4 +43,5 @@ public interface HbmBindingContext extends LocalBindingContext { public String determineEntityName(EntityElement entityElement); public void processFetchProfiles(List fetchProfiles, String containingEntityName); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HbmMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HbmMetadataSourceProcessorImpl.java new file mode 100644 index 000000000000..38a70e42b0e2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HbmMetadataSourceProcessorImpl.java @@ -0,0 +1,117 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.xml.spi.BindResult; + +import static java.util.Collections.emptyList; + +/** + * The {@link org.hibernate.metamodel.spi.MetadataSourceProcessor} implementation responsible for processing {@code hbm.xml} sources. + * + * @author Steve Ebersole + */ +public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor { + private final List processors = new ArrayList(); + private final List entityHierarchies; + + public HbmMetadataSourceProcessorImpl(BindingContext bindingContext, MetadataSources metadataSources) { + this( bindingContext, metadataSources.getBindResultList() ); + } + + @SuppressWarnings("unchecked") + public HbmMetadataSourceProcessorImpl(BindingContext bindingContext, List bindResults) { + final HierarchyBuilder hierarchyBuilder = new HierarchyBuilder( bindingContext ); + + for ( BindResult bindResult : bindResults ) { + if ( ! JaxbHibernateMapping.class.isInstance( bindResult.getRoot() ) ) { + continue; + } + + final MappingDocument mappingDocument = new MappingDocument( bindResult, bindingContext ); + processors.add( new HibernateMappingProcessor( mappingDocument ) ); + + hierarchyBuilder.processMappingDocument( mappingDocument ); + } + + this.entityHierarchies = hierarchyBuilder.groupEntityHierarchies(); + } + + // todo : still need to deal with auxiliary database objects + + @Override + public Iterable extractTypeDefinitionSources() { + if( CollectionHelper.isEmpty( processors )){ + return emptyList(); + } + final List typeDescriptorSources = new ArrayList(); + for ( HibernateMappingProcessor processor : processors ) { + processor.collectTypeDescriptorSources( typeDescriptorSources ); + } + return typeDescriptorSources; + } + + @Override + public Iterable extractFilterDefinitionSources() { + if( CollectionHelper.isEmpty( processors )){ + return emptyList(); + } + final List filterDefinitionSources = new ArrayList(); + for ( HibernateMappingProcessor processor : processors ) { + processor.collectFilterDefSources( filterDefinitionSources ); + } + return filterDefinitionSources; + } + + @Override + public Iterable extractGlobalIdentifierGeneratorSources() { + return emptyList(); + } + + @Override + @SuppressWarnings( {"unchecked", "RedundantCast"}) + public Collection extractEntityHierarchies() { + return entityHierarchies; + } + + @Override + public void processMappingDependentMetadata() { + for ( HibernateMappingProcessor processor : processors ) { + processor.processMappingDependentMetadata(); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/Helper.java new file mode 100644 index 000000000000..9b8e3570c9b7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/Helper.java @@ -0,0 +1,495 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.LockMode; +import org.hibernate.TruthValue; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCacheElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinedSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbLockModeAttribute; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbNaturalIdCacheElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbParamElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSqlDmlElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbUnionSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.TableInformationSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.MetaAttribute; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class Helper { + public static final HibernateTypeSource TO_ONE_ATTRIBUTE_TYPE_SOURCE = new HibernateTypeSource() { + @Override + public String getName() { + return null; + } + + @Override + public Map getParameters() { + return null; + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + + public static LockMode interpretLockMode(JaxbLockModeAttribute lockModeAttribute, LocalBindingContext context){ + if ( lockModeAttribute == null ) { + return LockMode.READ; + } + switch ( lockModeAttribute ) { + case NONE: + return LockMode.NONE; + case UPGRADE: + return LockMode.UPGRADE; + case UPGRADE_NOWAIT: + return LockMode.UPGRADE_NOWAIT; + case READ: + return LockMode.READ; + case WRITE: + return LockMode.WRITE; + case FORCE: + return LockMode.FORCE; + case OPTIMISTIC: + return LockMode.OPTIMISTIC; + case OPTIMISTIC_FORCE_INCREMENT: + return LockMode.OPTIMISTIC_FORCE_INCREMENT; + case PESSIMISTIC_READ: + return LockMode.PESSIMISTIC_READ; + case PESSIMISTIC_WRITE: + return LockMode.PESSIMISTIC_WRITE; + case PESSIMISTIC_FORCE_INCREMENT: + return LockMode.PESSIMISTIC_FORCE_INCREMENT; + default: + throw context.makeMappingException( "unknown lock mode: "+lockModeAttribute ); + } + } + + public static InheritanceType interpretInheritanceType(EntityElement entityElement) { + if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { + return InheritanceType.SINGLE_TABLE; + } + else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { + return InheritanceType.JOINED; + } + else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { + return InheritanceType.TABLE_PER_CLASS; + } + else { + return InheritanceType.NO_INHERITANCE; + } + } + + /** + * Given a user-specified description of how to perform custom SQL, build the {@link CustomSQL} representation. + * + * @param customSqlElement User-specified description of how to perform custom SQL + * + * @return The {@link CustomSQL} representation + */ + public static CustomSQL buildCustomSql(JaxbSqlDmlElement customSqlElement) { + if ( customSqlElement == null ) { + return null; + } + final ExecuteUpdateResultCheckStyle checkStyle = customSqlElement.getCheck() == null + ? customSqlElement.isCallable() + ? ExecuteUpdateResultCheckStyle.NONE + : ExecuteUpdateResultCheckStyle.COUNT + : ExecuteUpdateResultCheckStyle.fromExternalName( customSqlElement.getCheck().value() ); + return new CustomSQL( customSqlElement.getValue(), customSqlElement.isCallable(), checkStyle ); + } + + /** + * Given the user-specified entity mapping, determine the appropriate entity name + * + * @param entityElement The user-specified entity mapping + * @param unqualifiedClassPackage The package to use for unqualified class names + * + * @return The appropriate entity name + */ + public static String determineEntityName(EntityElement entityElement, String unqualifiedClassPackage) { + return entityElement.getEntityName() != null + ? entityElement.getEntityName() + : qualifyIfNeeded( entityElement.getName(), unqualifiedClassPackage ); + } + + public static Caching createCaching(JaxbCacheElement cacheElement) { + if ( cacheElement == null ) { + // I'd really rather this be UNKNOWN, but the annotation version resolves this to TRUE/FALSE + return new Caching( TruthValue.FALSE ); + } + + final AccessType accessType = AccessType.fromExternalName( cacheElement.getUsage().value() ); + final boolean cacheLazyProps = cacheElement.getInclude() == null + || !"non-lazy".equals( cacheElement.getInclude().value() ); + + return new Caching( + cacheElement.getRegion(), + accessType, + cacheLazyProps, + TruthValue.TRUE + ); + } + + public static Caching createNaturalIdCaching(JaxbNaturalIdCacheElement cacheElement) { + if ( cacheElement == null ) { + return new Caching( TruthValue.UNKNOWN ); + } + + return new Caching( + StringHelper.nullIfEmpty( cacheElement.getRegion() ), + null, + false, + TruthValue.TRUE + ); + } + + /** + * Qualify a (supposed class) name with the unqualified-class package name if it is not already qualified + * + * @param name The name + * @param unqualifiedClassPackage The unqualified-class package name + * + * @return {@code null} if the incoming name was {@code null}; or the qualified name. + */ + public static String qualifyIfNeeded(String name, String unqualifiedClassPackage) { + if ( name == null ) { + return null; + } + if ( name.indexOf( '.' ) < 0 && unqualifiedClassPackage != null ) { + return unqualifiedClassPackage + '.' + name; + } + return name; + } + + public static String getPropertyAccessorName(String access, boolean isEmbedded, String defaultAccess) { + return getValue( access, isEmbedded ? "embedded" : defaultAccess ); + } + + public static MetaAttributeContext extractMetaAttributeContext( + List metaAttributeSourceList, + boolean onlyInheritable, + MetaAttributeContext parentContext) { + final MetaAttributeContext subContext = new MetaAttributeContext( parentContext ); + + for ( ToolingHintSource meta : metaAttributeSourceList ) { + if ( onlyInheritable & !meta.isInheritable() ) { + continue; + } + + final String name = meta.getName(); + final MetaAttribute inheritedMetaAttribute = parentContext.getMetaAttribute( name ); + MetaAttribute metaAttribute = subContext.getLocalMetaAttribute( name ); + if ( metaAttribute == null || metaAttribute == inheritedMetaAttribute ) { + metaAttribute = new MetaAttribute( name ); + subContext.add( metaAttribute ); + } + metaAttribute.addValue( meta.getValue() ); + } + + return subContext; + } + + public static T getValue(T value, T defaultValue){ + return value == null ? defaultValue : value; + } + + public static Set interpretCascadeStyles(String cascades, LocalBindingContext bindingContext) { + final Set cascadeStyles = new HashSet(); + if ( StringHelper.isEmpty( cascades ) ) { + cascades = bindingContext.getMappingDefaults().getCascadeStyle(); + } + for ( String cascade : StringHelper.split( " ,", cascades ) ) { + cascadeStyles.add( CascadeStyles.getCascadeStyle( cascade ) ); + } + return cascadeStyles; + } + + public static Map extractParameters(List xmlParamElements) { + if ( xmlParamElements == null || xmlParamElements.isEmpty() ) { + return Collections.emptyMap(); + } + final HashMap params = new HashMap(); + for ( JaxbParamElement paramElement : xmlParamElements ) { + params.put( paramElement.getName(), paramElement.getValue() ); + } + return params; + } + + public static SizeSource createSizeSourceIfMapped(Integer length, Integer precision, Integer scale) { + if ( length != null || precision != null || scale != null ) { + return new SizeSourceImpl( precision, scale, length ); + } + return null; + } + + /** + * Operates like SQL coalesce expression, except empty strings are treated as null. Return the first non-empty value + * + * @param values The list of values. + * @param Generic type of values to coalesce + * + * @return The first non-empty value, or null if all values were empty + */ + public static T coalesce(T... values) { + if ( values == null ) { + return null; + } + for ( T value : values ) { + if ( value != null ) { + if ( String.class.isInstance( value ) ) { + if ( StringHelper.isNotEmpty( (String) value ) ) { + return value; + } + } + else { + return value; + } + } + } + return null; + } + + public static interface InLineViewNameInferrer { + public String inferInLineViewName(); + } + + public static TableSpecificationSource createTableSource( + MappingDocument mappingDocument, + TableInformationSource jaxbTableSource, + InLineViewNameInferrer inLineViewNameInferrer) { + if ( jaxbTableSource.getSubselectAttribute() == null && jaxbTableSource.getSubselect() == null ) { + return new TableSourceImpl( + mappingDocument, + jaxbTableSource.getSchema(), + jaxbTableSource.getCatalog(), + jaxbTableSource.getTable() + ); + } + else { + return new InLineViewSourceImpl( + mappingDocument, + jaxbTableSource.getSchema(), + jaxbTableSource.getCatalog(), + jaxbTableSource.getSubselectAttribute() != null + ? jaxbTableSource.getSubselectAttribute() + : jaxbTableSource.getSubselect(), + jaxbTableSource.getTable() == null + ? inLineViewNameInferrer.inferInLineViewName() + : jaxbTableSource.getTable() + ); + } + + } + + /** + * For things that define one or more "value sources" there is a lot of variance in terms of how they + * look in the XML. As an example, consider {@code } which might have:
        + *
      • a {@code column} XML attribute
      • + *
      • a {@code formula} XML attribute
      • + *
      • one or more nested {@code } XML elements
      • + *
      • a {@code } XML element
      • + *
      + * as opposed to {@code } which can only have:
        + *
      • a {@code column} XML attribute
      • + *
      + *

      + * This class adapts those variances to a unified contract which is intended to be used in conjunction with + * {@link #buildValueSources}. + */ + public static class ValueSourcesAdapter { + public String getContainingTableName() { + return null; + } + + public boolean isIncludedInInsertByDefault() { + return false; + } + + public boolean isIncludedInUpdateByDefault() { + return false; + } + + public String getColumnAttribute() { + return null; + } + + public String getFormulaAttribute() { + return null; + } + + public SizeSource getSizeSource() { + return null; + } + + public List getColumn(){ + return Collections.emptyList(); + } + + public List getFormula(){ + return Collections.emptyList(); + } + + public boolean isForceNotNull() { + return false; + } + } + + private static void checkColumnOrFormulaElements(MappingDocument mappingDocument, ValueSourcesAdapter valueSourcesAdapter) { + if ( CollectionHelper.isNotEmpty( valueSourcesAdapter.getColumn() ) || CollectionHelper.isNotEmpty( + valueSourcesAdapter.getFormula() + ) ) { + throw mappingDocument.getMappingLocalBindingContext().makeMappingException( + "column/formula/size attribute may not be used together with / subelement" + ); + } + } + + /** + * Given a {@link ValueSourcesAdapter}, build the corresponding list of {@link RelationalValueSource} + * + * @param mappingDocument the mapping document + * @param valueSourcesAdapter the adapter describing the value sources. + * + * @return The corresponding list. + */ + public static List buildValueSources( + MappingDocument mappingDocument, + ValueSourcesAdapter valueSourcesAdapter) { + List result = new ArrayList(); + + if ( StringHelper.isNotEmpty( valueSourcesAdapter.getColumnAttribute() ) ) { + // we have the XML defining a column attribute. + // it is therefore illegal for there to also be any nested formula or column elements + checkColumnOrFormulaElements(mappingDocument, valueSourcesAdapter); + // it is also illegal for there to also be a formula attribute + if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { + throw mappingDocument.getMappingLocalBindingContext().makeMappingException( + "column and formula attributes may not be used together" + ); + } + + result.add( + new ColumnAttributeSourceImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + valueSourcesAdapter.getColumnAttribute(), + valueSourcesAdapter.getSizeSource(), + valueSourcesAdapter.isIncludedInInsertByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isIncludedInUpdateByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isForceNotNull() ? TruthValue.FALSE : TruthValue.UNKNOWN + ) + ); + } + else if ( StringHelper.isNotEmpty( valueSourcesAdapter.getFormulaAttribute() ) ) { + // we have the XML defining a formula attribute (and not a column attribute) + // it is therefore illegal for there to also be any nested formula or column elements + checkColumnOrFormulaElements( mappingDocument, valueSourcesAdapter ); + // column/formula attribute combo checked already + + result.add( + new FormulaImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + valueSourcesAdapter.getFormulaAttribute() + ) + ); + } + else if ( valueSourcesAdapter.getSizeSource() != null ) { + // we have XML defining a length, precision, and/or scale attribute with neither + // a column nor formula attribute; assume this is a column. + // it is therefore illegal for there to also be any nested formula or column elements + checkColumnOrFormulaElements(mappingDocument, valueSourcesAdapter); + result.add( + new ColumnAttributeSourceImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + valueSourcesAdapter.getColumnAttribute(), + valueSourcesAdapter.getSizeSource(), + valueSourcesAdapter.isIncludedInInsertByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isIncludedInUpdateByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isForceNotNull() ? TruthValue.FALSE : TruthValue.UNKNOWN + ) + ); + + } + // we have the XML defining nested formula or column elements (and not column attribute nor formula attribute) + if ( CollectionHelper.isNotEmpty( valueSourcesAdapter.getColumn() ) ) { + for ( JaxbColumnElement column : valueSourcesAdapter.getColumn() ) { + result.add( + new ColumnSourceImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + column, + valueSourcesAdapter.isIncludedInInsertByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isIncludedInUpdateByDefault() ? TruthValue.TRUE : TruthValue.FALSE, + valueSourcesAdapter.isForceNotNull() ? TruthValue.FALSE : TruthValue.TRUE + ) + ); + } + } + if ( CollectionHelper.isNotEmpty( valueSourcesAdapter.getFormula() ) ) { + for ( String formula : valueSourcesAdapter.getFormula() ) { + result.add( + new FormulaImpl( + mappingDocument, + valueSourcesAdapter.getContainingTableName(), + formula + ) + ); + } + } + return result; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HibernateMappingProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HibernateMappingProcessor.java new file mode 100644 index 000000000000..862101f84d01 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HibernateMappingProcessor.java @@ -0,0 +1,322 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDatabaseObjectElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDialectScopeElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFetchProfileElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterDefElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIdentifierGeneratorElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbImportElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinedSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbResultsetElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSqlQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTypedefElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbUnionSubclassElement; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.BasicAuxiliaryDatabaseObjectImpl; + +/** + * Responsible for processing a {@code } element. Allows processing to be coordinated across + * all hbm files in an ordered fashion. The order is essentially the same as defined in + * {@link org.hibernate.metamodel.spi.MetadataSourceProcessor} + * + * @author Steve Ebersole + * @author Strong Liu + */ +public class HibernateMappingProcessor { + private final MappingDocument mappingDocument; + + private final ClassLoaderService classLoaderService; + + public HibernateMappingProcessor(MappingDocument mappingDocument) { + this.mappingDocument = mappingDocument; + this.classLoaderService = bindingContext().getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); + processDatabaseObjectDefinitions(); + processIdentifierGenerators(); + } + + private InFlightMetadataCollector metadataCollector() { + return bindingContext().getMetadataCollector(); + } + + private JaxbHibernateMapping mappingRoot() { + return mappingDocument.getMappingRoot(); + } + + private HbmBindingContext bindingContext() { + return mappingDocument.getMappingLocalBindingContext(); + } + + private Class classForName(String name) { + return classLoaderService.classForName( bindingContext().qualifyClassName( name ) ); + } + + private void processDatabaseObjectDefinitions() { + if ( mappingRoot().getDatabaseObject() == null ) { + return; + } + + for ( JaxbDatabaseObjectElement databaseObjectElement : mappingRoot().getDatabaseObject() ) { + final AuxiliaryDatabaseObject auxiliaryDatabaseObject; + if ( databaseObjectElement.getDefinition() != null ) { + final String className = databaseObjectElement.getDefinition().getClazz(); + try { + auxiliaryDatabaseObject = (AuxiliaryDatabaseObject) classForName( className ).newInstance(); + } + catch ( ClassLoadingException e ) { + throw e; + } + catch ( Exception e ) { + throw bindingContext().makeMappingException( "could not instantiate custom database object class [" + className + "]" ); + } + } + else { + Set dialectScopes = new HashSet(); + if ( databaseObjectElement.getDialectScope() != null ) { + for ( JaxbDialectScopeElement dialectScope : databaseObjectElement.getDialectScope() ) { + dialectScopes.add( dialectScope.getName() ); + } + } + auxiliaryDatabaseObject = new BasicAuxiliaryDatabaseObjectImpl( + metadataCollector().getDatabase().getDefaultSchema(), + databaseObjectElement.getCreate(), + databaseObjectElement.getDrop(), + dialectScopes + ); + } + metadataCollector().getDatabase().addAuxiliaryDatabaseObject( auxiliaryDatabaseObject ); + } + } + + public void collectTypeDescriptorSources(List typeDescriptorSources) { + if ( mappingRoot().getTypedef() == null ) { + return; + } + + for ( JaxbTypedefElement typeDefElement : mappingRoot().getTypedef() ) { + typeDescriptorSources.add( new TypeDescriptorSourceImpl( typeDefElement ) ); + } + } + + public void collectFilterDefSources(List filterDefinitionSources) { + if ( mappingRoot().getFilterDef() == null ) { + return; + } + + for ( JaxbFilterDefElement filterDefElement : mappingRoot().getFilterDef() ) { + filterDefinitionSources.add( new FilterDefinitionSourceImpl( mappingDocument, filterDefElement ) ); + } + } + + + private void processIdentifierGenerators() { + if ( mappingRoot().getIdentifierGenerator() == null ) { + return; + } + + for ( JaxbIdentifierGeneratorElement identifierGeneratorElement : mappingRoot().getIdentifierGenerator() ) { + metadataCollector().registerIdentifierGenerator( + identifierGeneratorElement.getName(), + identifierGeneratorElement.getClazz() + ); + } + } + + public void processMappingDependentMetadata() { + processFetchProfiles(); + processImports(); + processResultSetMappings(); + processNamedQueries(); + } + + private void processFetchProfiles() { + processFetchProfiles( mappingRoot().getFetchProfile(), null ); + for ( JaxbClassElement classElement : mappingRoot().getClazz() ) { + processFetchProfile( classElement ); + + // processing fetch profiles defined in the + processFetchProfilesInJoinedSubclass( classElement.getJoinedSubclass() ); + // + processFetchProfilesInUnionSubclass( classElement.getUnionSubclass() ); + // + processFetchProfilesInSubclass( classElement.getSubclass() ); + } + } + + private void processFetchProfilesInSubclass(List subclass) { + for ( JaxbSubclassElement subclassElement : subclass ) { + processFetchProfile( subclassElement ); + processFetchProfilesInSubclass( subclassElement.getSubclass() ); + } + } + + private void processFetchProfile(final EntityElement entityElement){ + processFetchProfiles( + entityElement.getFetchProfile(), + bindingContext().qualifyClassName( entityElement.getName() ) + ); + } + + private void processFetchProfilesInUnionSubclass(List unionSubclass) { + for ( JaxbUnionSubclassElement subclassElement : unionSubclass ) { + processFetchProfile( subclassElement ); + processFetchProfilesInUnionSubclass( subclassElement.getUnionSubclass() ); + } + } + + private void processFetchProfilesInJoinedSubclass(List joinedSubclassElements) { + for ( JaxbJoinedSubclassElement subclassElement : joinedSubclassElements ) { + processFetchProfile( subclassElement ); + processFetchProfilesInJoinedSubclass( subclassElement.getJoinedSubclass() ); + } + } + + public void processFetchProfiles(List fetchProfiles, String containingEntityName) { + for ( JaxbFetchProfileElement fetchProfile : fetchProfiles ) { + String profileName = fetchProfile.getName(); + Set fetches = new HashSet(); + for ( JaxbFetchProfileElement.JaxbFetch fetch : fetchProfile.getFetch() ) { + String entityName = fetch.getEntity() == null ? containingEntityName : fetch.getEntity(); + if ( entityName == null ) { + throw bindingContext().makeMappingException( "could not determine entity for fetch-profile fetch [" + profileName + "]:[" + + fetch.getAssociation() + "]" ); + } + fetches.add( new FetchProfile.Fetch( entityName, fetch.getAssociation(), fetch.getStyle().value() ) ); + } + metadataCollector().addFetchProfile( new FetchProfile( profileName, fetches ) ); + } + } + + private void processImports() { + JaxbHibernateMapping root = mappingRoot(); + for ( JaxbImportElement importValue : root.getImport() ) { + String className = bindingContext().qualifyClassName( importValue.getClazz() ); + String rename = importValue.getRename(); + rename = ( rename == null ) ? StringHelper.unqualify( className ) : rename; + metadataCollector().addImport( rename, className ); + } + if ( root.isAutoImport() ) { + processEntityElementsImport( root.getClazz() ); + processEntityElementsImport( root.getJoinedSubclass() ); + processEntityElementsImport( root.getUnionSubclass() ); + processEntityElementsImport( root.getSubclass() ); + } + } + + private void processEntityElementsImport(List entityElements) { + for ( final EntityElement element : entityElements ) { + processEntityElementImport( element ); + } + } + + private void processEntityElementImport(EntityElement entityElement) { + final String qualifiedName = bindingContext().determineEntityName( entityElement ); + final String importName = entityElement.getEntityName() == null + ? entityElement.getName() + : entityElement.getEntityName(); + metadataCollector().addImport( importName, qualifiedName ); + metadataCollector().addImport( StringHelper.unqualify( importName ), qualifiedName ); + + if ( JaxbClassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbClassElement) entityElement ).getSubclass() ); + processEntityElementsImport( ( (JaxbClassElement) entityElement ).getJoinedSubclass() ); + processEntityElementsImport( ( (JaxbClassElement) entityElement ).getUnionSubclass() ); + } + else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbSubclassElement) entityElement ).getSubclass() ); + } + else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbJoinedSubclassElement) entityElement ).getJoinedSubclass() ); + } + else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { + processEntityElementsImport( ( (JaxbUnionSubclassElement) entityElement ).getUnionSubclass() ); + } + } + + private void processResultSetMappings() { + List resultsetElements = new ArrayList(); + + addAllIfNotEmpty( resultsetElements, mappingRoot().getResultset() ); + findResultSets( resultsetElements, mappingRoot().getClazz() ); + findResultSets( resultsetElements, mappingRoot().getJoinedSubclass() ); + findResultSets( resultsetElements, mappingRoot().getUnionSubclass() ); + findResultSets( resultsetElements, mappingRoot().getSubclass() ); + if ( resultsetElements.isEmpty() ) { + return; + } + for ( final JaxbResultsetElement element : resultsetElements ) { + metadataCollector().addResultSetMapping( + ResultSetMappingBinder.buildResultSetMappingDefinitions( + element, bindingContext(), metadataCollector() + ) + ); + } + + } + + private static void findResultSets(List resultsetElements, List entityElements) { + for ( final EntityElement element : entityElements ) { + addAllIfNotEmpty( resultsetElements, element.getResultset() ); + } + } + + private static void addAllIfNotEmpty(List target, List values) { + if ( CollectionHelper.isNotEmpty( values ) ) { + target.addAll( values ); + } + } + + private void processNamedQueries() { + for ( final JaxbQueryElement element : mappingRoot().getQuery() ) { + NamedQueryBindingHelper.bindNamedQuery( element, metadataCollector() ); + } + for ( final JaxbSqlQueryElement element : mappingRoot().getSqlQuery() ) { + NamedQueryBindingHelper.bindNamedSQLQuery( + element, + bindingContext(), + metadataCollector() + ); + } + } + +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HierarchyBuilder.java new file mode 100644 index 000000000000..d4ee4dc2168c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/HierarchyBuilder.java @@ -0,0 +1,226 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinedSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSqlQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbUnionSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.SubEntityElement; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.SubclassEntitySource; +import org.hibernate.metamodel.spi.BindingContext; + +/** + * @author Steve Ebersole + */ +public class HierarchyBuilder { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HierarchyBuilder.class ); + + private final BindingContext bindingContext; + + private final List entityHierarchies = new ArrayList(); + + // process state + private final Map subEntityContainerMap = new HashMap(); + private final List extendsQueue = new ArrayList(); + + // mapping file specific state + private MappingDocument currentMappingDocument; + + public HierarchyBuilder(BindingContext bindingContext) { + this.bindingContext = bindingContext; + } + + public void processMappingDocument(MappingDocument mappingDocument) { + this.currentMappingDocument = mappingDocument; + try { + LOG.tracef( "Processing mapping document: %s ", mappingDocument.getOrigin() ); + processCurrentMappingDocument(); + } + finally { + this.currentMappingDocument = null; + } + } + + private void processCurrentMappingDocument() { + final JaxbHibernateMapping root = currentMappingDocument.getMappingRoot(); + for ( final JaxbClassElement jaxbClass : root.getClazz() ) { + // we can immediately handle elements in terms of creating the hierarchy entry + final RootEntitySourceImpl rootEntitySource = new RootEntitySourceImpl( + currentMappingDocument, + jaxbClass + ); + final EntityHierarchySourceImpl hierarchy = new EntityHierarchySourceImpl( rootEntitySource ); + entityHierarchies.add( hierarchy ); + subEntityContainerMap.put( rootEntitySource.getEntityName(), rootEntitySource ); + processSubElements( jaxbClass, rootEntitySource ); + } + List subEntityElements = new ArrayList( root.getJoinedSubclass() ); + subEntityElements.addAll( root.getUnionSubclass() ); + subEntityElements.addAll( root.getSubclass() ); + + for ( final SubEntityElement element : subEntityElements ) { + processSubclassElement( element ); + } + + } + + private void processSubclassElement(SubEntityElement element) { + // we have to see if this things super-type has been found yet, and if not add it to the + // extends queue + final String entityItExtends = currentMappingDocument.getMappingLocalBindingContext() + .qualifyClassName( element.getExtends() ); + final AbstractEntitySourceImpl container = subEntityContainerMap.get( entityItExtends ); + final SubclassEntitySourceImpl subClassEntitySource = createSubClassEntitySource( element, (EntitySource) container ); + final String entityName = subClassEntitySource.getEntityName(); + subEntityContainerMap.put( entityName, subClassEntitySource ); + processSubElements( element, subClassEntitySource ); + if ( container != null ) { + // we already have this entity's super, attach it and continue + container.add( subClassEntitySource ); + } + else { + // we do not yet have the super and have to wait, so add it fto the extends queue + extendsQueue.add( new ExtendsQueueEntry( subClassEntitySource, entityItExtends ) ); + } + } + + public List groupEntityHierarchies() { + while ( ! extendsQueue.isEmpty() ) { + // set up a pass over the queue + int numberOfMappingsProcessed = 0; + Iterator iterator = extendsQueue.iterator(); + while ( iterator.hasNext() ) { + final ExtendsQueueEntry entry = iterator.next(); + final AbstractEntitySourceImpl container = subEntityContainerMap.get( entry.entityItExtends ); + if ( container != null ) { + // we now have this entity's super, attach it and remove entry from extends queue + container.add( entry.subClassEntitySource ); + iterator.remove(); + numberOfMappingsProcessed++; + } + } + + if ( numberOfMappingsProcessed == 0 ) { + + // todo : we could log the waiting dependencies... + throw currentMappingDocument.getMappingLocalBindingContext().makeMappingException( "Unable to process extends dependencies in hbm files" ); + } + } + + return entityHierarchies; + } + + private void processSubElements(EntityElement entityElement, AbstractEntitySourceImpl container) { + if ( JaxbClassElement.class.isInstance( entityElement ) ) { + final JaxbClassElement jaxbClass = (JaxbClassElement) entityElement; + processElements( jaxbClass.getJoinedSubclass(), container ); + processElements( jaxbClass.getSubclass(), container ); + processElements( jaxbClass.getUnionSubclass(), container ); + } + else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) { + final JaxbSubclassElement jaxbSubclass = (JaxbSubclassElement) entityElement; + processElements( jaxbSubclass.getSubclass(), container ); + } + else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) { + final JaxbJoinedSubclassElement jaxbJoinedSubclass = (JaxbJoinedSubclassElement) entityElement; + processElements( jaxbJoinedSubclass.getJoinedSubclass(), container ); + } + else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) { + final JaxbUnionSubclassElement jaxbUnionSubclass = (JaxbUnionSubclassElement) entityElement; + processElements( jaxbUnionSubclass.getUnionSubclass(), container ); + } + processNamedQueries( entityElement ); + } + + private void processElements(List subElements, AbstractEntitySourceImpl container) { + for ( final SubEntityElement subElement : subElements ) { + final SubclassEntitySourceImpl subclassEntitySource = createSubClassEntitySource( subElement, ( EntitySource ) container ); + container.add( subclassEntitySource ); + final String subEntityName = subclassEntitySource.getEntityName(); + subEntityContainerMap.put( subEntityName, subclassEntitySource ); + + // Re-run the sub element to handle, as an example, subclasses + // within a subclass. + processSubElements(subElement, subclassEntitySource); + } + } + + private SubclassEntitySourceImpl createSubClassEntitySource(SubEntityElement subEntityElement, EntitySource entitySource) { + if ( JaxbJoinedSubclassElement.class.isInstance( subEntityElement ) ) { + return new JoinedSubclassEntitySourceImpl( + currentMappingDocument, + JaxbJoinedSubclassElement.class.cast( subEntityElement ), + entitySource + ); + } + else { + return new SubclassEntitySourceImpl( currentMappingDocument, subEntityElement, entitySource ); + } + } + + private void processNamedQueries( EntityElement entityElement ) { + // For backward compatibility, store named queries prefixed with + // the class name. + String queryNamePrefix = entityElement.getEntityName(); + queryNamePrefix = StringHelper.isNotEmpty( queryNamePrefix ) ? queryNamePrefix : currentMappingDocument.getMappingLocalBindingContext().qualifyClassName( entityElement.getName() ); + for ( final JaxbQueryElement element : entityElement.getQuery() ) { + element.setName( queryNamePrefix + "." + element.getName() ); + NamedQueryBindingHelper.bindNamedQuery( element, bindingContext.getMetadataCollector() ); + } + for ( final JaxbSqlQueryElement element : entityElement.getSqlQuery() ) { + element.setName( queryNamePrefix + "." + element.getName() ); + NamedQueryBindingHelper.bindNamedSQLQuery( + element, + currentMappingDocument.getMappingLocalBindingContext(), + bindingContext.getMetadataCollector() + ); + } + } + + private static class ExtendsQueueEntry { + private final SubclassEntitySource subClassEntitySource; + private final String entityItExtends; + + private ExtendsQueueEntry(SubclassEntitySource subClassEntitySource, String entityItExtends) { + this.subClassEntitySource = subClassEntitySource; + this.entityItExtends = entityItExtends; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdBagSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdBagSourceImpl.java new file mode 100644 index 000000000000..4c22365ba186 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdBagSourceImpl.java @@ -0,0 +1,178 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIdbagElement; +import org.hibernate.metamodel.source.spi.CollectionIdSource; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.Orderable; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * @author Steve Ebersole + */ +public class IdBagSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable { + public final CollectionIdSource collectionIdSource; + + public IdBagSourceImpl( + MappingDocument mappingDocument, + final JaxbIdbagElement element, + AbstractEntitySourceImpl abstractEntitySource) { + super( mappingDocument, element, abstractEntitySource ); + + final List relationalValueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return element.getCollectionId().getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + element.getCollectionId().getLength(), + null, + null + ); + } + + @Override + public List getColumn() { + return element.getCollectionId().getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isForceNotNull() { + return true; + } + } + ); + + ColumnSource collectionIdColumnSource = null; + if ( relationalValueSources != null && relationalValueSources.isEmpty() ) { + if ( relationalValueSources.size() > 1 ) { + throw makeMappingException( "Expecting just a single column for collection id (idbag)" ); + } + + final RelationalValueSource relationalValueSource = relationalValueSources.get( 0 ); + if ( !ColumnSource.class.isInstance( relationalValueSource ) ) { + throw makeMappingException( "Expecting column for collection id (idbag), but found formula" ); + } + + collectionIdColumnSource = (ColumnSource) relationalValueSource; + } + + final HibernateTypeSource typeSource = new HibernateTypeSource() { + private final String name = element.getCollectionId().getType(); + + @Override + public String getName() { + return name; + } + + @Override + public Map getParameters() { + return Collections.emptyMap(); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + + this.collectionIdSource = new CollectionIdSourceImpl( + collectionIdColumnSource, + typeSource, + element.getCollectionId().getGenerator().getClazz() + ); + } + + @Override + public PluralAttributeNature getNature() { + return PluralAttributeNature.ID_BAG; + } + + @Override + public JaxbBagElement getPluralAttributeElement() { + return (JaxbBagElement) super.getPluralAttributeElement(); + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getOrder() { + return getPluralAttributeElement().getOrderBy(); + } + + private static class CollectionIdSourceImpl implements CollectionIdSource { + private final ColumnSource columnSource; + private final HibernateTypeSource typeSource; + private final String generator; + + public CollectionIdSourceImpl( + ColumnSource columnSource, + HibernateTypeSource typeSource, + String generator) { + this.columnSource = columnSource; + this.typeSource = typeSource; + this.generator = generator; + } + + @Override + public ColumnSource getColumnSource() { + return columnSource; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getGeneratorName() { + return generator; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdentifierKeyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdentifierKeyAttributeSourceImpl.java new file mode 100644 index 000000000000..d8393a75ffd6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdentifierKeyAttributeSourceImpl.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * @author Gail Badner + */ +public class IdentifierKeyAttributeSourceImpl extends KeyAttributeSourceImpl { + public IdentifierKeyAttributeSourceImpl( + MappingDocument mappingDocument, + AttributeSourceContainer container, + JaxbKeyPropertyElement keyPropertyElement) { + super( mappingDocument, keyPropertyElement, container, NaturalIdMutability.NOT_NATURAL_ID ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdentifierKeyManyToOneSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdentifierKeyManyToOneSourceImpl.java new file mode 100644 index 000000000000..30b1fea7b5e4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IdentifierKeyManyToOneSourceImpl.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * @author Gail Badner + */ +public class IdentifierKeyManyToOneSourceImpl extends KeyManyToOneSourceImpl { + + public IdentifierKeyManyToOneSourceImpl( + MappingDocument mappingDocument, + AttributeSourceContainer container, + JaxbKeyManyToOneElement keyManyToOneElement) { + super( mappingDocument, container, keyManyToOneElement, NaturalIdMutability.NOT_NATURAL_ID ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/InLineViewSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/InLineViewSourceImpl.java new file mode 100644 index 000000000000..b83d90db30df --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/InLineViewSourceImpl.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.spi.InLineViewSource; + +/** + * @author Steve Ebersole + */ +public class InLineViewSourceImpl + extends AbstractHbmSourceNode + implements InLineViewSource { + private final String schemaName; + private final String catalogName; + private final String selectStatement; + private final String logicalName; + + public InLineViewSourceImpl( + MappingDocument mappingDocument, + String schemaName, + String catalogName, + String selectStatement, String logicalName) { + super( mappingDocument ); + this.schemaName = schemaName; + this.catalogName = catalogName; + this.selectStatement = selectStatement; + this.logicalName = logicalName; + } + + @Override + public String getExplicitSchemaName() { + return schemaName; + } + + @Override + public String getExplicitCatalogName() { + return catalogName; + } + + @Override + public String getSelectStatement() { + return selectStatement; + } + + @Override + public String getLogicalName() { + return logicalName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IndexConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IndexConstraintSourceImpl.java new file mode 100644 index 000000000000..a9103b3b6074 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/IndexConstraintSourceImpl.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.spi.IndexConstraintSource; + +/** + * @author Brett Meyer + */ +class IndexConstraintSourceImpl extends AbstractConstraintSource implements IndexConstraintSource { + + public IndexConstraintSourceImpl( String name, String tableName ) { + super( name, tableName ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "IndexConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean isUnique() { + // TODO: Is it possible to have a unique index in HBM? + return false; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/JoinedSubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/JoinedSubclassEntitySourceImpl.java new file mode 100644 index 000000000000..a22d2bd42e35 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/JoinedSubclassEntitySourceImpl.java @@ -0,0 +1,129 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinedSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOnDeleteAttribute; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.JoinedSubclassEntitySource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Strong Liu + */ +public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl implements JoinedSubclassEntitySource { + private final JaxbKeyElement key; + private final List primaryKeyJoinColumnSources; + + public JoinedSubclassEntitySourceImpl(MappingDocument sourceMappingDocument, JaxbJoinedSubclassElement entityElement, EntitySource container) { + super( sourceMappingDocument, entityElement, container ); + this.key = entityElement.getKey(); + List valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return Helper.getValue( key.isUpdate(), true ); + } + + @Override + public String getColumnAttribute() { + return key.getColumnAttribute(); + } + + @Override + public List getColumn() { + return key.getColumn(); + } + + @Override + public boolean isForceNotNull() { + return Helper.getValue( key.isNotNull(), false ); + } + + + } + ); + this.primaryKeyJoinColumnSources = new ArrayList( valueSources.size() ); + for ( final RelationalValueSource valueSource : valueSources ) { + primaryKeyJoinColumnSources.add( ColumnSource.class.cast( valueSource ) ) ; + } + } + + @Override + public boolean isCascadeDeleteEnabled() { + return key.getOnDelete() == JaxbOnDeleteAttribute.CASCADE; + } + + @Override + public String getExplicitForeignKeyName() { + return key.getForeignKey(); + } + + @Override + public boolean createForeignKeyConstraint() { + // TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)? + return true; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return key.getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegate() { + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( key.getPropertyRef() ); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( key.getPropertyRef() ); + } + + @Override + public String getReferencedAttributeName() { + return key.getPropertyRef(); + } + }; + } + + @Override + public List getPrimaryKeyColumnSources() { + return primaryKeyJoinColumnSources; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/KeyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/KeyAttributeSourceImpl.java new file mode 100644 index 000000000000..21b27fd2d255 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/KeyAttributeSourceImpl.java @@ -0,0 +1,220 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class KeyAttributeSourceImpl + extends AbstractHbmSourceNode + implements SingularAttributeSource { + private final JaxbKeyPropertyElement keyPropertyElement; + private final NaturalIdMutability naturalIdMutability; + private final HibernateTypeSource typeSource; + private final List valueSources; + + private final AttributePath attributePath; + private final AttributeRole attributeRole; + + public KeyAttributeSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyPropertyElement keyPropertyElement, + AttributeSourceContainer container, final NaturalIdMutability naturalIdMutability) { + super( mappingDocument ); + this.keyPropertyElement = keyPropertyElement; + this.naturalIdMutability = naturalIdMutability; + this.typeSource = new HibernateTypeSource() { + private final String name = keyPropertyElement.getTypeAttribute() != null + ? keyPropertyElement.getTypeAttribute() + : keyPropertyElement.getType() != null + ? keyPropertyElement.getType().getName() + : null; + private final Map parameters = ( keyPropertyElement.getType() != null ) + ? Helper.extractParameters( keyPropertyElement.getType().getParam() ) + : null; + + @Override + public String getName() { + return name; + } + + @Override + public Map getParameters() { + return parameters; + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return keyPropertyElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + keyPropertyElement.getLength(), + null, + null + ); + } + + + @Override + public List getColumn() { + return keyPropertyElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isForceNotNull() { + return true; + } + } + ); + + this.attributePath = container.getAttributePathBase().append( getName() ); + this.attributeRole = container.getAttributeRoleBase().append( getName() ); + } + + @Override + public String getName() { + return keyPropertyElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return keyPropertyElement.getAccess(); + } + + @Override + public PropertyGeneration getGeneration() { + return PropertyGeneration.NEVER; + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.BASIC; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Collection getToolingHintSources() { + return keyPropertyElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/KeyManyToOneSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/KeyManyToOneSourceImpl.java new file mode 100644 index 000000000000..2008fe450857 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/KeyManyToOneSourceImpl.java @@ -0,0 +1,230 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class KeyManyToOneSourceImpl + extends AbstractToOneAttributeSourceImpl + implements SingularAttributeSource { + private final JaxbKeyManyToOneElement keyManyToOneElement; + private final List valueSources; + + private final AttributePath attributePath; + private final AttributeRole attributeRole; + + public KeyManyToOneSourceImpl( + MappingDocument mappingDocument, + AttributeSourceContainer container, + final JaxbKeyManyToOneElement keyManyToOneElement, + final NaturalIdMutability naturalIdMutability) { + super( mappingDocument, naturalIdMutability, null ); + this.keyManyToOneElement = keyManyToOneElement; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return keyManyToOneElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return null; + } + + @Override + public List getColumn() { + return keyManyToOneElement.getColumn(); + } + + @Override + public List getFormula() { + return Collections.emptyList(); + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return false; + } + } + ); + + this.attributePath = container.getAttributePathBase().append( getName() ); + this.attributeRole = container.getAttributeRoleBase().append( getName() ); + } + + @Override + public String getName() { + return keyManyToOneElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public String getPropertyAccessorName() { + return keyManyToOneElement.getAccess(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.MANY_TO_ONE; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + protected boolean requiresImmediateFetch() { + return false; + } + + @Override + protected String getFetchSelectionString() { + return null; + } + + @Override + protected String getLazySelectionString() { + return keyManyToOneElement.getLazy() != null ? + keyManyToOneElement.getLazy().value() : + null; + } + + @Override + protected String getOuterJoinSelectionString() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Collection getToolingHintSources() { + return keyManyToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return keyManyToOneElement.getEntityName(); + } + + @Override + public boolean isUnique() { + return false; + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return ForeignKeyDirection.TO_PARENT; + } + + @Override + public Set getCascadeStyles() { + return Collections.singleton( CascadeStyles.NONE ); + } + + @Override + public String getExplicitForeignKeyName() { + return keyManyToOneElement.getForeignKey(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return "cascade".equals( keyManyToOneElement.getOnDelete().value() ); + } + + protected String getClassName() { + return keyManyToOneElement.getClazz(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ListSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ListSourceImpl.java new file mode 100644 index 000000000000..ba3f447d521c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ListSourceImpl.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListIndexElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +public class ListSourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource { + private final PluralAttributeSequentialIndexSource indexSource; + + public ListSourceImpl( + MappingDocument sourceMappingDocument, + JaxbListElement listElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, listElement, container ); + JaxbListIndexElement listIndexElement = listElement.getListIndex(); + if ( listIndexElement == null ) { + this.indexSource = new PluralAttributeSequentialIndexSourceImpl( sourceMappingDocument(), listElement.getIndex() ); + } + else { + this.indexSource = new PluralAttributeSequentialIndexSourceImpl( sourceMappingDocument(), listIndexElement ); + } + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } + + @Override + public JaxbListElement getPluralAttributeElement() { + return ( JaxbListElement ) super.getPluralAttributeElement(); + } + + @Override + public PluralAttributeNature getNature() { + return PluralAttributeNature.LIST; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/LoadCollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/LoadCollectionBinder.java new file mode 100644 index 000000000000..569b76e7cdee --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/LoadCollectionBinder.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.cfg.HbmBinder; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryCollectionReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbLoadCollectionElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; + +/** + * @author Strong Liu + */ +class LoadCollectionBinder extends AbstractReturnBinder { + LoadCollectionBinder( + final JaxbLoadCollectionElement element, + final int elementIndex, + final LocalBindingContext context, + final InFlightMetadataCollector metadataCollector) { + super( element, elementIndex, context, metadataCollector ); + } + + @Override + NativeSQLQueryReturn process() { + final String collectionAttribute = element.getRole(); + int dot = collectionAttribute.lastIndexOf( '.' ); + if ( dot == -1 ) { + throw context.makeMappingException( + "Collection attribute for sql query return [alias=" + alias + "] not formatted correctly {OwnerClassName.propertyName}" + ); + } + final String ownerClassName = HbmBinder.getClassName( + collectionAttribute.substring( 0, dot ), context.getMappingDefaults().getPackageName() + ); + final String ownerPropertyName = collectionAttribute.substring( dot + 1 ); + final Map propertyResults = new HashMap(); + processReturnProperties( new ReturnPropertiesCallbackImpl( alias, propertyResults, context ) ); + return new NativeSQLQueryCollectionReturn( + alias, ownerClassName, ownerPropertyName, propertyResults, lockMode + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ManyToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ManyToOneAttributeSourceImpl.java new file mode 100644 index 000000000000..2339574c9230 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ManyToOneAttributeSourceImpl.java @@ -0,0 +1,231 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Steve Ebersole + */ +class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl { + private final JaxbManyToOneElement manyToOneElement; + private final String containingTableName; + private final List valueSources; + + private final AttributeRole attributeRole; + private final AttributePath attributePath; + + ManyToOneAttributeSourceImpl( + MappingDocument sourceMappingDocument, + AttributeSourceContainer container, + final JaxbManyToOneElement manyToOneElement, + final String logicalTableName, + NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument, naturalIdMutability, manyToOneElement.getPropertyRef() ); + this.manyToOneElement = manyToOneElement; + this.containingTableName = logicalTableName; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return manyToOneElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return manyToOneElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + return manyToOneElement.getColumn(); + } + + @Override + public List getFormula() { + return manyToOneElement.getFormula(); + } + + @Override + public String getContainingTableName() { + return logicalTableName; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return manyToOneElement.isInsert(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return manyToOneElement.isUpdate(); + } + } + ); + + this.attributeRole = container.getAttributeRoleBase().append( manyToOneElement.getName() ); + this.attributePath = container.getAttributePathBase().append( manyToOneElement.getName() ); + } + + @Override + public String getName() { + return manyToOneElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public String getPropertyAccessorName() { + return manyToOneElement.getAccess(); + } + + @Override + public boolean isIgnoreNotFound() { + return manyToOneElement.getNotFound() != null && "ignore".equalsIgnoreCase( manyToOneElement.getNotFound().value() ); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return manyToOneElement.isOptimisticLock(); + } + + @Override + public Set getCascadeStyles() { + return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext() ); + } + + @Override + protected boolean requiresImmediateFetch() { + return false; + } + + @Override + protected String getFetchSelectionString() { + return manyToOneElement.getFetch() != null ? + manyToOneElement.getFetch().value() : + null; + } + + @Override + protected String getLazySelectionString() { + return manyToOneElement.getLazy() != null ? + manyToOneElement.getLazy().value() : + null; + } + + @Override + protected String getOuterJoinSelectionString() { + return manyToOneElement.getOuterJoin() != null ? + manyToOneElement.getOuterJoin().value() : + null; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.MANY_TO_ONE; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return manyToOneElement.isInsert(); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return manyToOneElement.isUpdate(); + } + + @Override + public boolean areValuesNullableByDefault() { + return ! Helper.getValue( manyToOneElement.isNotNull(), false ); + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Collection getToolingHintSources() { + return manyToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return manyToOneElement.getClazz() != null + ? bindingContext().qualifyClassName( manyToOneElement.getClazz() ) + : manyToOneElement.getEntityName(); + } + + @Override + public boolean isUnique() { + return manyToOneElement.isUnique(); + } + + @Override + public String getExplicitForeignKeyName() { + return manyToOneElement.getForeignKey(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return ForeignKeyDirection.TO_PARENT; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MapKeySourceBasicImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MapKeySourceBasicImpl.java new file mode 100644 index 000000000000..d71d59d693c2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MapKeySourceBasicImpl.java @@ -0,0 +1,221 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIndexElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapKeyElement; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceBasic; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * + */ +public class MapKeySourceBasicImpl extends AbstractHbmSourceNode implements PluralAttributeMapKeySourceBasic { + private final PluralAttributeIndexNature nature; + private final List valueSources; + private final HibernateTypeSource typeSource; + + public MapKeySourceBasicImpl(MappingDocument sourceMappingDocument, final JaxbMapKeyElement mapKey) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + + @Override + public String getColumnAttribute() { + return mapKey.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + mapKey.getLength(), + null, + null + ); + } + + + @Override + public List getColumn() { + return mapKey.getColumn(); + } + + @Override + public List getFormula() { + return mapKey.getFormula(); + } + + @Override + public String getFormulaAttribute() { + return mapKey.getFormulaAttribute(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } + ); + this.typeSource = new HibernateTypeSource() { + @Override + public String getName() { + if ( mapKey.getTypeAttribute() != null ) { + return mapKey.getTypeAttribute(); + } + if ( mapKey.getType() != null ) { + return mapKey.getType().getName(); + } + return null; + } + + @Override + public Map getParameters() { + return mapKey.getType() != null + ? Helper.extractParameters( mapKey.getType().getParam() ) + : java.util.Collections.emptyMap(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + this.nature = PluralAttributeIndexNature.BASIC; + } + + public MapKeySourceBasicImpl(MappingDocument sourceMappingDocument, final JaxbIndexElement indexElement) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( + sourceMappingDocument, + new Helper.ValueSourcesAdapter() { + + @Override + public String getColumnAttribute() { + return indexElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + indexElement.getLength(), + null, + null + ); + } + + + @Override + public List getColumn() { + return indexElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } + ); + typeSource = new HibernateTypeSource() { + @Override + public String getName() { + return indexElement.getType(); + } + + @Override + public Map getParameters() { + return java.util.Collections.emptyMap(); + } + + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + + this.nature = PluralAttributeIndexNature.BASIC; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public PluralAttributeIndexNature getNature() { + return nature; + } + + @Override + public List getDefaultNamingStrategies() { + final Binder.DefaultNamingStrategy defaultNamingStrategy = + new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.columnName( "idx" ); + } + }; + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public List relationalValueSources() { + return valueSources; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MapSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MapSourceImpl.java new file mode 100644 index 000000000000..2e9a38bc75c1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MapSourceImpl.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeIndexSource; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +public class MapSourceImpl extends AbstractPluralAttributeSourceImpl implements IndexedPluralAttributeSource { + private final PluralAttributeIndexSource indexSource; + + public MapSourceImpl( + MappingDocument sourceMappingDocument, + JaxbMapElement mapElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, mapElement, container ); + if ( mapElement.getMapKey() != null ) { + this.indexSource = new MapKeySourceBasicImpl( sourceMappingDocument, mapElement.getMapKey() ); + } + else if ( mapElement.getIndex() != null ) { + this.indexSource = new MapKeySourceBasicImpl( sourceMappingDocument, mapElement.getIndex() ); + } + else if ( mapElement.getCompositeMapKey() != null ) { + this.indexSource = new PluralAttributeMapKeySourceEmbeddedImpl( + sourceMappingDocument, + this, + mapElement.getCompositeMapKey() + ); + } + else if ( mapElement.getCompositeIndex() != null ) { + this.indexSource = new PluralAttributeMapKeySourceEmbeddedImpl( + sourceMappingDocument, + this, + mapElement.getCompositeIndex() + ); + } + else if ( mapElement.getMapKeyManyToMany() != null ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + else if ( mapElement.getIndexManyToMany() != null ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + else if ( mapElement.getIndexManyToAny() != null ) { + throw new NotYetImplementedException( " is not supported yet" ); + } + else { + throw new AssertionFailure( "No map key found" ); + } + } + + @Override + public PluralAttributeIndexSource getIndexSource() { + return indexSource; + } + + @Override + public JaxbMapElement getPluralAttributeElement() { + return ( JaxbMapElement ) super.getPluralAttributeElement(); + } + + @Override + public PluralAttributeNature getNature() { + return PluralAttributeNature.MAP; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MappingDocument.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MappingDocument.java new file mode 100644 index 000000000000..2df4768b6304 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/MappingDocument.java @@ -0,0 +1,156 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.OverriddenMappingDefaults; +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFetchProfileElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.spi.MappingDefaults; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.BaseDelegatingBindingContext; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; + +/** + * Aggregates together information about a mapping document. + * + * @author Steve Ebersole + */ +public class MappingDocument { + private final BindResult hbmBindResult; + private final LocalBindingContextImpl mappingLocalBindingContext; + + public MappingDocument(BindResult hbmBindResult, BindingContext bindingContext) { + this.hbmBindResult = hbmBindResult; + this.mappingLocalBindingContext = new LocalBindingContextImpl( bindingContext ); + + } + + public JaxbHibernateMapping getMappingRoot() { + return hbmBindResult.getRoot(); + } + + public Origin getOrigin() { + return hbmBindResult.getOrigin(); + } + + public BindResult getJaxbRoot() { + return hbmBindResult; + } + + public HbmBindingContext getMappingLocalBindingContext() { + return mappingLocalBindingContext; + } + + private class LocalBindingContextImpl extends BaseDelegatingBindingContext implements HbmBindingContext { + private final MappingDefaults localMappingDefaults; + private final MetaAttributeContext metaAttributeContext; + + private LocalBindingContextImpl(BindingContext rootBindingContext) { + super( rootBindingContext ); + this.localMappingDefaults = new OverriddenMappingDefaults( + rootBindingContext.getMappingDefaults(), + hbmBindResult.getRoot().getPackage(), + hbmBindResult.getRoot().getSchema(), + hbmBindResult.getRoot().getCatalog(), + null, + null, + null, + hbmBindResult.getRoot().getDefaultCascade(), + hbmBindResult.getRoot().getDefaultAccess(), + hbmBindResult.getRoot().isDefaultLazy() + ); + + if ( CollectionHelper.isEmpty( hbmBindResult.getRoot().getMeta() ) ) { + this.metaAttributeContext = new MetaAttributeContext( + rootBindingContext.getGlobalMetaAttributeContext() + ); + } + else { + this.metaAttributeContext = Helper.extractMetaAttributeContext( + hbmBindResult.getRoot().getMeta(), + true, + rootBindingContext.getGlobalMetaAttributeContext() + ); + } + } + + @Override + public String qualifyClassName(String unqualifiedName) { + return Helper.qualifyIfNeeded( unqualifiedName, getMappingDefaults().getPackageName() ); + } + + @Override + public JavaTypeDescriptor typeDescriptor(String name) { + return super.typeDescriptor( qualifyClassName( name ) ); + } + + @Override + public MappingDefaults getMappingDefaults() { + return localMappingDefaults; + } + + @Override + public Origin getOrigin() { + return hbmBindResult.getOrigin(); + } + + @Override + public MappingException makeMappingException(String message) { + return new MappingException( message, getOrigin() ); + } + + @Override + public MappingException makeMappingException(String message, Exception cause) { + return new MappingException( message, cause, getOrigin() ); + } + + @Override + public boolean isAutoImport() { + return hbmBindResult.getRoot().isAutoImport(); + } + + @Override + public MetaAttributeContext getMetaAttributeContext() { + return metaAttributeContext; + } + + @Override + public String determineEntityName(EntityElement entityElement) { + return Helper.determineEntityName( entityElement, getMappingDefaults().getPackageName() ); + } + + @Override + public void processFetchProfiles(List fetchProfiles, String containingEntityName) { + // todo : this really needs to not be part of the context + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/NamedQueryBindingHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/NamedQueryBindingHelper.java new file mode 100644 index 000000000000..48582cee8b13 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/NamedQueryBindingHelper.java @@ -0,0 +1,205 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.hbm.parser.BasicQueryElementContentParser; +import org.hibernate.metamodel.source.internal.hbm.parser.SQLQueryElementContentParser; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbLoadCollectionElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSqlQueryElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +/** + * Helper class used to bind named query elements. + * + * @author Brett Meyer + * @author Strong Liu + */ +public class NamedQueryBindingHelper { + + /** + * Helper method used to bind {@code } element. + * + * @param queryElement The {@code } element. + * @param metadataCollector The {@link org.hibernate.metamodel.Metadata} which this named query will be added to. + */ + public static void bindNamedQuery( + final JaxbQueryElement queryElement, + final InFlightMetadataCollector metadataCollector) { + final NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder(); + final BasicQueryElementContentParser parser = new BasicQueryElementContentParser(); + parser.parse( builder, queryElement ); + metadataCollector.addNamedQuery( builder.createNamedQueryDefinition() ); + } + + public static void bindNamedSQLQuery( + final JaxbSqlQueryElement queryElement, + final LocalBindingContext bindingContext, + final InFlightMetadataCollector metadataCollector) { + final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder(); + final SQLQueryElementContentParser parser = new SQLQueryElementContentParser(); + + parser.parse( builder, queryElement ); + + final boolean callable = queryElement.isCallable(); + final String resultSetRef = queryElement.getResultsetRef(); + //TODO: check if the refereneced result set mapping definition exist or not? + builder.setCallable( callable ).setResultSetRef( resultSetRef ); + + NamedSQLQueryDefinition namedQuery; + //query returns are defined in the element. + if ( StringHelper.isNotEmpty( resultSetRef ) ) { + namedQuery = builder.createNamedQueryDefinition(); + } + else { + namedQuery = parser.buildQueryReturns( queryElement.getName(),builder, bindingContext, metadataCollector ); + } + metadataCollector.addNamedNativeQuery( namedQuery ); + } + + + + private static Map bindPropertyResults( + String alias, JaxbLoadCollectionElement element, + EntityBinding entityBinding) { + List returnPropertyElements + = element.getReturnProperty(); + List properties + = new ArrayList(); + List propertyNames = new ArrayList(); + HashMap> propertyResults = new HashMap>(); + for ( JaxbReturnPropertyElement propertyElement : returnPropertyElements ) { + String name = propertyElement.getName(); + if ( entityBinding == null || name.indexOf( '.' ) == -1 ) { + properties.add( propertyElement ); + propertyNames.add( name ); + } + else { + /** + * Reorder properties + * 1. get the parent property + * 2. list all the properties following the expected one in the parent property + * 3. calculate the lowest index and insert the property + */ + if ( entityBinding == null ) { + throw new org.hibernate.MappingException( + "dotted notation in or not yet supported" + ); + } + int dotIndex = name.lastIndexOf( '.' ); + String reducedName = name.substring( 0, dotIndex ); + AttributeBinding value = null;// getRecursiveAttributeBinding(entityBinding, reducedName ); + Iterable parentPropIter; + if ( EmbeddedAttributeBinding.class.isInstance( value ) ) { + EmbeddedAttributeBinding comp + = (EmbeddedAttributeBinding) value; + parentPropIter = comp.getEmbeddableBinding().attributeBindings(); + } + else if ( SingularAssociationAttributeBinding.class.isInstance( value ) ) { + SingularAssociationAttributeBinding toOne + = SingularAssociationAttributeBinding.class.cast( + value + ); + EntityBinding referencedEntityBinding + = toOne.getReferencedEntityBinding(); + SingularAttributeBinding referencedAttributeBinding + = toOne.getReferencedAttributeBinding(); + try { + parentPropIter = EmbeddedAttributeBinding.class.cast( + referencedAttributeBinding + ).getEmbeddableBinding().attributeBindings(); + } + catch ( ClassCastException e ) { + throw new org.hibernate.MappingException( + "dotted notation reference neither a component nor a many/one to one", e + ); + } + } + else { + throw new org.hibernate.MappingException( + "dotted notation reference neither a component nor a many/one to one" + ); + } + boolean hasFollowers = false; + List followers = new ArrayList(); + for ( AttributeBinding binding : parentPropIter ) { + String currentPropertyName + = binding.getAttribute().getName(); + String currentName = reducedName + '.' + + currentPropertyName; + if ( hasFollowers ) { + followers.add( currentName ); + } + if ( name.equals( currentName ) ) { + hasFollowers = true; + } + } + + int index = propertyNames.size(); + int followersSize = followers.size(); + for ( int loop = 0; loop < followersSize; loop++ ) { + String follower = followers.get( loop ); + int currentIndex = getIndexOfFirstMatchingProperty( + propertyNames, follower + ); + index = currentIndex != -1 && currentIndex < index + ? currentIndex : index; + } + propertyNames.add( index, name ); + properties.add( index, propertyElement ); + } + } + + Map results = new HashMap( propertyResults.size() ); + return results; + } + + + + private static int getIndexOfFirstMatchingProperty(List propertyNames, + String follower) { + int propertySize = propertyNames.size(); + for ( int propIndex = 0; propIndex < propertySize; propIndex++ ) { + if ( ( (String) propertyNames.get( propIndex ) ).startsWith( + follower + ) ) { + return propIndex; + } + } + return -1; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/OneToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/OneToOneAttributeSourceImpl.java new file mode 100644 index 000000000000..756e69c23c7c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/OneToOneAttributeSourceImpl.java @@ -0,0 +1,226 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl { + private final JaxbOneToOneElement oneToOneElement; + private final List valueSources; + private final String containingTableName; + + private final AttributeRole attributeRole; + private final AttributePath attributePath; + + OneToOneAttributeSourceImpl( + MappingDocument sourceMappingDocument, + AttributeSourceContainer container, + final JaxbOneToOneElement oneToOneElement, + final String logicalTableName, + NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument, naturalIdMutability, oneToOneElement.getPropertyRef() ); + this.oneToOneElement = oneToOneElement; + this.containingTableName = logicalTableName; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + // Not applicable to one-to-one + return null; + } + + @Override + public String getFormulaAttribute() { + return oneToOneElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + // Not applicable to one-to-one + return null; + } + + @Override + public List getFormula() { + return oneToOneElement.getFormula(); + } + + @Override + public String getContainingTableName() { + return logicalTableName; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return false; + } + } + ); + + this.attributeRole = container.getAttributeRoleBase().append( oneToOneElement.getName() ); + this.attributePath = container.getAttributePathBase().append( oneToOneElement.getName() ); + } + + @Override + public String getName() { + return oneToOneElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public String getPropertyAccessorName() { + return oneToOneElement.getAccess(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public Set getCascadeStyles() { + return Helper.interpretCascadeStyles( oneToOneElement.getCascade(), bindingContext() ); + } + + @Override + protected String getFetchSelectionString() { + return oneToOneElement.getFetch()!=null? oneToOneElement.getFetch().value() : null; + } + + @Override + protected String getLazySelectionString() { + return oneToOneElement.getLazy()!=null? oneToOneElement.getLazy().value() : null; + } + + @Override + protected String getOuterJoinSelectionString() { + return oneToOneElement.getOuterJoin()!=null? oneToOneElement.getOuterJoin().value() : null; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.ONE_TO_ONE; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + protected boolean requiresImmediateFetch() { + return !oneToOneElement.isConstrained(); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Collection getToolingHintSources() { + return oneToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return oneToOneElement.getClazz() != null + ? bindingContext().qualifyClassName( oneToOneElement.getClazz() ) + : oneToOneElement.getEntityName(); + } + + @Override + public boolean isUnique() { + return true; + } + + @Override + public String getExplicitForeignKeyName() { + return oneToOneElement.getForeignKey(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return oneToOneElement.isConstrained() ? ForeignKeyDirection.FROM_PARENT : ForeignKeyDirection.TO_PARENT; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceBasicImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceBasicImpl.java new file mode 100644 index 000000000000..3d3950953453 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceBasicImpl.java @@ -0,0 +1,156 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbElementElement; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceBasic; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeElementSourceBasicImpl + extends AbstractHbmSourceNode + implements PluralAttributeElementSourceBasic { + private final List valueSources; + private final HibernateTypeSource typeSource; + + public PluralAttributeElementSourceBasicImpl( + MappingDocument sourceMappingDocument, + final JaxbElementElement elementElement) { + super( sourceMappingDocument ); + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public boolean isIncludedInInsertByDefault() { + return PluralAttributeElementSourceBasicImpl.this.areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return PluralAttributeElementSourceBasicImpl.this.areValuesIncludedInUpdateByDefault(); + } + + @Override + public String getColumnAttribute() { + return elementElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return elementElement.getFormulaAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + elementElement.getLength(), + elementElement.getPrecision(), + elementElement.getScale() + ); + } + + @Override + public List getColumn() { + return elementElement.getColumn(); + } + + @Override + public List getFormula() { + return elementElement.getFormula(); + } + + @Override + public boolean isForceNotNull() { + return elementElement.isNotNull(); + } + } + ); + + this.typeSource = new HibernateTypeSource() { + @Override + public String getName() { + if ( elementElement.getTypeAttribute() != null ) { + return elementElement.getTypeAttribute(); + } + else if ( elementElement.getType() != null ) { + return elementElement.getType().getName(); + } + else { + return null; + } + } + + @Override + public Map getParameters() { + return elementElement.getType() != null + ? Helper.extractParameters( elementElement.getType().getParam() ) + : java.util.Collections.emptyMap(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.BASIC; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public HibernateTypeSource getExplicitHibernateTypeSource() { + return typeSource; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceEmbeddedImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceEmbeddedImpl.java new file mode 100644 index 000000000000..43d8d64ffff2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceEmbeddedImpl.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.hibernate.EntityMode; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbAnyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCompositeElementElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbNestedCompositeElementElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTuplizerElement; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceEmbedded; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementSourceEmbeddedImpl + extends AbstractHbmSourceNode + implements PluralAttributeElementSourceEmbedded { + + private final JaxbCompositeElementElement compositeElement; + private final EmbeddableSourceImpl embeddableSource; + private final Set cascadeStyles; + + public PluralAttributeElementSourceEmbeddedImpl( + MappingDocument mappingDocument, + AbstractPluralAttributeSourceImpl pluralAttributeSource, + JaxbCompositeElementElement compositeElement, + String cascadeString) { + super( mappingDocument ); + this.compositeElement = compositeElement; + + this.embeddableSource = new EmbeddableSourceImpl( + mappingDocument, + pluralAttributeSource.getAttributeRole(), + pluralAttributeSource.getAttributePath(), + new EmbeddableJaxbSourceImpl( compositeElement ), + null, + NaturalIdMutability.NOT_NATURAL_ID + ); + + this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.AGGREGATE; + } + + @Override + public EmbeddableSource getEmbeddableSource() { + return embeddableSource; + } + + @Override + public Collection getToolingHintSources() { + return compositeElement.getMeta(); + } + + public static class EmbeddableJaxbSourceImpl extends AbstractEmbeddableJaxbSource { + private final JaxbCompositeElementElement compositeElement; + + public EmbeddableJaxbSourceImpl(JaxbCompositeElementElement compositeElement) { + this.compositeElement = compositeElement; + } + + @Override + public String getClazz() { + return compositeElement.getClazz(); + } + + @Override + public String findParent() { + return compositeElement.getParent() != null + ? compositeElement.getParent().getName() + : null; + } + + @Override + public String findTuplizer() { + if ( compositeElement.getTuplizer() == null ) { + return null; + } + final EntityMode entityMode = StringHelper.isEmpty( compositeElement.getClazz() ) ? EntityMode.MAP : EntityMode.POJO; + for ( JaxbTuplizerElement tuplizerElement : compositeElement.getTuplizer() ) { + if ( entityMode == EntityMode.parse( tuplizerElement.getEntityMode().value() ) ) { + return tuplizerElement.getClazz(); + } + } + return null; + } + + @Override + public List getPropertyElementList() { + return compositeElement.getProperty(); + } + + @Override + public List getAnyElementList() { + return compositeElement.getAny(); + } + + @Override + public List getNestedCompositeElementList() { + return compositeElement.getNestedCompositeElement(); + } + + @Override + public List getManyToOneElementList() { + return compositeElement.getManyToOne(); + } + } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceManyToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceManyToManyImpl.java new file mode 100644 index 000000000000..bd069566d61e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceManyToManyImpl.java @@ -0,0 +1,268 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; +import java.util.Set; + +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFilterElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToManyElement; +import org.hibernate.metamodel.source.spi.FilterSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceManyToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementSourceManyToManyImpl + extends AbstractPluralAssociationElementSourceImpl + implements PluralAttributeElementSourceManyToMany { + private final JaxbManyToManyElement manyToManyElement; + private final Set cascadeStyles; + + private final List valueSources; + private final FilterSource[] filterSources; + public PluralAttributeElementSourceManyToManyImpl( + MappingDocument mappingDocument, + final PluralAttributeSource pluralAttributeSource, + final JaxbManyToManyElement manyToManyElement, + String cascadeString) { + super( mappingDocument, pluralAttributeSource ); + this.manyToManyElement = manyToManyElement; + this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() ); + + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return true; + } + + @Override + public String getColumnAttribute() { + return manyToManyElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return manyToManyElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + return manyToManyElement.getColumn(); + } + + @Override + public List getFormula() { + return manyToManyElement.getFormula(); + } + } + ); + this.filterSources = buildFilterSources(); + } + + private FilterSource[] buildFilterSources() { + final int size = manyToManyElement.getFilter().size(); + if ( size == 0 ) { + return null; + } + + FilterSource[] results = new FilterSource[size]; + for ( int i = 0; i < size; i++ ) { + JaxbFilterElement element = manyToManyElement.getFilter().get( i ); + results[i] = new FilterSourceImpl( sourceMappingDocument(), element ); + } + return results; + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.MANY_TO_MANY; + } + + @Override + public String getReferencedEntityName() { + return StringHelper.isNotEmpty( manyToManyElement.getEntityName() ) + ? manyToManyElement.getEntityName() + : bindingContext().qualifyClassName( manyToManyElement.getClazz() ); + } + + @Override + public FilterSource[] getFilterSources() { + return filterSources; + } + + @Override + public String getReferencedEntityAttributeName() { + return manyToManyElement.getPropertyRef(); + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isIgnoreNotFound() { + return manyToManyElement.getNotFound() != null && "ignore".equalsIgnoreCase( manyToManyElement.getNotFound().value() ); + } + + @Override + public String getExplicitForeignKeyName() { + return manyToManyElement.getForeignKey(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return false; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return manyToManyElement.getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegateImpl(); + } + + @Override + public boolean isUnique() { + return manyToManyElement.isUnique(); + } + + @Override + public String getWhere() { + return manyToManyElement.getWhere(); + } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } + + @Override + public FetchTiming getFetchTiming() { + final String fetchSelection = manyToManyElement.getFetch() != null ? + manyToManyElement.getFetch().value() : + null; + final String lazySelection = manyToManyElement.getLazy() != null + ? manyToManyElement.getLazy().value() + : null; + final String outerJoinSelection = manyToManyElement.getOuterJoin() != null + ? manyToManyElement.getOuterJoin().value() + : null; + + if ( lazySelection == null ) { + if ( "join".equals( fetchSelection ) || "true".equals( outerJoinSelection ) ) { + return FetchTiming.IMMEDIATE; + } + else if ( "false".equals( outerJoinSelection ) ) { + return FetchTiming.DELAYED; + } + else { + // default is FetchTiming.IMMEDIATE. + return FetchTiming.IMMEDIATE; + } + } + else if ( "true".equals( lazySelection ) ) { + return FetchTiming.DELAYED; + } + else if ( "false".equals( lazySelection ) ) { + return FetchTiming.IMMEDIATE; + } + // TODO: improve this method to say attribute name. + throw new MappingException( + String.format( + "Unexpected lazy selection [%s] on many-to-many element", + lazySelection + ), + origin() + ); + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getOrder() { + return manyToManyElement.getOrderBy(); + } + + public class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + @Override + public String getReferencedAttributeName() { + return manyToManyElement.getPropertyRef(); + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( manyToManyElement.getPropertyRef() ); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( manyToManyElement.getPropertyRef() ); + } + } + + @Override + public boolean createForeignKeyConstraint() { + // TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)? + return true; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceOneToManyImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceOneToManyImpl.java new file mode 100644 index 000000000000..b3d98c3d7bb3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeElementSourceOneToManyImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToManyElement; +import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceOneToMany; +import org.hibernate.metamodel.source.spi.PluralAttributeSource; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeElementSourceOneToManyImpl + extends AbstractPluralAssociationElementSourceImpl + implements PluralAttributeElementSourceOneToMany { + private final JaxbOneToManyElement oneToManyElement; + private final Set cascadeStyles; + + public PluralAttributeElementSourceOneToManyImpl( + MappingDocument mappingDocument, + final PluralAttributeSource pluralAttributeSource, + final JaxbOneToManyElement oneToManyElement, + String cascadeString) { + super( mappingDocument, pluralAttributeSource ); + this.oneToManyElement = oneToManyElement; + this.cascadeStyles = Helper.interpretCascadeStyles( cascadeString, bindingContext() ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.ONE_TO_MANY; + } + + @Override + public String getReferencedEntityName() { + return StringHelper.isNotEmpty( oneToManyElement.getEntityName() ) + ? oneToManyElement.getEntityName() + : bindingContext().qualifyClassName( oneToManyElement.getClazz() ); + } + + @Override + public boolean isIgnoreNotFound() { + return oneToManyElement.getNotFound() != null && "ignore".equalsIgnoreCase( oneToManyElement.getNotFound().value() ); + } + + @Override + public Set getCascadeStyles() { + return cascadeStyles; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeKeySourceImpl.java new file mode 100644 index 000000000000..720c78a971b2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeKeySourceImpl.java @@ -0,0 +1,141 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.PluralAttributeKeySource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +public class PluralAttributeKeySourceImpl + extends AbstractHbmSourceNode + implements PluralAttributeKeySource { + private final JaxbKeyElement keyElement; + + private final List valueSources; + + public PluralAttributeKeySourceImpl( + MappingDocument mappingDocument, + final JaxbKeyElement keyElement, + final AttributeSourceContainer container) { + super( mappingDocument ); + this.keyElement = keyElement; + + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return Helper.getValue( keyElement.isUpdate(), true ); + } + + @Override + public String getColumnAttribute() { + return keyElement.getColumnAttribute(); + } + + @Override + public List getColumn() { + return keyElement.getColumn(); + } + + @Override + public boolean isForceNotNull() { + return Helper.getValue( keyElement.isNotNull(), false ); + } + } + ); + } + + @Override + public String getExplicitForeignKeyName() { + return keyElement.getForeignKey(); + } + + @Override + public boolean createForeignKeyConstraint() { + // TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)? + return true; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return keyElement.getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegate() { + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( keyElement.getPropertyRef() ); + } + + @Override + public String getReferencedAttributeName() { + return keyElement.getPropertyRef(); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( keyElement.getPropertyRef() ); + } + }; + } + + @Override + public boolean isCascadeDeleteEnabled() { + return "cascade".equals( keyElement.getOnDelete().value() ); + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeMapKeySourceEmbeddedImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeMapKeySourceEmbeddedImpl.java new file mode 100644 index 000000000000..3ca71a0be90a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeMapKeySourceEmbeddedImpl.java @@ -0,0 +1,182 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCompositeIndexElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCompositeMapKeyElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement; +import org.hibernate.metamodel.source.spi.EmbeddableSource; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceEmbedded; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * @author Gail Badner + */ +public class PluralAttributeMapKeySourceEmbeddedImpl + extends AbstractHbmSourceNode + implements PluralAttributeMapKeySourceEmbedded { + + private final AbstractPluralAttributeSourceImpl pluralAttributeSource; + private final EmbeddableSourceImpl embeddableSource; + + + public PluralAttributeMapKeySourceEmbeddedImpl( + MappingDocument mappingDocument, + AbstractPluralAttributeSourceImpl pluralAttributeSource, + final JaxbCompositeIndexElement compositeIndexElement) { + this( + mappingDocument, + pluralAttributeSource, + new AbstractEmbeddableJaxbSource() { + + @Override + public String getClazz() { + return compositeIndexElement.getClazz(); + } + + @Override + public String findParent() { + return null; + } + + @Override + public String findTuplizer() { + return null; + } + + @Override + public List getKeyPropertyElementList() { + return compositeIndexElement.getKeyProperty(); + } + + @Override + public List getKeyManyToOneElementList() { + return compositeIndexElement.getKeyManyToOne(); + } + } + ); + } + + public PluralAttributeMapKeySourceEmbeddedImpl( + MappingDocument mappingDocument, + AbstractPluralAttributeSourceImpl pluralAttributeSource, + final JaxbCompositeMapKeyElement compositeMapKeyElement) { + this( + mappingDocument, + pluralAttributeSource, + + new AbstractEmbeddableJaxbSource() { + + @Override + public String getClazz() { + return compositeMapKeyElement.getClazz(); + } + + @Override + public String findParent() { + return null; + } + + @Override + public String findTuplizer() { + return null; + } + + @Override + public List getKeyPropertyElementList() { + return compositeMapKeyElement.getKeyProperty(); + } + + @Override + public List getKeyManyToOneElementList() { + return compositeMapKeyElement.getKeyManyToOne(); + } + } + ); + } + + private PluralAttributeMapKeySourceEmbeddedImpl( + MappingDocument mappingDocument, + AbstractPluralAttributeSourceImpl pluralAttributeSource, + EmbeddableJaxbSource embeddableJaxbSource) { + super( mappingDocument ); + + this.pluralAttributeSource = pluralAttributeSource; + this.embeddableSource = new EmbeddableSourceImpl( + mappingDocument, + pluralAttributeSource.getAttributeRole().append( "key" ), + pluralAttributeSource.getAttributePath().append( "key" ), + embeddableJaxbSource, + null, + NaturalIdMutability.NOT_NATURAL_ID + ); + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.AGGREGATE; + } + + @Override + public EmbeddableSource getEmbeddableSource() { + return embeddableSource; + } + + @Override + public List getDefaultNamingStrategies() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public HibernateTypeSource getTypeInformation() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List relationalValueSources() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeSequentialIndexSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeSequentialIndexSourceImpl.java new file mode 100644 index 000000000000..c2dc88d14a24 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PluralAttributeSequentialIndexSourceImpl.java @@ -0,0 +1,196 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIndexElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListIndexElement; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * + */ +public class PluralAttributeSequentialIndexSourceImpl extends AbstractHbmSourceNode implements + PluralAttributeSequentialIndexSource { + private final List< RelationalValueSource > valueSources; + private final HibernateTypeSource typeSource; + private final int base; + + public PluralAttributeSequentialIndexSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbListIndexElement indexElement) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() { + + List< JaxbColumnElement > columnElements = indexElement.getColumn() == null ? Collections.EMPTY_LIST : Collections.singletonList( indexElement.getColumn() ); + + @Override + public String getColumnAttribute() { + return indexElement.getColumnAttribute(); + } + + @Override + public List getColumn() { + return columnElements; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } ); + typeSource = new HibernateTypeSource() { + + @Override + public String getName() { + return "integer"; + } + + @Override + public Map< String, String > getParameters() { + return java.util.Collections.< String, String >emptyMap(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + base = Integer.parseInt( indexElement.getBase() ); + } + + public PluralAttributeSequentialIndexSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbIndexElement indexElement) { + super( sourceMappingDocument ); + valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() { + + @Override + public String getColumnAttribute() { + return indexElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + indexElement.getLength(), + null, + null + ); + } + @Override + public List getColumn() { + return indexElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return areValuesIncludedInInsertByDefault(); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return areValuesIncludedInUpdateByDefault(); + } + } ); + typeSource = new HibernateTypeSource() { + + @Override + public String getName() { + return StringHelper.isEmpty( indexElement.getType() ) ? "integer" : indexElement.getType(); + } + + @Override + public Map< String, String > getParameters() { + return java.util.Collections.< String, String >emptyMap(); + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + base = 0; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + @Override + public int base() { + return base; + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.SEQUENTIAL; + } + + @Override + public List getDefaultNamingStrategies() { + final Binder.DefaultNamingStrategy defaultNamingStrategy = new Binder.DefaultNamingStrategy() { + @Override + public String defaultName(NamingStrategy namingStrategy) { + return namingStrategy.columnName( "idx" ); + } + }; + return Collections.singletonList( defaultNamingStrategy ); + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public List< RelationalValueSource > relationalValueSources() { + return valueSources; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PropertyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PropertyAttributeSourceImpl.java new file mode 100644 index 000000000000..8e8845e23359 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/PropertyAttributeSourceImpl.java @@ -0,0 +1,238 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Implementation for {@code } mappings + * + * @author Steve Ebersole + */ +class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements SingularAttributeSource { + private final JaxbPropertyElement propertyElement; + private final HibernateTypeSource typeSource; + private final List valueSources; + private final NaturalIdMutability naturalIdMutability; + private final String containingTableName; + + private final AttributeRole attributeRole; + private final AttributePath attributePath; + + PropertyAttributeSourceImpl( + MappingDocument sourceMappingDocument, + AttributeSourceContainer container, + final JaxbPropertyElement propertyElement, + final String logicalTableName, + NaturalIdMutability naturalIdMutability) { + super( sourceMappingDocument ); + this.propertyElement = propertyElement; + this.typeSource = new HibernateTypeSource() { + private final String name = propertyElement.getTypeAttribute() != null + ? propertyElement.getTypeAttribute() + : propertyElement.getType() != null + ? propertyElement.getType().getName() + : null; + private final Map parameters = ( propertyElement.getType() != null ) + ? Helper.extractParameters( propertyElement.getType().getParam() ) + : null; + + @Override + public String getName() { + return name; + } + + @Override + public Map getParameters() { + return parameters; + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + this.containingTableName = logicalTableName; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return propertyElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + // TODO: propertyElement.getPrecision() and getScale() return String, + // but should return int + return Helper.createSizeSourceIfMapped( + propertyElement.getLength(), + propertyElement.getPrecision() == null ? null : Integer.valueOf( propertyElement.getPrecision() ), + propertyElement.getScale() == null ? null : Integer.valueOf( propertyElement.getScale() ) + ); + } + + @Override + public String getFormulaAttribute() { + return propertyElement.getFormulaAttribute(); + } + + @Override + public List getColumn() { + return propertyElement.getColumn(); + } + + @Override + public List getFormula() { + return propertyElement.getFormula(); + } + + @Override + public String getContainingTableName() { + return logicalTableName; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return Helper.getValue( propertyElement.isInsert(), true ); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return Helper.getValue( propertyElement.isUpdate(), true ); + } + } + ); + this.naturalIdMutability = naturalIdMutability; + + this.attributeRole = container.getAttributeRoleBase().append( getName() ); + this.attributePath = container.getAttributePathBase().append( getName() ); + } + + @Override + public String getName() { + return propertyElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return propertyElement.getAccess(); + } + + @Override + public PropertyGeneration getGeneration() { + return PropertyGeneration.parse( propertyElement.getGenerated().value() ); + } + + @Override + public boolean isLazy() { + return Helper.getValue( propertyElement.isLazy(), false ); + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return Helper.getValue( propertyElement.isOptimisticLock(), true ); + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.BASIC; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return Helper.getValue( propertyElement.isInsert(), true ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return Helper.getValue( propertyElement.isUpdate(), true ); + } + + @Override + public boolean areValuesNullableByDefault() { + return ! Helper.getValue( propertyElement.isNotNull(), false ); + } + + @Override + public String getContainingTableName() { + return containingTableName; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Collection getToolingHintSources() { + return propertyElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ResultSetMappingBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ResultSetMappingBinder.java new file mode 100644 index 000000000000..9bfdd384c153 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ResultSetMappingBinder.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbLoadCollectionElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbResultsetElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnJoinElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnScalarElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.type.Type; + +public class ResultSetMappingBinder { + public static ResultSetMappingDefinition buildResultSetMappingDefinitions( + final JaxbResultsetElement element, + final LocalBindingContext bindingContext, + final InFlightMetadataCollector metadataCollector) { + final ResultSetMappingDefinition definition = new ResultSetMappingDefinition( element.getName() ); + int cnt = 0; + for ( final JaxbReturnScalarElement r : element.getReturnScalar() ) { + String column = r.getColumn(); + String typeFromXML = r.getType(); + Type type = StringHelper.isNotEmpty( typeFromXML ) ? metadataCollector.getTypeResolver() + .heuristicType( typeFromXML ) : null; + definition.addQueryReturn( new NativeSQLQueryScalarReturn( column, type ) ); + } + for ( final JaxbReturnElement r : element.getReturn() ) { + definition.addQueryReturn( new ReturnBinder( r, cnt++, bindingContext, metadataCollector ).process() ); + } + for ( final JaxbReturnJoinElement r : element.getReturnJoin() ) { + definition.addQueryReturn( new ReturnJoinBinder( r, cnt++, bindingContext, metadataCollector ).process() ); + } + for ( final JaxbLoadCollectionElement r : element.getLoadCollection() ) { + definition.addQueryReturn( new LoadCollectionBinder( r, cnt++, bindingContext, metadataCollector ).process() ); + } + + return definition; + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ReturnBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ReturnBinder.java new file mode 100644 index 000000000000..472ab152c411 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ReturnBinder.java @@ -0,0 +1,142 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnPropertyElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +/** + * @author Strong Liu + */ +class ReturnBinder extends AbstractReturnBinder { + ReturnBinder( + final JaxbReturnElement element, + final int elementIndex, + final LocalBindingContext context, + final InFlightMetadataCollector metadataCollector) { + super( element, elementIndex, context, metadataCollector ); + } + + @Override + NativeSQLQueryReturn process() { + final String clazz = element.getClazz(); + String entityName = element.getEntityName(); + if ( StringHelper.isEmpty( clazz ) && StringHelper.isEmpty( entityName ) ) { + throw context.makeMappingException( + " must specify either a class or entity-name" + ); + } + entityName = StringHelper.isNotEmpty( entityName ) ? entityName : context.qualifyClassName( clazz ); + final EntityBinding entityBinding = metadataCollector.getEntityBinding( entityName ); + // TODO throw exception here?? + // if ( entityBinding == null ) { + // throw bindingContext.makeMappingException( "Can't locate entitybinding" ); + // } + + final Map propertyResults = new HashMap(); + bindDiscriminatorColumn( propertyResults ); + processReturnProperties( new ReturnPropertiesCallbackImpl2( alias, propertyResults, context ) ); + + return new NativeSQLQueryRootReturn( + alias, entityName, propertyResults, lockMode + ); + } + + + private void bindDiscriminatorColumn(final Map propertyResults) { + final JaxbReturnElement.JaxbReturnDiscriminator discriminator = element.getReturnDiscriminator(); + if ( discriminator != null && StringHelper.isNotEmpty( discriminator.getColumn() ) ) { + String discriminatorColumn = StringHelper.unquote( discriminator.getColumn() ); + propertyResults.put( "class", new String[] { discriminatorColumn } ); + } + } + + private static class ReturnPropertiesCallbackImpl2 implements ReturnPropertiesCallback { + private final LocalBindingContext bindingContext; + private final String alias; + private final Map propertyResults; + + private ReturnPropertiesCallbackImpl2( + final String alias, final Map propertyResults, + final LocalBindingContext bindingContext) { + this.alias = alias; + this.bindingContext = bindingContext; + this.propertyResults = propertyResults; + } + + @Override + public void process(final JaxbReturnPropertyElement propertyElement) { + final String name = propertyElement.getName(); + if ( "class".equals( name ) ) { + throw bindingContext.makeMappingException( + "class is not a valid property name to use in a , use instead" + ); + } + if ( propertyResults.containsKey( name ) ) { + throw bindingContext.makeMappingException( + "duplicate return-property for property " + name + " on alias " + alias + ); + } + final List returnColumnNames = getResultColumns( propertyElement, bindingContext ); + + if ( returnColumnNames.isEmpty() ) { + throw bindingContext.makeMappingException( + "return-property for alias " + alias + " must specify at least one column or return-column name" + ); + } + + propertyResults.put( name, returnColumnNames.toArray( new String[returnColumnNames.size()] ) ); + } + + private static List getResultColumns( + final JaxbReturnPropertyElement propertyresult, final LocalBindingContext context) { + List allResultColumns = new ArrayList(); + if ( propertyresult.getColumn() != null ) { + String column = context.getMetadataCollector() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( propertyresult.getColumn() ); + allResultColumns.add( column ); + } + for ( JaxbReturnPropertyElement.JaxbReturnColumn returnColumn : propertyresult.getReturnColumn() ) { + if ( returnColumn.getName() != null ) { + String column = context.getMetadataCollector() + .getObjectNameNormalizer() + .normalizeIdentifierQuoting( returnColumn.getName() ); + + allResultColumns.add( column ); + } + } + return allResultColumns; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ReturnJoinBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ReturnJoinBinder.java new file mode 100644 index 000000000000..fc5cc57d1836 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/ReturnJoinBinder.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnJoinElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; + +/** + * @author Strong Liu + */ +class ReturnJoinBinder extends AbstractReturnBinder { + ReturnJoinBinder( + final JaxbReturnJoinElement element, + final int elementIndex, + final LocalBindingContext context, + final InFlightMetadataCollector metadataCollector) { + super( element, elementIndex, context, metadataCollector ); + } + + @Override + NativeSQLQueryReturn process() { + final String roleAttribute = element.getProperty(); + int dot = roleAttribute.lastIndexOf( '.' ); + if ( dot == -1 ) { + throw context.makeMappingException( + "Role attribute for sql query return " + "[alias=" + alias + "] not formatted correctly " + "{owningAlias.propertyName}" + ); + } + final String roleOwnerAlias = roleAttribute.substring( 0, dot ); + final String roleProperty = roleAttribute.substring( dot + 1 ); + final Map propertyResults = new HashMap(); + processReturnProperties( new ReturnPropertiesCallbackImpl( alias, propertyResults, context ) ); + return new NativeSQLQueryJoinReturn( + alias, roleOwnerAlias, roleProperty, propertyResults, lockMode + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/RootEntitySourceImpl.java new file mode 100644 index 000000000000..b39f699a73d1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/RootEntitySourceImpl.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbNaturalIdElement; +import org.hibernate.metamodel.source.spi.AttributeSource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.spi.NaturalIdMutability; + +/** + * @author Steve Ebersole + * @author Gail Badner + */ +public class RootEntitySourceImpl extends AbstractEntitySourceImpl { + private final TableSpecificationSource primaryTable; + + protected RootEntitySourceImpl( + MappingDocument sourceMappingDocument, + JaxbClassElement entityElement) { + super( sourceMappingDocument, entityElement ); + this.primaryTable = Helper.createTableSource( sourceMappingDocument(), entityElement, this ); + afterInstantiation(); + } + + @Override + protected List buildAttributeSources(List attributeSources) { + final JaxbNaturalIdElement naturalId = entityElement().getNaturalId(); + if ( naturalId != null ) { + final NaturalIdMutability naturalIdMutability = naturalId.isMutable() + ? NaturalIdMutability.MUTABLE + : NaturalIdMutability.IMMUTABLE; + processPropertyAttributes( attributeSources, naturalId.getProperty(), null, naturalIdMutability ); + processManyToOneAttributes( attributeSources, naturalId.getManyToOne(), null, naturalIdMutability ); + processComponentAttributes( attributeSources, naturalId.getComponent(), null, naturalIdMutability ); + processDynamicComponentAttributes( + attributeSources, + naturalId.getDynamicComponent(), + null, + naturalIdMutability + ); + processAnyAttributes( attributeSources, naturalId.getAny(), null, naturalIdMutability ); + } + return super.buildAttributeSources( attributeSources ); + } + + @Override + protected JaxbClassElement entityElement() { + return (JaxbClassElement) super.entityElement(); + } + + @Override + public TableSpecificationSource getPrimaryTable() { + return primaryTable; + } + + @Override + public String getDiscriminatorMatchValue() { + return entityElement().getDiscriminatorValue(); + } + + @Override + public IdentifiableTypeSource getSuperType() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SecondaryTableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SecondaryTableSourceImpl.java new file mode 100644 index 000000000000..05de26066f26 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SecondaryTableSourceImpl.java @@ -0,0 +1,199 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFetchStyleAttribute; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbJoinElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOnDeleteAttribute; +import org.hibernate.metamodel.source.spi.ColumnSource; +import org.hibernate.metamodel.source.spi.InLineViewSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SecondaryTableSource; +import org.hibernate.metamodel.source.spi.TableSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +class SecondaryTableSourceImpl extends AbstractHbmSourceNode implements SecondaryTableSource { + private final JaxbJoinElement joinElement; + private final TableSpecificationSource joinTable; + private final List columnSources; + private final JoinColumnResolutionDelegate fkJoinColumnResolutionDelegate; + + @SuppressWarnings("unchecked") + public SecondaryTableSourceImpl( + MappingDocument sourceMappingDocument, + final JaxbJoinElement joinElement, + Helper.InLineViewNameInferrer inLineViewNameInferrer) { + super( sourceMappingDocument ); + this.joinElement = joinElement; + this.joinTable = Helper.createTableSource( sourceMappingDocument(), joinElement, inLineViewNameInferrer ); + + // the cast is ok here because the adapter should never be returning formulas since the schema does not allow it + this.columnSources = extractColumnSources(); + + fkJoinColumnResolutionDelegate = joinElement.getKey().getPropertyRef() == null + ? null + : new JoinColumnResolutionDelegateImpl( joinElement ); + } + + private List extractColumnSources() { + final List columnSources = new ArrayList(); + final List valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getContainingTableName() { + return joinElement.getTable(); + } + + @Override + public String getColumnAttribute() { + return joinElement.getKey().getColumnAttribute(); + } + + @Override + public List getColumn() { + return joinElement.getKey().getColumn(); + } + + @Override + public boolean isForceNotNull() { + return true; + } + } + ); + for ( RelationalValueSource valueSource : valueSources ) { + columnSources.add( (ColumnSource) valueSource ); + } + return columnSources; + } + + @Override + public TableSpecificationSource getTableSource() { + return joinTable; + } + + @Override + public List getPrimaryKeyColumnSources() { + return columnSources; + } + + @Override + public String getComment() { + return joinElement.getComment(); + } + + @Override + public FetchStyle getFetchStyle() { + return joinElement.getFetch() == JaxbFetchStyleAttribute.JOIN ? + FetchStyle.JOIN : + FetchStyle.SELECT; + } + + @Override + public boolean isInverse() { + return joinElement.isInverse(); + } + + @Override + public boolean isOptional() { + return joinElement.isOptional(); + } + + @Override + public boolean isCascadeDeleteEnabled() { + return joinElement.getKey().getOnDelete() == JaxbOnDeleteAttribute.CASCADE; + } + + @Override + public String getExplicitForeignKeyName() { + return joinElement.getKey().getForeignKey(); + } + + @Override + public boolean createForeignKeyConstraint() { + // TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)? + return true; + } + + @Override + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { + return fkJoinColumnResolutionDelegate; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return Helper.buildCustomSql( joinElement.getSqlInsert() ); + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return Helper.buildCustomSql( joinElement.getSqlUpdate() ); + } + + @Override + public CustomSQL getCustomSqlDelete() { + return Helper.buildCustomSql( joinElement.getSqlDelete() ); + } + + + public String getLogicalTableNameForContainedColumns() { + return TableSource.class.isInstance( joinTable ) + ? ( (TableSource) joinTable ).getExplicitTableName() + : ( (InLineViewSource) joinTable ).getLogicalName(); + } + + private static class JoinColumnResolutionDelegateImpl implements JoinColumnResolutionDelegate { + private final JaxbJoinElement joinElement; + + public JoinColumnResolutionDelegateImpl(JaxbJoinElement joinElement) { + this.joinElement = joinElement; + } + + @Override + public List getJoinColumns(JoinColumnResolutionContext context) { + return context.resolveRelationalValuesForAttribute( getReferencedAttributeName() ); + } + + @Override + public String getReferencedAttributeName() { + return joinElement.getKey().getPropertyRef(); + } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( joinElement.getKey().getPropertyRef() ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SetSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SetSourceImpl.java new file mode 100644 index 000000000000..ac33fcfd204a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SetSourceImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSetElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.Orderable; +import org.hibernate.metamodel.source.spi.Sortable; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * @author Steve Ebersole + */ +public class SetSourceImpl extends AbstractPluralAttributeSourceImpl implements Orderable, Sortable { + public SetSourceImpl( + MappingDocument sourceMappingDocument, + JaxbSetElement setElement, + AttributeSourceContainer container) { + super( sourceMappingDocument, setElement, container ); + } + + @Override + public JaxbSetElement getPluralAttributeElement() { + return (JaxbSetElement) super.getPluralAttributeElement(); + } + + @Override + public PluralAttributeNature getNature() { + return PluralAttributeNature.SET; + } + + @Override + public boolean isSorted() { + String comparatorName = getComparatorName(); + return StringHelper.isNotEmpty( comparatorName ) + && !comparatorName.equals("unsorted"); + } + + @Override + public String getComparatorName() { + return getPluralAttributeElement().getSort(); + } + + @Override + public boolean isOrdered() { + return StringHelper.isNotEmpty( getOrder() ); + } + + @Override + public String getOrder() { + return getPluralAttributeElement().getOrderBy(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SingularIdentifierAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SingularIdentifierAttributeSourceImpl.java new file mode 100644 index 000000000000..b6db4cf4f034 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SingularIdentifierAttributeSourceImpl.java @@ -0,0 +1,221 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIdElement; +import org.hibernate.metamodel.source.spi.AttributeSourceContainer; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.SizeSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Implementation for {@code } mappings + * + * @author Steve Ebersole + */ +class SingularIdentifierAttributeSourceImpl + extends AbstractHbmSourceNode + implements SingularAttributeSource { + + private final JaxbIdElement idElement; + private final HibernateTypeSource typeSource; + private final List valueSources; + + private final AttributeRole attributeRole; + private final AttributePath attributePath; + + public SingularIdentifierAttributeSourceImpl( + MappingDocument mappingDocument, + AttributeSourceContainer container, + final JaxbIdElement idElement) { + super( mappingDocument ); + this.idElement = idElement; + this.typeSource = new HibernateTypeSource() { + private final String name = idElement.getTypeAttribute() != null + ? idElement.getTypeAttribute() + : idElement.getType() != null + ? idElement.getType().getName() + : null; + private final Map parameters = ( idElement.getType() != null ) + ? Helper.extractParameters( idElement.getType().getParam() ) + : null; + + @Override + public String getName() { + return name; + } + + @Override + public Map getParameters() { + return parameters; + } + + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return idElement.getColumnAttribute(); + } + + @Override + public SizeSource getSizeSource() { + return Helper.createSizeSourceIfMapped( + idElement.getLength(), + null, + null + ); + } + + @Override + public List getColumn() { + return idElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isForceNotNull() { + return true; + } + } + ); + + this.attributeRole = container.getAttributeRoleBase().append( getName() ); + this.attributePath = container.getAttributePathBase().append( getName() ); + } + + @Override + public String getName() { + return idElement.getName() == null + ? "id" + : idElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return idElement.getAccess(); + } + + @Override + public PropertyGeneration getGeneration() { + return PropertyGeneration.INSERT; + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return NaturalIdMutability.NOT_NATURAL_ID; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.BASIC; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return false; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Collection getToolingHintSources() { + return idElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SizeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SizeSourceImpl.java new file mode 100644 index 000000000000..93073af75116 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SizeSourceImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.spi.SizeSource; + +/** + * @author Gail Badner + */ +public class SizeSourceImpl implements SizeSource { + + private final Integer length; + private final Integer precision; + private final Integer scale; + + public SizeSourceImpl(Integer precision, Integer scale, Integer length) { + this.precision = precision; + this.scale = scale; + this.length = length; + } + + public boolean isLengthDefined() { + return length != null; + } + + public int getLength() { + if ( length == null ) { + throw new UnsupportedOperationException( "length is undefined." ); + } + return length; + } + + public boolean isPrecisionDefined() { + return precision != null; + } + + public int getPrecision() { + if ( precision == null ) { + throw new UnsupportedOperationException( "precision is undefined." ); + } + return precision; + } + + public boolean isScaleDefined() { + return scale != null; + } + + public int getScale() { + if ( scale == null ) { + throw new UnsupportedOperationException( "scale is undefined." ); + } + return scale; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SubclassEntitySourceImpl.java new file mode 100644 index 000000000000..a3903c344238 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/SubclassEntitySourceImpl.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSubclassElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.TableInformationSource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.SubclassEntitySource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; + +/** + * @author Steve Ebersole + */ +public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implements SubclassEntitySource { + private final EntitySource container; + private final TableSpecificationSource primaryTable; + protected SubclassEntitySourceImpl( + MappingDocument sourceMappingDocument, + EntityElement entityElement, + EntitySource container) { + super( sourceMappingDocument, entityElement ); + this.container = container; + this.primaryTable = TableInformationSource.class.isInstance( entityElement ) + ? Helper.createTableSource( sourceMappingDocument(), (TableInformationSource) entityElement, this ) + : null; + + + afterInstantiation(); + } + + @Override + public TableSpecificationSource getPrimaryTable() { + return primaryTable; + } + + @Override + public String getDiscriminatorMatchValue() { + return JaxbSubclassElement.class.isInstance( entityElement() ) + ? ( (JaxbSubclassElement) entityElement() ).getDiscriminatorValue() + : null; + } + + @Override + public IdentifiableTypeSource getSuperType() { + return container; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TableSourceImpl.java new file mode 100644 index 000000000000..f698415836ef --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TableSourceImpl.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import org.hibernate.metamodel.source.spi.TableSource; + +/** + * @author Steve Ebersole + */ +public class TableSourceImpl + extends AbstractHbmSourceNode + implements TableSource { + private final String schema; + private final String catalog; + private final String tableName; + private final String rowId; + + TableSourceImpl( + MappingDocument mappingDocument, + String schema, + String catalog, + String tableName) { + this( mappingDocument, schema, catalog, tableName, null ); + } + + TableSourceImpl( + MappingDocument mappingDocument, + String schema, + String catalog, + String tableName, + String rowId) { + super( mappingDocument ); + this.schema = schema; + this.catalog = catalog; + this.tableName = tableName; + this.rowId = rowId; + } + + @Override + public String getExplicitSchemaName() { + return schema; + } + + @Override + public String getExplicitCatalogName() { + return catalog; + } + + @Override + public String getExplicitTableName() { + return tableName; + } + + @Override + public String getRowId() { + return rowId; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TimestampAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TimestampAttributeSourceImpl.java new file mode 100644 index 000000000000..fbdbd0ed9d83 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TimestampAttributeSourceImpl.java @@ -0,0 +1,211 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTimestampElement; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.source.spi.VersionAttributeSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Implementation for {@code } mappings + * + * @author Steve Ebersole + */ +class TimestampAttributeSourceImpl + extends AbstractHbmSourceNode + implements VersionAttributeSource { + private final JaxbTimestampElement timestampElement; + private final List valueSources; + + private final AttributePath attributePath; + private final AttributeRole attributeRole; + + TimestampAttributeSourceImpl( + MappingDocument mappingDocument, + RootEntitySourceImpl rootEntitySource, + final JaxbTimestampElement timestampElement) { + super( mappingDocument ); + this.timestampElement = timestampElement; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return timestampElement.getColumnAttribute(); + } + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return true; + } + } + ); + + this.attributePath = rootEntitySource.getAttributePathBase().append( getName() ); + this.attributeRole = rootEntitySource.getAttributeRoleBase().append( getName() ); + } + + private final HibernateTypeSource typeSource = new HibernateTypeSource() { + @Override + public String getName() { + return "db".equals( timestampElement.getSource() ) ? "dbtimestamp" : "timestamp"; + } + + @Override + public Map getParameters() { + return null; + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + + @Override + public String getName() { + return timestampElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return timestampElement.getAccess(); + } + + private ValueHolder propertyGenerationValue = new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public PropertyGeneration initialize() { + final PropertyGeneration propertyGeneration = timestampElement.getGenerated() == null + ? PropertyGeneration.NEVER + : PropertyGeneration.parse( timestampElement.getGenerated().value() ); + if ( propertyGeneration == PropertyGeneration.INSERT ) { + throw makeMappingException( "'generated' attribute cannot be 'insert' for versioning property" ); + } + return propertyGeneration; + } + } + ); + + @Override + public PropertyGeneration getGeneration() { + return propertyGenerationValue.getValue(); + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return NaturalIdMutability.NOT_NATURAL_ID; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.BASIC; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public String getContainingTableName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Collection getToolingHintSources() { + return timestampElement.getMeta(); + } + + @Override + public String getUnsavedValue() { + return timestampElement.getUnsavedValue().value(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TypeDescriptorSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TypeDescriptorSourceImpl.java new file mode 100644 index 000000000000..68a5fc00550a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/TypeDescriptorSourceImpl.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Map; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTypedefElement; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; + +/** + * @author Steve Ebersole + */ +public class TypeDescriptorSourceImpl implements TypeDescriptorSource { + private static final String[] NO_REGISTRATION_KEYS = new String[0]; + + private final String name; + private final String implementationClassName; + private final Map params; + + public TypeDescriptorSourceImpl(JaxbTypedefElement typeDefElement) { + this.name = typeDefElement.getName(); + this.implementationClassName = typeDefElement.getClazz(); + this.params = Helper.extractParameters( typeDefElement.getParam() ); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getTypeImplementationClassName() { + return implementationClassName; + } + + @Override + public String[] getRegistrationKeys() { + return NO_REGISTRATION_KEYS; + } + + @Override + public Map getParameters() { + return params; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/UniqueConstraintSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/UniqueConstraintSourceImpl.java new file mode 100644 index 000000000000..c9e1da8f45f4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/UniqueConstraintSourceImpl.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.List; + +import org.hibernate.metamodel.source.spi.UniqueConstraintSource; + +/** + * @author Hardy Ferentschik + */ +class UniqueConstraintSourceImpl extends AbstractConstraintSource implements UniqueConstraintSource { + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames, List orderings) { +// super( name, tableName, columnNames, orderings ); + super( name, tableName ); + } + + public UniqueConstraintSourceImpl(String name, String tableName, List columnNames) { +// super( name, tableName, columnNames, Collections.EMPTY_LIST ); + super( name, tableName ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "UniqueConstraintSourceImpl" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", tableName='" ).append( tableName ).append( '\'' ); + sb.append( ", columnNames=" ).append( columnNames ); + sb.append( ", orderings=" ).append( orderings ); + sb.append( '}' ); + return sb.toString(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/VersionAttributeSourceImpl.java new file mode 100644 index 000000000000..1223d686bb72 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/VersionAttributeSourceImpl.java @@ -0,0 +1,217 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.hbm; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.util.ValueHolder; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbVersionElement; +import org.hibernate.metamodel.source.spi.HibernateTypeSource; +import org.hibernate.metamodel.source.spi.RelationalValueSource; +import org.hibernate.metamodel.source.spi.ToolingHintSource; +import org.hibernate.metamodel.source.spi.VersionAttributeSource; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + + +/** + * Implementation for {@code } mappings + * + * @author Steve Ebersole + */ +class VersionAttributeSourceImpl + extends AbstractHbmSourceNode + implements VersionAttributeSource { + private final JaxbVersionElement versionElement; + private final List valueSources; + + private final AttributePath attributePath; + private final AttributeRole attributeRole; + + VersionAttributeSourceImpl( + MappingDocument mappingDocument, + RootEntitySourceImpl rootEntitySource, + final JaxbVersionElement versionElement) { + super( mappingDocument ); + this.versionElement = versionElement; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return versionElement.getColumnAttribute(); + } + @Override + public List getColumn() { + return versionElement.getColumn(); + } + + @Override + public boolean isIncludedInInsertByDefault() { + return Helper.getValue( versionElement.isInsert(), true ); + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return true; + } + } + ); + + this.attributePath = rootEntitySource.getAttributePathBase().append( getName() ); + this.attributeRole = rootEntitySource.getAttributeRoleBase().append( getName() ); + } + + private final HibernateTypeSource typeSource = new HibernateTypeSource() { + @Override + public String getName() { + return versionElement.getType() == null ? "integer" : versionElement.getType(); + } + + @Override + public Map getParameters() { + return null; + } + @Override + public JavaTypeDescriptor getJavaType() { + return null; + } + }; + + @Override + public String getUnsavedValue() { + return versionElement.getUnsavedValue().value(); + } + + @Override + public String getName() { + return versionElement.getName(); + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public HibernateTypeSource getTypeInformation() { + return typeSource; + } + + @Override + public String getPropertyAccessorName() { + return versionElement.getAccess(); + } + + private ValueHolder propertyGenerationValue = new ValueHolder( + new ValueHolder.DeferredInitializer() { + @Override + public PropertyGeneration initialize() { + final PropertyGeneration propertyGeneration = versionElement.getGenerated() == null + ? PropertyGeneration.NEVER + : PropertyGeneration.parse( versionElement.getGenerated().value() ); + if ( propertyGeneration == PropertyGeneration.INSERT ) { + throw makeMappingException( "'generated' attribute cannot be 'insert' for versioning property" ); + } + return propertyGeneration; + } + } + ); + @Override + public PropertyGeneration getGeneration() { + return propertyGenerationValue.getValue(); + } + + @Override + public boolean isLazy() { + return false; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return NaturalIdMutability.NOT_NATURAL_ID; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public SingularAttributeNature getSingularAttributeNature() { + return SingularAttributeNature.BASIC; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return Helper.getValue( versionElement.isInsert(), true ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return true; + } + + @Override + public String getContainingTableName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public Collection getToolingHintSources() { + return versionElement.getMeta(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/AbstractQueryElementContentsParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/AbstractQueryElementContentsParser.java new file mode 100644 index 000000000000..c34e92681ffa --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/AbstractQueryElementContentsParser.java @@ -0,0 +1,228 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm.parser; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.CacheMode; +import org.hibernate.FlushMode; +import org.hibernate.MappingException; +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCacheModeAttribute; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbFlushModeAttribute; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbQueryParamElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSqlQueryElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.QuerySourceElement; + +/** + * @author Brett Meyer + */ +abstract class AbstractQueryElementContentsParser { + + // TODO: Hate the use of QuerySourceElement -- remove/refactor. + + public void parse( NamedQueryDefinitionBuilder builder, + final JaxbQueryElement queryElement ) { + + QuerySourceElement element = new QuerySourceElement() { + @Override + public List getContent() { + return queryElement.getContent(); + } + + @Override + public JaxbCacheModeAttribute getCacheMode() { + return queryElement.getCacheMode(); + } + + @Override + public String getCacheRegion() { + return queryElement.getCacheRegion(); + } + + @Override + public boolean isCacheable() { + return queryElement.isCacheable(); + } + + @Override + public String getComment() { + return queryElement.getComment(); + } + + @Override + public Integer getFetchSize() { + return queryElement.getFetchSize(); + } + + @Override + public JaxbFlushModeAttribute getFlushMode() { + return queryElement.getFlushMode(); + } + + @Override + public String getName() { + return queryElement.getName(); + } + + @Override + public boolean isReadOnly() { + return queryElement.isReadOnly(); + } + + @Override + public Integer getTimeout() { + return queryElement.getTimeout(); + } + }; + + parse( builder, element ); + } + + public void parse( NamedQueryDefinitionBuilder builder, + final JaxbSqlQueryElement queryElement ) { + + QuerySourceElement element = new QuerySourceElement() { + @Override + public List getContent() { + return queryElement.getContent(); + } + + @Override + public JaxbCacheModeAttribute getCacheMode() { + return queryElement.getCacheMode(); + } + + @Override + public String getCacheRegion() { + return queryElement.getCacheRegion(); + } + + @Override + public boolean isCacheable() { + return queryElement.isCacheable(); + } + + @Override + public String getComment() { + return queryElement.getComment(); + } + + @Override + public Integer getFetchSize() { + return queryElement.getFetchSize(); + } + + @Override + public JaxbFlushModeAttribute getFlushMode() { + return queryElement.getFlushMode(); + } + + @Override + public String getName() { + return queryElement.getName(); + } + + @Override + public boolean isReadOnly() { + return queryElement.isReadOnly(); + } + + @Override + public Integer getTimeout() { + return queryElement.getTimeout(); + } + }; + + parse( builder, element ); + } + + private void parse( NamedQueryDefinitionBuilder builder, + QuerySourceElement queryElement ) { + final String queryName = queryElement.getName(); + final boolean cacheable = queryElement.isCacheable(); + final String region = queryElement.getCacheRegion(); + final Integer timeout = queryElement.getTimeout(); + final Integer fetchSize = queryElement.getFetchSize(); + final boolean readonly = queryElement.isReadOnly(); + final String comment = queryElement.getComment(); + final CacheMode cacheMode = queryElement.getCacheMode() == null + ? null : CacheMode.valueOf( queryElement + .getCacheMode().value().toUpperCase() ); + final FlushMode flushMode = queryElement.getFlushMode() == null + ? null : FlushMode.valueOf( queryElement + .getFlushMode().value().toUpperCase() ); + + builder.setName( queryName ).setCacheable( cacheable ) + .setCacheRegion( region ).setTimeout( timeout ) + .setFetchSize( fetchSize ).setFlushMode( flushMode ) + .setCacheMode( cacheMode ).setReadOnly( readonly ) + .setComment( comment ); + + final List list = queryElement.getContent(); + parse( queryName, list, builder ); + } + + private void parse(String queryName, List contents, + NamedQueryDefinitionBuilder builder) { + final Map queryParam = new HashMap(); + String query = ""; + boolean isQueryDefined = false; + for ( Serializable obj : contents ) { + if ( obj == null ) { + continue; + } + else if ( JaxbQueryParamElement.class.isInstance( obj ) ) { + JaxbQueryParamElement element + = JaxbQueryParamElement.class.cast( obj ); + queryParam.put( element.getName(), element.getType() ); + } + else if ( String.class.isInstance( obj ) ) { + if ( !isQueryDefined ) { + if ( StringHelper.isNotEmpty( obj.toString().trim() ) ) { + query = obj.toString().trim(); + isQueryDefined = true; + } + + } + else { + throw new MappingException( + "Duplicate query string is defined in Named query[+" + + queryName + "]" ); + } + } + parseExtra( queryName, obj, builder ); + } + builder.setParameterTypes( queryParam ); + if ( StringHelper.isEmpty( query ) ) { + throw new MappingException( + "Named query[" + queryName+ "] has no query string defined"); + } + builder.setQuery( query ); + } + + protected abstract void parseExtra(String queryName, Serializable obj, NamedQueryDefinitionBuilder builder); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/BasicQueryElementContentParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/BasicQueryElementContentParser.java new file mode 100644 index 000000000000..5d9714fd4d97 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/BasicQueryElementContentParser.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm.parser; + +import java.io.Serializable; + +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; + +/** + * @author Brett Meyer + */ +public class BasicQueryElementContentParser extends AbstractQueryElementContentsParser { + + @Override + protected void parseExtra(String queryName, Serializable obj, + NamedQueryDefinitionBuilder builder) { + // do nothing + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/SQLQueryElementContentParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/SQLQueryElementContentParser.java new file mode 100644 index 000000000000..cc8b531b4b1c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/hbm/parser/SQLQueryElementContentParser.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.metamodel.source.internal.hbm.parser; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; + +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; +import org.hibernate.metamodel.source.internal.hbm.ResultSetMappingBinder; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbLoadCollectionElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbResultsetElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnJoinElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbReturnScalarElement; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbSynchronizeElement; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.LocalBindingContext; + +/** + * @author Brett Meyer + * @author String Liu + */ +public class SQLQueryElementContentParser extends AbstractQueryElementContentsParser { + private final List synchronizedTables = new ArrayList(); + private final List loadCollectionElements = new ArrayList(); + private final List returnScalarElements = new ArrayList(); + private final List returnElements = new ArrayList(); + private final List returnJoinElements = new ArrayList(); + + @Override + protected void parseExtra( String queryName, Serializable obj, + NamedQueryDefinitionBuilder builder ) { + if ( !JAXBElement.class.isInstance( obj ) ) { + return; + } + JAXBElement jaxbElement = JAXBElement.class.cast( obj ); + Class targetType = jaxbElement.getDeclaredType(); + Object value = jaxbElement.getValue(); + if ( JaxbSynchronizeElement.class == targetType ) { + JaxbSynchronizeElement element = JaxbSynchronizeElement.class.cast( value ); + synchronizedTables.add( element.getTable() ); + } + else if ( JaxbLoadCollectionElement.class == targetType ) { + loadCollectionElements.add( JaxbLoadCollectionElement.class.cast( value ) ); + } + else if ( JaxbReturnScalarElement.class == targetType ) { + returnScalarElements.add( JaxbReturnScalarElement.class.cast( value ) ); + } + else if ( JaxbReturnElement.class == targetType ) { + returnElements.add( JaxbReturnElement.class.cast( value ) ); + } + else if ( JaxbReturnJoinElement.class == targetType ) { + returnJoinElements.add( JaxbReturnJoinElement.class.cast( value ) ); + } + } + + public NamedSQLQueryDefinition buildQueryReturns( + final String queryName, + final NamedSQLQueryDefinitionBuilder builder, + final LocalBindingContext bindingContext, + final InFlightMetadataCollector metadataCollector) { + + final JaxbResultsetElement mockedResultSet = new JaxbResultsetElement() { + @Override + public String getName() { + return queryName; + } + @Override + public List getLoadCollection() { + return loadCollectionElements; + } + + @Override + public List getReturn() { + return returnElements; + } + + @Override + public List getReturnJoin() { + return returnJoinElements; + } + + @Override + public List getReturnScalar() { + return returnScalarElements; + } + }; + + final ResultSetMappingDefinition definition = ResultSetMappingBinder.buildResultSetMappingDefinitions( mockedResultSet,bindingContext, metadataCollector ); + + return builder.setQueryReturns( definition.getQueryReturns() ) + .setQuerySpaces( synchronizedTables ) + .createNamedQueryDefinition(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractAttributesBuilder.java new file mode 100644 index 000000000000..acc267622c59 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractAttributesBuilder.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.AttributesContainer; +import org.hibernate.metamodel.source.internal.jaxb.JaxbBasic; +import org.hibernate.metamodel.source.internal.jaxb.JaxbElementCollection; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbedded; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddedId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbManyToMany; +import org.hibernate.metamodel.source.internal.jaxb.JaxbManyToOne; +import org.hibernate.metamodel.source.internal.jaxb.JaxbOneToMany; +import org.hibernate.metamodel.source.internal.jaxb.JaxbOneToOne; +import org.hibernate.metamodel.source.internal.jaxb.JaxbTransient; +import org.hibernate.metamodel.source.internal.jaxb.JaxbVersion; + +import org.jboss.jandex.ClassInfo; + +/** + * Abstract parse to handle {@link org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes JaxbAttributes} + * and {@link org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddableAttributes JaxbEmbeddableAttributes}. + * + * It would be really helpful if these two classes can implement an interface with those abstract methods in this class. + * + * @author Strong Liu + */ +public abstract class AbstractAttributesBuilder { + + private ClassInfo classInfo; + private EntityMappingsMocker.Default defaults; + private IndexBuilder indexBuilder; + + AbstractAttributesBuilder(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults) { + this.indexBuilder = indexBuilder; + this.classInfo = classInfo; + this.defaults = defaults; + } + + final void parse() { + for ( JaxbId id : getId() ) { + new IdMocker( indexBuilder, classInfo, defaults, id ).process(); + } + for ( JaxbTransient transientObj : getAttributesContainer().getTransient() ) { + new TransientMocker( indexBuilder, classInfo, defaults, transientObj ).process(); + } + for ( JaxbVersion version : getVersion() ) { + new VersionMocker( indexBuilder, classInfo, defaults, version ).process(); + } + + for ( JaxbBasic basic : getAttributesContainer().getBasic() ) { + new BasicMocker( indexBuilder, classInfo, defaults, basic ).process(); + } + for ( JaxbElementCollection elementCollection : getAttributesContainer().getElementCollection() ) { + new ElementCollectionMocker( + indexBuilder, classInfo, defaults, elementCollection + ).process(); + } + for ( JaxbEmbedded embedded : getAttributesContainer().getEmbedded() ) { + new EmbeddedMocker( indexBuilder, classInfo, defaults, embedded ).process(); + } + for ( JaxbManyToMany manyToMany : getAttributesContainer().getManyToMany() ) { + new ManyToManyMocker( indexBuilder, classInfo, defaults, manyToMany ).process(); + } + + for ( JaxbManyToOne manyToOne : getAttributesContainer().getManyToOne() ) { + new ManyToOneMocker( indexBuilder, classInfo, defaults, manyToOne ).process(); + } + for ( JaxbOneToMany oneToMany : getAttributesContainer().getOneToMany() ) { + new OneToManyMocker( + indexBuilder, classInfo, defaults, oneToMany + ).process(); + } + for ( JaxbOneToOne oneToOne : getAttributesContainer().getOneToOne() ) { + new OneToOneMocker( indexBuilder, classInfo, defaults, oneToOne ).process(); + } + if ( getEmbeddedId() != null ) { + new EmbeddedIdMocker( + indexBuilder, classInfo, defaults, getEmbeddedId() + ).process(); + } + } + + abstract List getId(); + abstract List getVersion(); + abstract JaxbEmbeddedId getEmbeddedId(); + abstract protected AttributesContainer getAttributesContainer(); +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractEntityObjectMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractEntityObjectMocker.java new file mode 100644 index 000000000000..6fa0cbbdb71b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractEntityObjectMocker.java @@ -0,0 +1,175 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import javax.persistence.AccessType; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners; +import org.hibernate.metamodel.source.internal.jaxb.JaxbIdClass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostLoad; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostPersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostUpdate; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPrePersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreUpdate; +import org.hibernate.metamodel.source.internal.jaxb.ManagedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class AbstractEntityObjectMocker extends AnnotationMocker { + private ListenerMocker listenerparse; + protected AbstractAttributesBuilder attributesBuilder; + protected ClassInfo classInfo; + + AbstractEntityObjectMocker(IndexBuilder indexBuilder, EntityMappingsMocker.Default defaults) { + super( indexBuilder, defaults ); + } + + private boolean isPreProcessCalled = false; + + /** + * Pre-process Entity Objects to find the default {@link javax.persistence.Access} for later attributes processing. + */ + public final void preProcess() { + DefaultConfigurationHelper.INSTANCE.applyDefaults( getEntityElement(), getDefaults() ); + classInfo = indexBuilder.createClassInfo( getEntityElement().getClazz() ); + DotName classDotName = classInfo.name(); + if ( getEntityElement().isMetadataComplete() != null && getEntityElement().isMetadataComplete() ) { + indexBuilder.metadataComplete( classDotName ); + } + parseAccessType( getEntityElement().getAccess(), getTarget() ); + isPreProcessCalled = true; + } + + public final void process() { + if ( !isPreProcessCalled ) { + throw new AssertionFailure( "preProcess should be called before process" ); + } + if ( getEntityElement().getAccess() == null ) { + AccessType accessType = AccessHelper.getEntityAccess( getTargetName(), indexBuilder ); + if ( accessType == null ) { + accessType = getDefaults().getAccess(); + } + parseAccessType( accessType, getTarget() ); + } + processExtra(); + if ( isExcludeDefaultListeners() ) { + create( EXCLUDE_DEFAULT_LISTENERS ); + } + if ( isExcludeSuperclassListeners() ) { + create( EXCLUDE_SUPERCLASS_LISTENERS ); + } + parseIdClass( getIdClass() ); + + if ( getAttributes() != null ) { + getAttributesBuilder().parse(); + + } + if ( getEntityListeners() != null ) { + getListenerparse().parse( getEntityListeners() ); + } + getListenerparse().parse( getPrePersist(), PRE_PERSIST ); + getListenerparse().parse( getPreRemove(), PRE_REMOVE ); + getListenerparse().parse( getPreUpdate(), PRE_UPDATE ); + getListenerparse().parse( getPostPersist(), POST_PERSIST ); + getListenerparse().parse( getPostUpdate(), POST_UPDATE ); + getListenerparse().parse( getPostRemove(), POST_REMOVE ); + getListenerparse().parse( getPostLoad(), POST_LOAD ); + + indexBuilder.finishEntityObject( getTargetName(), getDefaults() ); + } + + abstract protected ManagedType getEntityElement(); + abstract protected void processExtra(); + abstract protected boolean isExcludeDefaultListeners(); + + abstract protected boolean isExcludeSuperclassListeners(); + + abstract protected JaxbIdClass getIdClass(); + + abstract protected JaxbEntityListeners getEntityListeners(); + abstract protected JaxbPrePersist getPrePersist(); + + abstract protected JaxbPreRemove getPreRemove(); + + abstract protected JaxbPreUpdate getPreUpdate(); + + abstract protected JaxbPostPersist getPostPersist(); + + abstract protected JaxbPostUpdate getPostUpdate(); + + abstract protected JaxbPostRemove getPostRemove(); + + abstract protected JaxbPostLoad getPostLoad(); + + abstract protected JaxbAttributes getAttributes(); + + protected ListenerMocker getListenerparse() { + if ( listenerparse == null ) { + listenerparse = new ListenerMocker( indexBuilder, classInfo ); + } + return listenerparse; + } + + protected AbstractAttributesBuilder getAttributesBuilder() { + if ( attributesBuilder == null ) { + attributesBuilder = new AttributesBuilder( + indexBuilder, classInfo, getEntityElement().getAccess(), getDefaults(), getAttributes() + ); + } + return attributesBuilder; + } + + protected AnnotationInstance parseIdClass(JaxbIdClass idClass) { + if ( idClass == null ) { + return null; + } + String className = MockHelper.buildSafeClassName( idClass.getClazz(), getDefaults().getPackageName() ); + return create( + ID_CLASS, MockHelper.classValueArray( + "value", className, indexBuilder.getServiceRegistry() + ) + ); + } + + + @Override + protected DotName getTargetName() { + return classInfo.name(); + } + + @Override + protected AnnotationTarget getTarget() { + return classInfo; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractMocker.java new file mode 100644 index 000000000000..622d069ffee5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AbstractMocker.java @@ -0,0 +1,127 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jaxb.JaxbIndex; +import org.hibernate.metamodel.source.internal.jaxb.JaxbUniqueConstraint; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +/** + * Base class for the mock jandex annotations created from orm.xml. + * + * @author Strong Liu + */ +public abstract class AbstractMocker implements JPADotNames { + final protected IndexBuilder indexBuilder; + + AbstractMocker(IndexBuilder indexBuilder) { + this.indexBuilder = indexBuilder; + } + + + abstract protected AnnotationInstance push(AnnotationInstance annotationInstance); + + + protected AnnotationInstance create(DotName name, AnnotationTarget target) { + return create( name, target, MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY ); + } + + + protected AnnotationInstance create(DotName name, AnnotationTarget target, List annotationValueList) { + return create( name, target, MockHelper.toArray( annotationValueList ) ); + } + + protected AnnotationInstance create(DotName name, AnnotationTarget target, AnnotationValue[] annotationValues) { + AnnotationInstance annotationInstance = MockHelper.create( name, target, annotationValues ); + push( annotationInstance ); + return annotationInstance; + + } + + + protected AnnotationInstance parseAccessType(AccessType accessType, AnnotationTarget target) { + if ( accessType == null ) { + return null; + } + return create( ACCESS, target, MockHelper.enumValueArray( "value", ACCESS_TYPE, accessType ) ); + } + + protected void nestedUniqueConstraintList(String name, List constraints, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { + AnnotationValue[] values = new AnnotationValue[constraints.size()]; + for ( int i = 0; i < constraints.size(); i++ ) { + AnnotationInstance annotationInstance = parseUniqueConstraint( constraints.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); + } + MockHelper.addToCollectionIfNotNull( annotationValueList, AnnotationValue.createArrayValue( name, values ) ); + } + + } + + // @UniqueConstraint + protected AnnotationInstance parseUniqueConstraint(JaxbUniqueConstraint uniqueConstraint, AnnotationTarget target) { + if ( uniqueConstraint == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", uniqueConstraint.getName(), annotationValueList ); + MockHelper.stringArrayValue( "columnNames", uniqueConstraint.getColumnName(), annotationValueList ); + return create( UNIQUE_CONSTRAINT, target, annotationValueList ); + } + + protected void nestedIndexConstraintList(String name, List constraints, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { + AnnotationValue[] values = new AnnotationValue[constraints.size()]; + for ( int i = 0; i < constraints.size(); i++ ) { + AnnotationInstance annotationInstance = parseIndexConstraint( constraints.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( "", annotationInstance ); + } + MockHelper.addToCollectionIfNotNull( annotationValueList, AnnotationValue.createArrayValue( name, values ) ); + } + + } + + // @Index + protected AnnotationInstance parseIndexConstraint(JaxbIndex index, AnnotationTarget target) { + if ( index == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", index.getName(), annotationValueList ); + MockHelper.stringValue( "columnList", index.getColumnList(), annotationValueList ); + MockHelper.booleanValue( "unique", index.isUnique(), annotationValueList ); + return create( INDEX, target, annotationValueList ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AccessHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AccessHelper.java new file mode 100644 index 000000000000..379d2cc4bc84 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AccessHelper.java @@ -0,0 +1,219 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.List; +import java.util.Map; +import javax.persistence.AccessType; + +import org.hibernate.AssertionFailure; +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.MethodInfo; +import org.jboss.logging.Logger; + +/** + * @author Strong Liu + */ +public class AccessHelper implements JPADotNames { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + AccessHelper.class.getName() + ); + + static AccessType getAccessFromDefault(IndexBuilder indexBuilder) { + AnnotationInstance annotationInstance = JandexHelper.getSingleAnnotation( + indexBuilder.getAnnotations(), + PseudoJpaDotNames.DEFAULT_ACCESS + ); + if ( annotationInstance == null ) { + return null; + } + else { + return JandexHelper.getEnumValue( + annotationInstance, + "value", + AccessType.class, + indexBuilder.getServiceRegistry().getService( ClassLoaderService.class ) + ); + } + + } + + static AccessType getAccessFromIdPosition(DotName className, IndexBuilder indexBuilder) { + Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); + Map> ormAnnotations = indexBuilder.getClassInfoAnnotationsMap( className ); + AccessType accessType = getAccessFromIdPosition( ormAnnotations ); + if ( accessType == null ) { + accessType = getAccessFromIdPosition( indexedAnnotations ); + } + if ( accessType == null ) { + ClassInfo parent = indexBuilder.getClassInfo( className ); + if ( parent == null ) { + parent = indexBuilder.getIndexedClassInfo( className ); + } + if ( parent != null ) { + DotName parentClassName = parent.superName(); + accessType = getAccessFromIdPosition( parentClassName, indexBuilder ); + } + + } + + return accessType; + } + + private static AccessType getAccessFromIdPosition(Map> annotations) { + if ( annotations == null || annotations.isEmpty() || !( annotations.containsKey( ID ) ) ) { + return null; + } + List idAnnotationInstances = annotations.get( ID ); + if ( CollectionHelper.isNotEmpty( idAnnotationInstances ) ) { + return processIdAnnotations( idAnnotationInstances ); + } + return null; + } + + private static AccessType processIdAnnotations(List idAnnotations) { + AccessType accessType = null; + for ( AnnotationInstance annotation : idAnnotations ) { + AnnotationTarget tmpTarget = annotation.target(); + if ( tmpTarget == null ) { + throw new AssertionFailure( "@Id has no AnnotationTarget, this is mostly a internal error." ); + } + if ( accessType == null ) { + accessType = annotationTargetToAccessType( tmpTarget ); + } + else { + if ( !accessType.equals( annotationTargetToAccessType( tmpTarget ) ) ) { + throw new MappingException( "Inconsistent placement of @Id annotation within hierarchy " ); + } + } + } + return accessType; + } + + static AccessType annotationTargetToAccessType(AnnotationTarget target) { + return ( target instanceof MethodInfo ) ? AccessType.PROPERTY : AccessType.FIELD; + } + + static AccessType getEntityAccess(DotName className, IndexBuilder indexBuilder) { + Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); + Map> ormAnnotations = indexBuilder.getClassInfoAnnotationsMap( className ); + AccessType accessType = getAccess( ormAnnotations, indexBuilder ); + if ( accessType == null ) { + accessType = getAccess( indexedAnnotations, indexBuilder ); + } + if ( accessType == null ) { + ClassInfo parent = indexBuilder.getClassInfo( className ); + if ( parent == null ) { + parent = indexBuilder.getIndexedClassInfo( className ); + } + if ( parent != null ) { + DotName parentClassName = parent.superName(); + accessType = getEntityAccess( parentClassName, indexBuilder ); + } + } + return accessType; + + } + + private static AccessType getAccess(Map> annotations, IndexBuilder indexBuilder) { + if ( annotations == null || annotations.isEmpty() || !isEntityObject( annotations ) ) { + return null; + } + List accessAnnotationInstances = annotations.get( JPADotNames.ACCESS ); + if ( CollectionHelper.isNotEmpty( accessAnnotationInstances ) ) { + for ( AnnotationInstance annotationInstance : accessAnnotationInstances ) { + if ( annotationInstance.target() != null && annotationInstance.target() instanceof ClassInfo ) { + return JandexHelper.getEnumValue( + annotationInstance, + "value", + AccessType.class, + indexBuilder.getServiceRegistry().getService( ClassLoaderService.class ) + ); + } + } + } + return null; + } + + private static boolean isEntityObject(Map> annotations) { + return annotations.containsKey( ENTITY ) || annotations.containsKey( MAPPED_SUPERCLASS ) || annotations + .containsKey( EMBEDDABLE ); + } + + /** + * Get {@link javax.persistence.AccessType } from {@link javax.persistence.Access @Access} on the attribute of the given class + */ + static AccessType getAccessFromAttributeAnnotation(DotName className, String attributeName, IndexBuilder indexBuilder) { + Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); + if ( indexedAnnotations != null && indexedAnnotations.containsKey( ACCESS ) ) { + List annotationInstances = indexedAnnotations.get( ACCESS ); + if ( CollectionHelper.isNotEmpty( annotationInstances ) ) { + for ( AnnotationInstance annotationInstance : annotationInstances ) { + AnnotationTarget indexedPropertyTarget = annotationInstance.target(); + if ( indexedPropertyTarget == null ) { + continue; + } + if ( JandexHelper.getPropertyName( indexedPropertyTarget ).equals( attributeName ) ) { + AccessType accessType = JandexHelper.getEnumValue( + annotationInstance, + "value", + AccessType.class, + indexBuilder.getServiceRegistry().getService( ClassLoaderService.class ) + ); + /** + * here we ignore @Access(FIELD) on property (getter) and @Access(PROPERTY) on field + */ + AccessType targetAccessType = annotationTargetToAccessType( indexedPropertyTarget ); + if ( accessType.equals( targetAccessType ) ) { + return targetAccessType; + } + else { + LOG.warn( + String.format( + "%s.%s has @Access on %s, but it tries to assign the access type to %s, this is not allowed by JPA spec, and will be ignored.", + className, + attributeName, + targetAccessType, + accessType + ) + ); + } + } + } + } + } + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AnnotationMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AnnotationMocker.java new file mode 100644 index 000000000000..11f72036dc36 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AnnotationMocker.java @@ -0,0 +1,588 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.EnumType; +import javax.persistence.TemporalType; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAssociationOverride; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributeOverride; +import org.hibernate.metamodel.source.internal.jaxb.JaxbCollectionTable; +import org.hibernate.metamodel.source.internal.jaxb.JaxbColumn; +import org.hibernate.metamodel.source.internal.jaxb.JaxbJoinColumn; +import org.hibernate.metamodel.source.internal.jaxb.JaxbJoinTable; +import org.hibernate.metamodel.source.internal.jaxb.JaxbLob; +import org.hibernate.metamodel.source.internal.jaxb.JaxbOrderColumn; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPrimaryKeyJoinColumn; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class AnnotationMocker extends AbstractMocker { + private EntityMappingsMocker.Default defaults; + + AnnotationMocker(IndexBuilder indexBuilder, EntityMappingsMocker.Default defaults) { + super( indexBuilder ); + this.defaults = defaults; + } + + abstract void process(); + + protected EntityMappingsMocker.Default getDefaults() { + return defaults; + } + + protected boolean isDefaultCascadePersist() { + return defaults.isCascadePersist()!=null && defaults.isCascadePersist(); + } + + //@JoinTable + protected AnnotationInstance parseJoinTable(JaxbJoinTable joinTable, AnnotationTarget target) { + if ( joinTable == null ) { + return null; + } + DefaultConfigurationHelper.INSTANCE.applyDefaults(joinTable,getDefaults()); + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", joinTable.getName(), annotationValueList ); + MockHelper.stringValue( "catalog", joinTable.getCatalog(), annotationValueList ); + MockHelper.stringValue( "schema", joinTable.getSchema(), annotationValueList ); + nestedJoinColumnList( "joinColumns", joinTable.getJoinColumn(), annotationValueList ); + nestedJoinColumnList( "inverseJoinColumns", joinTable.getInverseJoinColumn(), annotationValueList ); + nestedUniqueConstraintList( "uniqueConstraints", joinTable.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", joinTable.getIndex(), annotationValueList ); + return create( JOIN_TABLE, target, annotationValueList ); + } + + //@AssociationOverride + private AnnotationInstance parseAssociationOverride(JaxbAssociationOverride associationOverride, AnnotationTarget target) { + if ( associationOverride == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", associationOverride.getName(), annotationValueList ); + if ( associationOverride instanceof JaxbAssociationOverrideProxy ) { + JaxbAssociationOverrideProxy proxy = (JaxbAssociationOverrideProxy) associationOverride; + MockHelper.addToCollectionIfNotNull( annotationValueList, proxy.getJoinColumnsAnnotationValue() ); + MockHelper.addToCollectionIfNotNull( annotationValueList, proxy.getJoinTableAnnotationValue() ); + } + else { + nestedJoinColumnList( + "joinColumns", associationOverride.getJoinColumn(), annotationValueList + ); + MockHelper.nestedAnnotationValue( + "joinTable", parseJoinTable( associationOverride.getJoinTable(), null ), annotationValueList + ); + } + return create( ASSOCIATION_OVERRIDE, target, annotationValueList ); + } + + private AnnotationValue[] nestedJoinColumnList(String name, List columns, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( columns ) ) { + AnnotationValue[] values = new AnnotationValue[columns.size()]; + for ( int i = 0; i < columns.size(); i++ ) { + AnnotationInstance annotationInstance = parseJoinColumn( columns.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + return values; + } + return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + protected AnnotationInstance parseColumnOrFormulas(List columnOrFormulas, AnnotationTarget target) { + if ( columnOrFormulas.isEmpty() ) { + return null; + } + + // todo : add @ColumnOrFormulas and @ColumnOrFormula annotations + + if ( columnOrFormulas.size() == 1 ) { + final Object columnOrFormula = columnOrFormulas.get( 0 ); + if ( String.class.isInstance( columnOrFormula ) ) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "value", (String) columnOrFormula, annotationValueList ); + return create( HibernateDotNames.FORMULA, target, annotationValueList ); + } + else { + return parseColumn( (JaxbColumn) columnOrFormula, target ); + } + } + else { + final List annotationValueList = new ArrayList(); + for ( Object columnOrFormula : columnOrFormulas ) { + // currently formulas are not supported in mix + if ( String.class.isInstance( columnOrFormula ) ) { + throw new NotYetImplementedException( "Requires @ColumnOrFormulas" ); + } + + AnnotationInstance annotationInstance = parseColumn( (JaxbColumn) columnOrFormula, null ); + annotationValueList.add( MockHelper.nestedAnnotationValue( "", annotationInstance ) ); + } + + return create( HibernateDotNames.COLUMNS, target, MockHelper.toArray( annotationValueList ) ); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //@Column + protected AnnotationInstance parseColumn(JaxbColumn column, AnnotationTarget target) { + if ( column == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", column.getName(), annotationValueList ); + MockHelper.stringValue( "columnDefinition", column.getColumnDefinition(), annotationValueList ); + MockHelper.stringValue( "table", column.getTable(), annotationValueList ); + MockHelper.booleanValue( "unique", column.isUnique(), annotationValueList ); + MockHelper.booleanValue( "nullable", column.isNullable(), annotationValueList ); + MockHelper.booleanValue( "insertable", column.isInsertable(), annotationValueList ); + MockHelper.booleanValue( "updatable", column.isUpdatable(), annotationValueList ); + MockHelper.integerValue( "length", column.getLength(), annotationValueList ); + MockHelper.integerValue( "precision", column.getPrecision(), annotationValueList ); + MockHelper.integerValue( "scale", column.getScale(), annotationValueList ); + return create( COLUMN, target, annotationValueList ); + } + + //@AttributeOverride + private AnnotationInstance parseAttributeOverride(JaxbAttributeOverride attributeOverride, AnnotationTarget target) { + if ( attributeOverride == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", attributeOverride.getName(), annotationValueList ); + if ( attributeOverride instanceof JaxbAttributeOverrideProxy ) { + JaxbAttributeOverrideProxy proxy = (JaxbAttributeOverrideProxy) attributeOverride; + MockHelper.addToCollectionIfNotNull( annotationValueList, proxy.getColumnAnnotationValue() ); + } + else { + MockHelper.nestedAnnotationValue( + "column", parseColumn( attributeOverride.getColumn(), null ), annotationValueList + ); + } + return + create( + ATTRIBUTE_OVERRIDE, target, annotationValueList + + ); + } + + + protected AnnotationInstance parseOrderColumn(JaxbOrderColumn orderColumn, AnnotationTarget target) { + if ( orderColumn == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", orderColumn.getName(), annotationValueList ); + MockHelper.stringValue( "columnDefinition", orderColumn.getColumnDefinition(), annotationValueList ); + MockHelper.booleanValue( "nullable", orderColumn.isNullable(), annotationValueList ); + MockHelper.booleanValue( "insertable", orderColumn.isInsertable(), annotationValueList ); + MockHelper.booleanValue( "updatable", orderColumn.isUpdatable(), annotationValueList ); + return create( ORDER_COLUMN, target, annotationValueList ); + } + + //@JoinColumn + protected AnnotationInstance parseJoinColumn(JaxbJoinColumn column, AnnotationTarget target) { + if ( column == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", column.getName(), annotationValueList ); + MockHelper.stringValue( "columnDefinition", column.getColumnDefinition(), annotationValueList ); + MockHelper.stringValue( "table", column.getTable(), annotationValueList ); + MockHelper.stringValue( + "referencedColumnName", column.getReferencedColumnName(), annotationValueList + ); + MockHelper.booleanValue( "unique", column.isUnique(), annotationValueList ); + MockHelper.booleanValue( "nullable", column.isNullable(), annotationValueList ); + MockHelper.booleanValue( "insertable", column.isInsertable(), annotationValueList ); + MockHelper.booleanValue( "updatable", column.isUpdatable(), annotationValueList ); + return create( JOIN_COLUMN, target, annotationValueList ); + } + + protected AnnotationInstance parseLob(JaxbLob lob, AnnotationTarget target) { + if ( lob == null ) { + return null; + } + return create( LOB, target ); + } + + protected AnnotationInstance parseTemporalType(TemporalType temporalType, AnnotationTarget target) { + if ( temporalType == null ) { + return null; + } + return create( TEMPORAL, target, MockHelper.enumValueArray( "value", TEMPORAL_TYPE, temporalType ) ); + } + + protected AnnotationInstance parseEnumType(EnumType enumerated, AnnotationTarget target) { + if ( enumerated == null ) { + return null; + } + return create( ENUMERATED, target, MockHelper.enumValueArray( "value", ENUM_TYPE, enumerated ) ); + } + + + protected AnnotationInstance parsePrimaryKeyJoinColumn(JaxbPrimaryKeyJoinColumn primaryKeyJoinColumn, AnnotationTarget target) { + if ( primaryKeyJoinColumn == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", primaryKeyJoinColumn.getName(), annotationValueList ); + MockHelper.stringValue( + "referencedColumnName", primaryKeyJoinColumn.getReferencedColumnName(), annotationValueList + ); + MockHelper.stringValue( + "columnDefinition", primaryKeyJoinColumn.getColumnDefinition(), annotationValueList + ); + return + create( + PRIMARY_KEY_JOIN_COLUMN, target, annotationValueList + + ); + } + + protected AnnotationInstance parsePrimaryKeyJoinColumnList(List primaryKeyJoinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { + if ( primaryKeyJoinColumnList.size() == 1 ) { + return parsePrimaryKeyJoinColumn( primaryKeyJoinColumnList.get( 0 ), target ); + } + else { + return create( + PRIMARY_KEY_JOIN_COLUMNS, + target, + nestedPrimaryKeyJoinColumnList( "value", primaryKeyJoinColumnList, null ) + ); + } + } + + return null; + + } + + protected AnnotationValue[] nestedPrimaryKeyJoinColumnList(String name, List constraints, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { + AnnotationValue[] values = new AnnotationValue[constraints.size()]; + for ( int i = 0; i < constraints.size(); i++ ) { + AnnotationInstance annotationInstance = parsePrimaryKeyJoinColumn( constraints.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + return values; + } + return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; + + } + + protected void getAnnotationInstanceByTarget(DotName annName, AnnotationTarget target, Operation operation) { + Map> annotatedMap = indexBuilder.getIndexedAnnotations( getTargetName() ); + if ( !annotatedMap.containsKey( annName ) ) { + return; + } + List annotationInstanceList = annotatedMap.get( annName ); + if ( CollectionHelper.isNotEmpty( annotationInstanceList ) ) { + for ( AnnotationInstance annotationInstance : annotationInstanceList ) { + AnnotationTarget annotationTarget = annotationInstance.target(); + if ( MockHelper.targetEquals( target, annotationTarget ) ) { + if ( operation.process( annotationInstance ) ) { + return; + } + } + } + } + } + + + protected AnnotationInstance parseAttributeOverrides(List attributeOverrides, AnnotationTarget target) { + if ( target == null ) { + throw new AssertionFailure( "target can not be null" ); + } + if ( attributeOverrides == null || attributeOverrides.isEmpty() ) { + return null; + } + Set names = new HashSet(); + for ( JaxbAttributeOverride attributeOverride : attributeOverrides ) { + names.add( attributeOverride.getName() ); + } + Operation operation = new AttributeOverrideOperation( names, attributeOverrides ); + getAnnotationInstanceByTarget( + ATTRIBUTE_OVERRIDES, target, new ContainerOperation( operation ) + ); + getAnnotationInstanceByTarget( + ATTRIBUTE_OVERRIDE, target, operation + ); + if ( attributeOverrides.size() == 1 ) { + return parseAttributeOverride( attributeOverrides.get( 0 ), target ); + } + else { + AnnotationValue[] values = new AnnotationValue[attributeOverrides.size()]; + for ( int i = 0; i < values.length; i++ ) { + values[i] = MockHelper.nestedAnnotationValue( + "", parseAttributeOverride( attributeOverrides.get( i ), null ) + ); + } + return create( + ATTRIBUTE_OVERRIDES, + target, + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } + ); + } + } + + protected AnnotationInstance parseAssociationOverrides(List associationOverrides, AnnotationTarget target) { + if ( target == null ) { + throw new AssertionFailure( "target can not be null" ); + } + if ( associationOverrides == null || associationOverrides.isEmpty() ) { + return null; + } + + Set names = new HashSet(); + for ( JaxbAssociationOverride associationOverride : associationOverrides ) { + names.add( associationOverride.getName() ); + } + Operation operation = new AssociationOverrideOperation( names, associationOverrides ); + getAnnotationInstanceByTarget( + ASSOCIATION_OVERRIDES, target, new ContainerOperation( operation ) + ); + getAnnotationInstanceByTarget( + ASSOCIATION_OVERRIDE, target, operation + ); + + + if ( associationOverrides.size() == 1 ) { + return parseAssociationOverride( associationOverrides.get( 0 ), target ); + } + else { + AnnotationValue[] values = new AnnotationValue[associationOverrides.size()]; + for ( int i = 0; i < values.length; i++ ) { + values[i] = MockHelper.nestedAnnotationValue( + "", parseAssociationOverride( associationOverrides.get( i ), null ) + ); + } + return create( + ASSOCIATION_OVERRIDES, + target, + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } + ); + } + + } + + protected AnnotationInstance parseCollectionTable(JaxbCollectionTable collectionTable, AnnotationTarget target) { + if ( collectionTable == null ) { + return null; + } + DefaultConfigurationHelper.INSTANCE.applyDefaults(collectionTable,getDefaults()); + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", collectionTable.getName(), annotationValueList ); + MockHelper.stringValue( "catalog", collectionTable.getCatalog(), annotationValueList ); + MockHelper.stringValue( "schema", collectionTable.getSchema(), annotationValueList ); + nestedJoinColumnList( "joinColumns", collectionTable.getJoinColumn(), annotationValueList ); + nestedUniqueConstraintList( "uniqueConstraints", collectionTable.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", collectionTable.getIndex(), annotationValueList ); + return create( COLLECTION_TABLE, target, annotationValueList ); + } + + + protected AnnotationInstance parseJoinColumnList(List joinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( joinColumnList ) ) { + if ( joinColumnList.size() == 1 ) { + return parseJoinColumn( joinColumnList.get( 0 ), target ); + } + else { + AnnotationValue[] values = nestedJoinColumnList( "value", joinColumnList, null ); + return create( + JOIN_COLUMNS, + target, + values + ); + } + } + return null; + + } + + protected interface Operation { + boolean process(AnnotationInstance annotationInstance); + } + + class ContainerOperation implements Operation { + private Operation child; + + ContainerOperation(Operation child) { + this.child = child; + } + + @Override + public boolean process(AnnotationInstance annotationInstance) { + AnnotationValue value = annotationInstance.value(); + AnnotationInstance[] indexedAttributeOverridesValues = value.asNestedArray(); + for ( AnnotationInstance ai : indexedAttributeOverridesValues ) { + child.process( ai ); + } + return true; + } + } + + class AttributeOverrideOperation implements Operation { + private Set names; + private List attributeOverrides; + + AttributeOverrideOperation(Set names, List attributeOverrides) { + this.names = names; + this.attributeOverrides = attributeOverrides; + } + + @Override + public boolean process(AnnotationInstance annotationInstance) { + String name = annotationInstance.value( "name" ).asString(); + if ( !names.contains( name ) ) { + JaxbAttributeOverrideProxy attributeOverride = new JaxbAttributeOverrideProxy(); + attributeOverride.setName( name ); + attributeOverride.setColumnAnnotationValue( annotationInstance.value( "column" ) ); + attributeOverrides.add( attributeOverride ); + } + return false; + } + } + + + class AssociationOverrideOperation implements Operation { + private Set names; + private List associationOverrides; + + AssociationOverrideOperation(Set names, List associationOverrides) { + this.names = names; + this.associationOverrides = associationOverrides; + } + + @Override + public boolean process(AnnotationInstance annotationInstance) { + String name = annotationInstance.value( "name" ).asString(); + if ( !names.contains( name ) ) { + JaxbAssociationOverrideProxy associationOverride = new JaxbAssociationOverrideProxy(); + associationOverride.setName( name ); + associationOverride.setJoinColumnsAnnotationValue( annotationInstance.value( "joinColumns" ) ); + associationOverride.setJoinTableAnnotationValue( annotationInstance.value( "joinTable" ) ); + associationOverrides.add( associationOverride ); + } + return false; + } + + } + + class JaxbAssociationOverrideProxy extends JaxbAssociationOverride { + private AnnotationValue joinTableAnnotationValue; + private AnnotationValue joinColumnsAnnotationValue; + + AnnotationValue getJoinColumnsAnnotationValue() { + return joinColumnsAnnotationValue; + } + + void setJoinColumnsAnnotationValue(AnnotationValue joinColumnsAnnotationValue) { + this.joinColumnsAnnotationValue = joinColumnsAnnotationValue; + } + + AnnotationValue getJoinTableAnnotationValue() { + return joinTableAnnotationValue; + } + + void setJoinTableAnnotationValue(AnnotationValue joinTableAnnotationValue) { + this.joinTableAnnotationValue = joinTableAnnotationValue; + } + } + + class JaxbAttributeOverrideProxy extends JaxbAttributeOverride { + private AnnotationValue columnAnnotationValue; + + AnnotationValue getColumnAnnotationValue() { + return columnAnnotationValue; + } + + void setColumnAnnotationValue(AnnotationValue columnAnnotationValue) { + this.columnAnnotationValue = columnAnnotationValue; + } + } + + /** + * Create simple AnnotationInstance with empty annotation value. + * AnnotationInstance's target is get from #{getTarget} + * + * @param name annotation name + * + * @return annotationInstance which name is , target is from #{getTarget}, and has no annotation values. + */ + protected AnnotationInstance create(DotName name) { + return create( name, MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY ); + } + + protected AnnotationInstance create(DotName name, AnnotationValue[] annotationValues) { + return create( name, getTarget(), annotationValues ); + + } + + protected AnnotationInstance create(DotName name, List annotationValueList) { + return create( name, getTarget(), annotationValueList ); + } + + /** + * @return DotName as the key for the ClassInfo object this mocker created that being push to. + */ + abstract protected DotName getTargetName(); + + /** + * @return Default Annotation Target for #{create} and #{mocker} methods. + */ + abstract protected AnnotationTarget getTarget(); + + protected AnnotationInstance push(AnnotationInstance annotationInstance) { + if ( annotationInstance != null && annotationInstance.target() != null ) { + indexBuilder.addAnnotationInstance( getTargetName(), annotationInstance ); + } + return annotationInstance; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AttributesBuilder.java new file mode 100644 index 000000000000..cb796618d7e7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/AttributesBuilder.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.metamodel.source.internal.jaxb.AttributesContainer; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddedId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbVersion; + +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class AttributesBuilder extends AbstractAttributesBuilder { + private final JaxbAttributes attributes; + + AttributesBuilder( + IndexBuilder indexBuilder, + ClassInfo classInfo, + AccessType accessType, + EntityMappingsMocker.Default defaults, + JaxbAttributes attributes) { + super( indexBuilder, classInfo, defaults ); + this.attributes = attributes; + } + + @Override + protected AttributesContainer getAttributesContainer() { + return attributes; + } + + @Override + List getId() { + return attributes.getId(); + } + + @Override + List getVersion() { + return attributes.getVersion(); + } + + @Override + JaxbEmbeddedId getEmbeddedId() { + return attributes.getEmbeddedId(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/BasicMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/BasicMocker.java new file mode 100644 index 000000000000..1cc9559e5a97 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/BasicMocker.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbBasic; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class BasicMocker extends PropertyMocker { + private final JaxbBasic basic; + + BasicMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbBasic basic) { + super( indexBuilder, classInfo, defaults ); + this.basic = basic; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return basic; + } + + @Override + protected void processExtra() { + List annotationValueList = new ArrayList(); + MockHelper.booleanValue( "optional", basic.isOptional(), annotationValueList ); + MockHelper.enumValue( "fetch", FETCH_TYPE, basic.getFetch(), annotationValueList ); + create( BASIC, annotationValueList ); + parseColumnOrFormulas( basic.getColumnOrFormula(), getTarget() ); + parseEnumType( basic.getEnumerated(), getTarget() ); + parseLob( basic.getLob(), getTarget() ); + parseTemporalType( basic.getTemporal(), getTarget() ); + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/DefaultConfigurationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/DefaultConfigurationHelper.java new file mode 100644 index 000000000000..4231c581b480 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/DefaultConfigurationHelper.java @@ -0,0 +1,290 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.internal.jandex.filter.IndexedAnnotationFilter; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbTable; +import org.hibernate.metamodel.source.internal.jaxb.ManagedType; +import org.hibernate.metamodel.source.internal.jaxb.SchemaAware; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; + +/** + * @author Strong Liu + */ +public class DefaultConfigurationHelper { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + DefaultConfigurationHelper.class.getName() + ); + public static final DefaultConfigurationHelper INSTANCE = new DefaultConfigurationHelper(); + static final DotName[] GLOBAL_ANNOTATIONS = new DotName[] { + JPADotNames.SEQUENCE_GENERATOR, + JPADotNames.TABLE_GENERATOR, + JPADotNames.NAMED_QUERIES, + JPADotNames.NAMED_QUERY, + JPADotNames.NAMED_NATIVE_QUERIES, + JPADotNames.NAMED_NATIVE_QUERY, + JPADotNames.SQL_RESULT_SET_MAPPING, + JPADotNames.SQL_RESULT_SET_MAPPINGS + }; + static final DotName[] SCHEMA_AWARE_ANNOTATIONS = new DotName[] { + JPADotNames.TABLE, + JPADotNames.JOIN_TABLE, + JPADotNames.COLLECTION_TABLE, + JPADotNames.SECONDARY_TABLE, + JPADotNames.SECONDARY_TABLES, + JPADotNames.TABLE_GENERATOR, + JPADotNames.SEQUENCE_GENERATOR + }; + static final DotName[] ASSOCIATION_ANNOTATIONS = new DotName[] { + JPADotNames.ONE_TO_MANY, JPADotNames.ONE_TO_ONE, JPADotNames.MANY_TO_ONE, JPADotNames.MANY_TO_MANY + }; + + private DefaultConfigurationHelper() { + } + + public void applyDefaults(SchemaAware schemaAware, EntityMappingsMocker.Default defaults) { + if ( hasSchemaOrCatalogDefined( defaults ) ) { + if ( StringHelper.isEmpty( schemaAware.getSchema() ) ) { + schemaAware.setSchema( defaults.getSchema() ); + } + if ( StringHelper.isEmpty( schemaAware.getCatalog() ) ) { + schemaAware.setCatalog( defaults.getCatalog() ); + } + } + } + + public void applyDefaults(Map> annotationsMap, EntityMappingsMocker.Default defaults) { + if ( annotationsMap.isEmpty() || defaults == null ) { + return; + } + if ( hasSchemaOrCatalogDefined( defaults ) ) { + applyDefaultSchemaAndCatalog( annotationsMap, defaults ); + } + if ( defaults.isCascadePersist()!=null && defaults.isCascadePersist() ) { + applyDefaultCascadePersist( annotationsMap ); + } + } + + public void applyDefaults(ManagedType entityElement, EntityMappingsMocker.Default defaults) { + if(JaxbEntity.class.isInstance( entityElement )) + mockTableIfNonExist( JaxbEntity.class.cast( entityElement ), defaults ); + applyDefaultsToEntityObject( entityElement , defaults ); + } + + private void mockTableIfNonExist(JaxbEntity entity, EntityMappingsMocker.Default defaults) { + if ( hasSchemaOrCatalogDefined( defaults ) ) { + JaxbTable table = entity.getTable(); + if ( table == null ) { + table = new JaxbTable(); + entity.setTable( table ); + } + } + } + + private void applyDefaultsToEntityObject(ManagedType entityObject, EntityMappingsMocker.Default defaults) { + if ( defaults == null ) { + return; + } + String className = MockHelper.buildSafeClassName( entityObject.getClazz(), defaults.getPackageName() ); + entityObject.setClazz( className ); + if ( entityObject.isMetadataComplete() == null ) { + entityObject.setMetadataComplete( defaults.isMetadataComplete() ); + } + LOG.debugf( "Adding XML overriding information for %s", className ); + } + + private boolean hasSchemaOrCatalogDefined(EntityMappingsMocker.Default defaults) { + return ( defaults != null ) && ( StringHelper.isNotEmpty( defaults.getSchema() ) || StringHelper.isNotEmpty( + defaults.getCatalog() + ) ); + } + + private void applyDefaultCascadePersist(Map> annotationsMap) { + for ( DotName annName : ASSOCIATION_ANNOTATIONS ) { + if ( annotationsMap.containsKey( annName ) ) { + addCascadePersistIfNotExist( annName, annotationsMap ); + } + } + } + + private void applyDefaultSchemaAndCatalog(Map> annotationsMap, EntityMappingsMocker.Default defaults) { + for ( DotName annName : SCHEMA_AWARE_ANNOTATIONS ) { + mockTableIfNonExist( annotationsMap, annName ); + if ( annotationsMap.containsKey( annName ) ) { + overrideSchemaCatalogByDefault( annName, annotationsMap, defaults ); + } + } + } + + private void mockTableIfNonExist(Map> annotationsMap, DotName annName) { + if ( annName == JPADotNames.TABLE && !annotationsMap.containsKey( JPADotNames.TABLE ) && annotationsMap + .containsKey( JPADotNames.ENTITY ) ) { + //if an entity doesn't have a @Table, we create one here + AnnotationInstance entity = JandexHelper.getSingleAnnotation( annotationsMap, JPADotNames.ENTITY ); + AnnotationInstance table = MockHelper.create( + JPADotNames.TABLE, entity.target(), MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY + ); + List annotationInstanceList = new ArrayList( 1 ); + annotationInstanceList.add( table ); + annotationsMap.put( JPADotNames.TABLE, annotationInstanceList ); + } + } + + private void addCascadePersistIfNotExist(DotName annName, Map> indexedAnnotationMap) { + List annotationInstanceList = indexedAnnotationMap.get( annName ); + if ( annotationInstanceList == null || annotationInstanceList.isEmpty() ) { + return; + } + List newAnnotationInstanceList = new ArrayList( annotationInstanceList.size() ); + for ( AnnotationInstance annotationInstance : annotationInstanceList ) { + AnnotationValue cascadeValue = annotationInstance.value( "cascade" ); + List newAnnotationValueList = new ArrayList(); + newAnnotationValueList.addAll( annotationInstance.values() ); + if ( cascadeValue == null ) { + AnnotationValue temp = AnnotationValue.createEnumValue( "", JPADotNames.CASCADE_TYPE, "PERSIST" ); + cascadeValue = AnnotationValue.createArrayValue( "cascade", new AnnotationValue[] { temp } ); + } + else { + newAnnotationValueList.remove( cascadeValue ); + String[] cascadeTypes = cascadeValue.asEnumArray(); + boolean hasPersistDefined = false; + for ( String type : cascadeTypes ) { + if ( "PERSIST".equals( type ) ) { + hasPersistDefined = true; + continue; + } + } + if ( hasPersistDefined ) { + newAnnotationInstanceList.add( annotationInstance ); + continue; + } + String[] newCascadeTypes = new String[cascadeTypes.length + 1]; + newCascadeTypes[0] = "PERSIST"; + System.arraycopy( cascadeTypes, 0, newCascadeTypes, 1, cascadeTypes.length ); + AnnotationValue[] cascades = new AnnotationValue[newCascadeTypes.length]; + for ( int i = 0; i < newCascadeTypes.length; i++ ) { + cascades[i] = AnnotationValue.createEnumValue( "", JPADotNames.CASCADE_TYPE, newCascadeTypes[i] ); + } + cascadeValue = AnnotationValue.createArrayValue( "cascade", cascades ); + + } + newAnnotationValueList.add( cascadeValue ); + + AnnotationInstance newAnnotationInstance = MockHelper.create( + annotationInstance.name(), + annotationInstance.target(), + MockHelper.toArray( newAnnotationValueList ) + ); + newAnnotationInstanceList.add( newAnnotationInstance ); + } + indexedAnnotationMap.put( annName, newAnnotationInstanceList ); + } + + //@Table, @CollectionTable, @JoinTable, @SecondaryTable + private void overrideSchemaCatalogByDefault(DotName annName, Map> indexedAnnotationMap, EntityMappingsMocker.Default defaults) { + List annotationInstanceList = indexedAnnotationMap.get( annName ); + if ( annotationInstanceList == null || annotationInstanceList.isEmpty() ) { + return; + } + List newAnnotationInstanceList = new ArrayList( annotationInstanceList.size() ); + for ( AnnotationInstance annotationInstance : annotationInstanceList ) { + if ( annName.equals( IndexedAnnotationFilter.SECONDARY_TABLES ) ) { + AnnotationInstance[] secondaryTableAnnotationInstanceArray = annotationInstance.value().asNestedArray(); + AnnotationValue[] newAnnotationValueArray = new AnnotationValue[secondaryTableAnnotationInstanceArray.length]; + for ( int i = 0; i < secondaryTableAnnotationInstanceArray.length; i++ ) { + newAnnotationValueArray[i] = MockHelper.nestedAnnotationValue( + "", overrideSchemaCatalogByDefault( + secondaryTableAnnotationInstanceArray[i], + defaults + ) + ); + } + AnnotationInstance secondaryTablesAnnotationInstance = MockHelper.create( + annName, + annotationInstance.target(), + new AnnotationValue[] { + AnnotationValue.createArrayValue( "value", newAnnotationValueArray ) + } + ); + newAnnotationInstanceList.add( secondaryTablesAnnotationInstance ); + } + else { + newAnnotationInstanceList.add( overrideSchemaCatalogByDefault( annotationInstance, defaults ) ); + } + } + indexedAnnotationMap.put( annName, newAnnotationInstanceList ); + } + + private AnnotationInstance overrideSchemaCatalogByDefault(AnnotationInstance annotationInstance, EntityMappingsMocker.Default defaults) { + List newAnnotationValueList = new ArrayList(); + newAnnotationValueList.addAll( annotationInstance.values() ); + boolean schemaDefined = false; + boolean catalogDefined = false; + if ( annotationInstance.value( "schema" ) != null ) { + schemaDefined = true; + } + if ( annotationInstance.value( "catalog" ) != null ) { + catalogDefined = true; + } + if ( schemaDefined && catalogDefined ) { + return annotationInstance; + } + if ( !catalogDefined && StringHelper.isNotEmpty( defaults.getCatalog() ) ) { + newAnnotationValueList.add( + AnnotationValue.createStringValue( + "catalog", defaults.getCatalog() + ) + ); + } + if ( !schemaDefined && StringHelper.isNotEmpty( defaults.getSchema() ) ) { + newAnnotationValueList.add( + AnnotationValue.createStringValue( + "schema", defaults.getSchema() + ) + ); + } + return MockHelper.create( + annotationInstance.name(), + annotationInstance.target(), + MockHelper.toArray( newAnnotationValueList ) + ); + } + + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ElementCollectionMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ElementCollectionMocker.java new file mode 100644 index 000000000000..af33a3aca9c3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ElementCollectionMocker.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbElementCollection; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class ElementCollectionMocker extends PropertyMocker { + private final JaxbElementCollection elementCollection; + + ElementCollectionMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbElementCollection elementCollection) { + super( indexBuilder, classInfo, defaults ); + this.elementCollection = elementCollection; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return elementCollection; + } + + @Override + protected void processExtra() { + List annotationValueList = new ArrayList(); + MockHelper.classValue( + "targetClass", + elementCollection.getTargetClass(), + annotationValueList, + indexBuilder.getServiceRegistry() + ); + MockHelper.enumValue( "fetch", FETCH_TYPE, elementCollection.getFetch(), annotationValueList ); + create( ELEMENT_COLLECTION, annotationValueList ); + parseLob( elementCollection.getLob(), getTarget() ); + parseEnumType( elementCollection.getEnumerated(), getTarget() ); + parseColumn( elementCollection.getColumn(), getTarget() ); + parseTemporalType( elementCollection.getTemporal(), getTarget() ); + parseCollectionTable( elementCollection.getCollectionTable(), getTarget() ); + parseAssociationOverrides( elementCollection.getAssociationOverride(), getTarget() ); + parseAttributeOverrides( elementCollection.getAttributeOverride(), getTarget() ); + if ( elementCollection.getOrderBy() != null ) { + create( ORDER_BY, MockHelper.stringValueArray( "value", elementCollection.getOrderBy() ) ); + } + parseAttributeOverrides( elementCollection.getMapKeyAttributeOverride(), getTarget() ); + parseMapKeyJoinColumnList( elementCollection.getMapKeyJoinColumn(), getTarget() ); + parseMapKey( elementCollection.getMapKey(), getTarget() ); + parseMapKeyColumn( elementCollection.getMapKeyColumn(), getTarget() ); + parseMapKeyClass( elementCollection.getMapKeyClass(), getTarget() ); + parseMapKeyEnumerated( elementCollection.getMapKeyEnumerated(), getTarget() ); + parseMapKeyTemporal( elementCollection.getMapKeyTemporal(), getTarget() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddableAttributesBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddableAttributesBuilder.java new file mode 100644 index 000000000000..3908bdc881e6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddableAttributesBuilder.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.Collections; +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.metamodel.source.internal.jaxb.AttributesContainer; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddableAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddedId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbVersion; + +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class EmbeddableAttributesBuilder extends AbstractAttributesBuilder { + private final JaxbEmbeddableAttributes attributes; + + EmbeddableAttributesBuilder( + IndexBuilder indexBuilder, + ClassInfo classInfo, + AccessType accessType, + EntityMappingsMocker.Default defaults, + JaxbEmbeddableAttributes embeddableAttributes) { + super( indexBuilder, classInfo, defaults ); + this.attributes = embeddableAttributes; + } + + @Override + protected AttributesContainer getAttributesContainer() { + return attributes; + } + + @Override + List getId() { + return Collections.emptyList(); + } + + @Override + List getVersion() { + return Collections.emptyList(); + } + + @Override + JaxbEmbeddedId getEmbeddedId() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddableMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddableMocker.java new file mode 100644 index 000000000000..be475551227d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddableMocker.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddable; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners; +import org.hibernate.metamodel.source.internal.jaxb.JaxbIdClass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostLoad; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostPersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostUpdate; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPrePersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreUpdate; +import org.hibernate.metamodel.source.internal.jaxb.ManagedType; + +/** + * Mock to {@link javax.persistence.Embeddable @Embeddable} + * + * @author Strong Liu + */ +public class EmbeddableMocker extends AbstractEntityObjectMocker { + private final JaxbEmbeddable embeddable; + + EmbeddableMocker(IndexBuilder indexBuilder, JaxbEmbeddable embeddable, EntityMappingsMocker.Default defaults) { + super( indexBuilder, defaults ); + this.embeddable = embeddable; + } + + @Override + protected AbstractAttributesBuilder getAttributesBuilder() { + if ( attributesBuilder == null ) { + attributesBuilder = new EmbeddableAttributesBuilder( + indexBuilder, classInfo, embeddable.getAccess(), getDefaults(), embeddable.getAttributes() + ); + } + return attributesBuilder; + } + + @Override + protected ManagedType getEntityElement() { + return embeddable; + } + + @Override + protected void processExtra() { + create( EMBEDDABLE ); + } + + @Override + protected boolean isExcludeDefaultListeners() { + return false; + } + + @Override + protected boolean isExcludeSuperclassListeners() { + return false; + } + + @Override + protected JaxbIdClass getIdClass() { + return null; + } + + @Override + protected JaxbEntityListeners getEntityListeners() { + return null; + } + + @Override + protected JaxbPrePersist getPrePersist() { + return null; + } + + @Override + protected JaxbPreRemove getPreRemove() { + return null; + } + + @Override + protected JaxbPreUpdate getPreUpdate() { + return null; + } + + @Override + protected JaxbPostPersist getPostPersist() { + return null; + } + + @Override + protected JaxbPostUpdate getPostUpdate() { + return null; + } + + @Override + protected JaxbPostRemove getPostRemove() { + return null; + } + + @Override + protected JaxbPostLoad getPostLoad() { + return null; + } + + @Override + protected JaxbAttributes getAttributes() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddedIdMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddedIdMocker.java new file mode 100644 index 000000000000..3fe7728b3ee1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddedIdMocker.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddedId; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class EmbeddedIdMocker extends PropertyMocker { + private final JaxbEmbeddedId embeddedId; + + EmbeddedIdMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbEmbeddedId embeddedId) { + super( indexBuilder, classInfo, defaults ); + this.embeddedId = embeddedId; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return embeddedId; + } + + @Override + protected void processExtra() { + create( EMBEDDED_ID ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddedMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddedMocker.java new file mode 100644 index 000000000000..f53df95797df --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EmbeddedMocker.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbedded; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class EmbeddedMocker extends PropertyMocker { + private final JaxbEmbedded embedded; + + EmbeddedMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbEmbedded embedded) { + super( indexBuilder, classInfo, defaults ); + this.embedded = embedded; + } + + @Override + protected void processExtra() { + create( EMBEDDED ); + parseAttributeOverrides( embedded.getAttributeOverride(), getTarget() ); + parseAssociationOverrides( embedded.getAssociationOverride(), getTarget() ); + + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return embedded; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java new file mode 100644 index 000000000000..29b297653881 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java @@ -0,0 +1,272 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEmbeddable; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMappedSuperclass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitDefaults; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; + +/** + * Parse all {@link org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings} generated from orm.xml. + * + * @author Strong Liu + */ +@Deprecated +public class EntityMappingsMocker { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( EntityMappingsMocker.class ); + + private final List> xmlBindings; + + /** + * Default configuration defined in Persistence Metadata Unit, one or zero per Persistence Unit. + */ + private Default globalDefaults; + private final IndexBuilder indexBuilder; + private final GlobalAnnotations globalAnnotations; + + public EntityMappingsMocker(List> xmlBindings, IndexView index, ServiceRegistry serviceRegistry) { + this.xmlBindings = xmlBindings; + this.indexBuilder = new IndexBuilder( index, serviceRegistry ); + this.globalAnnotations = new GlobalAnnotations(); + } + + public EntityMappingsMocker( + List xmlEntityMappingsList, + Index index, + ServiceRegistry serviceRegistry) { + this( + grabJaxbEntityMappings( xmlEntityMappingsList ), + index, + serviceRegistry + ); + } + + private static List> grabJaxbEntityMappings(List xmlEntityMappingsList) { + final List> result = new ArrayList>(); + for ( JaxbEntityMappings binding : xmlEntityMappingsList ) { + result.add( + new BindResult( + binding, + new Origin( SourceType.OTHER, Origin.UNKNOWN_FILE_PATH ) + ) + ); + } + return result; + } + + /** + * Create new {@link Index} with mocking JPA annotations from {@link org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings} + * and merge them with existing {@link Index} + * + * @return new {@link Index} + */ + public Index mockNewIndex() { + processPersistenceUnitMetadata( xmlBindings ); + processEntityMappings( xmlBindings ); + processGlobalAnnotations(); + return indexBuilder.build( globalDefaults ); + } + + /** + * processing PersistenceUnitMetadata, there should be only one PersistenceUnitMetadata in all mapping xml files. + */ + private void processPersistenceUnitMetadata(List> xmlBindings) { + for ( BindResult xmlBinding : xmlBindings ) { + //we have to iterate entityMappingsList first to find persistence-unit-metadata + JaxbPersistenceUnitMetadata pum = xmlBinding.getRoot().getPersistenceUnitMetadata(); + if ( globalDefaults != null ) { + LOG.duplicateMetadata(); + return; + } + if ( pum == null ) { + continue; + } + globalDefaults = new Default(); + if ( pum.getXmlMappingMetadataComplete() != null ) { + globalDefaults.setMetadataComplete( true ); + indexBuilder.mappingMetadataComplete(); + } + JaxbPersistenceUnitDefaults pud = pum.getPersistenceUnitDefaults(); + if ( pud == null ) { + return; + } + globalDefaults.setSchema( pud.getSchema() ); + globalDefaults.setCatalog( pud.getCatalog() ); + //globalDefaults.setAccess( pud.getAccess() ); + globalDefaults.setCascadePersist( pud.getCascadePersist() != null ); + new PersistenceMetadataMocker( indexBuilder, pud ).process(); + } + } + + + private void processEntityMappings(List> xmlBindings) { + List mockerList = new ArrayList(); + for ( BindResult xmlBinding : xmlBindings ) { + final Default defaults = getEntityMappingsDefaults( xmlBinding.getRoot() ); + globalAnnotations.collectGlobalMappings( xmlBinding.getRoot(), defaults ); + for ( JaxbMappedSuperclass mappedSuperclass : xmlBinding.getRoot().getMappedSuperclass() ) { + AbstractEntityObjectMocker mocker = + new MappedSuperclassMocker( indexBuilder, mappedSuperclass, defaults ); + mockerList.add( mocker ); + mocker.preProcess(); + } + for ( JaxbEmbeddable embeddable : xmlBinding.getRoot().getEmbeddable() ) { + AbstractEntityObjectMocker mocker = + new EmbeddableMocker( indexBuilder, embeddable, defaults ); + mockerList.add( mocker ); + mocker.preProcess(); + } + for ( JaxbEntity entity : xmlBinding.getRoot().getEntity() ) { + globalAnnotations.collectGlobalMappings( entity, defaults ); + AbstractEntityObjectMocker mocker = + new EntityMocker( indexBuilder, entity, defaults ); + mockerList.add( mocker ); + mocker.preProcess(); + } + } + for ( AbstractEntityObjectMocker mocker : mockerList ) { + mocker.process(); + } + } + + private void processGlobalAnnotations() { + if ( globalAnnotations.hasGlobalConfiguration() ) { + indexBuilder.collectGlobalConfigurationFromIndex( globalAnnotations ); + new GlobalAnnotationMocker( + indexBuilder, globalAnnotations + ).process(); + } + } + + private Default getEntityMappingsDefaults(JaxbEntityMappings entityMappings) { + Default entityMappingDefault = new Default(); + entityMappingDefault.setPackageName( entityMappings.getPackage() ); + entityMappingDefault.setSchema( entityMappings.getSchema() ); + entityMappingDefault.setCatalog( entityMappings.getCatalog() ); + entityMappingDefault.setAccess( entityMappings.getAccess() ); + final Default defaults = new Default(); + defaults.override( globalDefaults ); + defaults.override( entityMappingDefault ); + return defaults; + } + + + public static class Default implements Serializable { + private AccessType access; + private String packageName; + private String schema; + private String catalog; + private Boolean metadataComplete; + private Boolean cascadePersist; + + public AccessType getAccess() { + return access; + } + + public void setAccess(AccessType access) { + this.access = access; + } + + public String getCatalog() { + return catalog; + } + + public void setCatalog(String catalog) { + this.catalog = catalog; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public Boolean isMetadataComplete() { + return metadataComplete; + } + + public void setMetadataComplete(Boolean metadataComplete) { + this.metadataComplete = metadataComplete; + } + + public Boolean isCascadePersist() { + return cascadePersist; + } + + public void setCascadePersist(Boolean cascadePersist) { + this.cascadePersist = cascadePersist; + } + + void override(Default globalDefault) { + if ( globalDefault != null ) { + if ( globalDefault.getAccess() != null ) { + access = globalDefault.getAccess(); + } + if ( globalDefault.getPackageName() != null ) { + packageName = globalDefault.getPackageName(); + } + if ( globalDefault.getSchema() != null ) { + schema = globalDefault.getSchema(); + } + if ( globalDefault.getCatalog() != null ) { + catalog = globalDefault.getCatalog(); + } + if ( globalDefault.isCascadePersist() != null ) { + cascadePersist = globalDefault.isCascadePersist(); + } + if ( globalDefault.isMetadataComplete() != null ) { + metadataComplete = globalDefault.isMetadataComplete(); + } + + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMocker.java new file mode 100644 index 000000000000..3e14a1342fef --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMocker.java @@ -0,0 +1,290 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.persistence.AccessType; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbDiscriminatorColumn; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners; +import org.hibernate.metamodel.source.internal.jaxb.JaxbIdClass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbInheritance; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostLoad; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostPersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostUpdate; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPrePersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreUpdate; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSecondaryTable; +import org.hibernate.metamodel.source.internal.jaxb.JaxbTable; +import org.hibernate.metamodel.source.internal.jaxb.ManagedType; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * Mock to {@link javax.persistence.Entity @Entity} + * + * @author Strong Liu + */ +public class EntityMocker extends AbstractEntityObjectMocker { + private final JaxbEntity entity; + + public EntityMocker(IndexBuilder indexBuilder, JaxbEntity entity, EntityMappingsMocker.Default defaults) { + super( indexBuilder, defaults ); + this.entity = entity; + } + + @Override + protected void processExtra() { + //@Entity + create( ENTITY, MockHelper.stringValueArray( "name", entity.getName() ) ); + + + if ( entity.isCacheable() != null ) { + //@Cacheable + create( + CACHEABLE, + MockHelper.booleanValueArray( "value", entity.isCacheable() ) + + ); + } + if ( StringHelper.isNotEmpty( entity.getDiscriminatorValue() ) ) { + //@DiscriminatorValue + create( + DISCRIMINATOR_VALUE, + MockHelper.stringValueArray( "value", entity.getDiscriminatorValue() ) + + ); + } + //@Table + parseTable( entity.getTable() ); + parseInheritance( entity.getInheritance() ); + parseDiscriminatorColumn( entity.getDiscriminatorColumn() ); + parseAttributeOverrides( entity.getAttributeOverride(), getTarget() ); + parseAssociationOverrides( entity.getAssociationOverride(), getTarget() ); + parsePrimaryKeyJoinColumnList( entity.getPrimaryKeyJoinColumn(), getTarget() ); + parseSecondaryTableList( entity.getSecondaryTable(), getTarget() ); + + } + + //@Table (entity only) + private AnnotationInstance parseTable(JaxbTable table) { + if ( table == null ) { + return null; + } + DefaultConfigurationHelper.INSTANCE.applyDefaults(table,getDefaults()); + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", table.getName(), annotationValueList ); + MockHelper.stringValue( "catalog", table.getCatalog(), annotationValueList ); + MockHelper.stringValue( "schema", table.getSchema(), annotationValueList ); + nestedUniqueConstraintList( "uniqueConstraints", table.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", table.getIndex(), annotationValueList ); + return create( TABLE, annotationValueList ); + } + + protected AccessType getDefaultAccess() { + if ( entity.getAccess() != null ) { + return entity.getAccess(); + } + + return null; + } + + protected AccessType getAccessFromIndex(DotName className) { + Map> indexedAnnotations = indexBuilder.getIndexedAnnotations( className ); + List accessAnnotationInstances = indexedAnnotations.get( ACCESS ); + if ( CollectionHelper.isNotEmpty( accessAnnotationInstances ) ) { + for ( AnnotationInstance annotationInstance : accessAnnotationInstances ) { + if ( annotationInstance.target() != null && annotationInstance.target() instanceof ClassInfo ) { + ClassInfo ci = (ClassInfo) ( annotationInstance.target() ); + if ( className.equals( ci.name() ) ) { + //todo does ci need to have @Entity or @MappedSuperClass ?? + return AccessType.valueOf( annotationInstance.value().asEnum() ); + } + } + } + } + return null; + } + + @Override + protected ManagedType getEntityElement() { + return entity; + } + + @Override + protected JaxbPrePersist getPrePersist() { + return entity.getPrePersist(); + } + + @Override + protected JaxbPreRemove getPreRemove() { + return entity.getPreRemove(); + } + + @Override + protected JaxbPreUpdate getPreUpdate() { + return entity.getPreUpdate(); + } + + @Override + protected JaxbPostPersist getPostPersist() { + return entity.getPostPersist(); + } + + @Override + protected JaxbPostUpdate getPostUpdate() { + return entity.getPostUpdate(); + } + + @Override + protected JaxbPostRemove getPostRemove() { + return entity.getPostRemove(); + } + + @Override + protected JaxbPostLoad getPostLoad() { + return entity.getPostLoad(); + } + + @Override + protected JaxbAttributes getAttributes() { + return entity.getAttributes(); + } + + + @Override + protected boolean isExcludeDefaultListeners() { + return entity.getExcludeDefaultListeners() != null; + } + + @Override + protected boolean isExcludeSuperclassListeners() { + return entity.getExcludeSuperclassListeners() != null; + } + + @Override + protected JaxbIdClass getIdClass() { + return entity.getIdClass(); + } + + @Override + protected JaxbEntityListeners getEntityListeners() { + return entity.getEntityListeners(); + } + + //@Inheritance + protected AnnotationInstance parseInheritance(JaxbInheritance inheritance) { + if ( inheritance == null ) { + return null; + } + return + create( + INHERITANCE, + MockHelper.enumValueArray( "strategy", INHERITANCE_TYPE, inheritance.getStrategy() ) + + ); + } + + //@DiscriminatorColumn + protected AnnotationInstance parseDiscriminatorColumn(JaxbDiscriminatorColumn discriminatorColumn) { + if ( discriminatorColumn == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", discriminatorColumn.getName(), annotationValueList ); + MockHelper.stringValue( + "columnDefinition", discriminatorColumn.getColumnDefinition(), annotationValueList + ); + MockHelper.integerValue( "length", discriminatorColumn.getLength(), annotationValueList ); + MockHelper.enumValue( + "discriminatorType", DISCRIMINATOR_TYPE, discriminatorColumn.getDiscriminatorType(), annotationValueList + ); + return create(DISCRIMINATOR_COLUMN, annotationValueList); + + } + + //@SecondaryTable + protected AnnotationInstance parseSecondaryTable(JaxbSecondaryTable secondaryTable, AnnotationTarget target) { + if ( secondaryTable == null ) { + return null; + } + DefaultConfigurationHelper.INSTANCE.applyDefaults(secondaryTable,getDefaults()); + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", secondaryTable.getName(), annotationValueList ); + MockHelper.stringValue( "catalog", secondaryTable.getCatalog(), annotationValueList ); + MockHelper.stringValue( "schema", secondaryTable.getSchema(), annotationValueList ); + nestedPrimaryKeyJoinColumnList("pkJoinColumns", secondaryTable.getPrimaryKeyJoinColumn(), annotationValueList); + nestedUniqueConstraintList("uniqueConstraints", secondaryTable.getUniqueConstraint(), annotationValueList); + nestedIndexConstraintList( "indexes", secondaryTable.getIndex(), annotationValueList ); + return create( SECONDARY_TABLE, target, annotationValueList ); + } + + + protected AnnotationInstance parseSecondaryTableList(List primaryKeyJoinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( primaryKeyJoinColumnList ) ) { + if ( primaryKeyJoinColumnList.size() == 1 ) { + return parseSecondaryTable( primaryKeyJoinColumnList.get( 0 ), target ); + } + else { + return create( + SECONDARY_TABLES, + target, + nestedSecondaryTableList( "value", primaryKeyJoinColumnList, null ) + ); + } + } + return null; + + } + + protected AnnotationValue[] nestedSecondaryTableList(String name, List secondaryTableList, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( secondaryTableList ) ) { + AnnotationValue[] values = new AnnotationValue[secondaryTableList.size()]; + for ( int i = 0; i < secondaryTableList.size(); i++ ) { + AnnotationInstance annotationInstance = parseSecondaryTable( secondaryTableList.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + return values; + } + return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/GlobalAnnotationMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/GlobalAnnotationMocker.java new file mode 100644 index 000000000000..41ec193eed9a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/GlobalAnnotationMocker.java @@ -0,0 +1,327 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbNamedNativeQuery; +import org.hibernate.metamodel.source.internal.jaxb.JaxbNamedQuery; +import org.hibernate.metamodel.source.internal.jaxb.JaxbQueryHint; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSequenceGenerator; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSqlResultSetMapping; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSqlResultSetMappingColumnResult; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSqlResultSetMappingEntityResult; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSqlResultSetMappingFieldResult; +import org.hibernate.metamodel.source.internal.jaxb.JaxbTableGenerator; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Strong Liu + */ +public class GlobalAnnotationMocker extends AbstractMocker { + private GlobalAnnotations globalAnnotations; + + GlobalAnnotationMocker(IndexBuilder indexBuilder, GlobalAnnotations globalAnnotations) { + super( indexBuilder ); + this.globalAnnotations = globalAnnotations; + } + + + void process() { + if ( !globalAnnotations.getTableGeneratorMap().isEmpty() ) { + for ( JaxbTableGenerator generator : globalAnnotations.getTableGeneratorMap().values() ) { + parseTableGenerator( generator ); + } + } + if ( !globalAnnotations.getSequenceGeneratorMap().isEmpty() ) { + for ( JaxbSequenceGenerator generator : globalAnnotations.getSequenceGeneratorMap().values() ) { + parseSequenceGenerator( generator ); + } + } + if ( !globalAnnotations.getNamedQueryMap().isEmpty() ) { + Collection namedQueries = globalAnnotations.getNamedQueryMap().values(); + if ( namedQueries.size() > 1 ) { + parseNamedQueries( namedQueries ); + } + else { + parseNamedQuery( namedQueries.iterator().next() ); + } + } + if ( !globalAnnotations.getNamedNativeQueryMap().isEmpty() ) { + Collection namedQueries = globalAnnotations.getNamedNativeQueryMap().values(); + if ( namedQueries.size() > 1 ) { + parseNamedNativeQueries( namedQueries ); + } + else { + parseNamedNativeQuery( namedQueries.iterator().next() ); + } + } + if ( !globalAnnotations.getSqlResultSetMappingMap().isEmpty() ) { + parseSqlResultSetMappings( globalAnnotations.getSqlResultSetMappingMap().values() ); + } + indexBuilder.finishGlobalConfigurationMocking( globalAnnotations ); + } + + private AnnotationInstance parseSqlResultSetMappings(Collection namedQueries) { + AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; + int i = 0; + for ( JaxbSqlResultSetMapping namedQuery : namedQueries ) { + AnnotationInstance annotationInstance = parseSqlResultSetMapping( namedQuery ); + values[i++] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + return create( + SQL_RESULT_SET_MAPPINGS, null, + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } + + ); + } + + + //@SqlResultSetMapping + private AnnotationInstance parseSqlResultSetMapping(JaxbSqlResultSetMapping mapping) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", mapping.getName(), annotationValueList ); + nestedEntityResultList( "entities", mapping.getEntityResult(), annotationValueList ); + nestedColumnResultList( "columns", mapping.getColumnResult(), annotationValueList ); + return create( SQL_RESULT_SET_MAPPING, null, annotationValueList ); + } + + + //@EntityResult + private AnnotationInstance parseEntityResult(JaxbSqlResultSetMappingEntityResult result) { + + List annotationValueList = new ArrayList(); + MockHelper.stringValue( + "discriminatorColumn", result.getDiscriminatorColumn(), annotationValueList + ); + nestedFieldResultList( "fields", result.getFieldResult(), annotationValueList ); + MockHelper.classValue( + "entityClass", result.getEntityClass(), annotationValueList, indexBuilder.getServiceRegistry() + ); + return + create( + ENTITY_RESULT, null, annotationValueList + + ); + } + + private void nestedEntityResultList(String name, List entityResults, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( entityResults ) ) { + AnnotationValue[] values = new AnnotationValue[entityResults.size()]; + for ( int i = 0; i < entityResults.size(); i++ ) { + AnnotationInstance annotationInstance = parseEntityResult( entityResults.get( i ) ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + } + } + + //@ColumnResult + private AnnotationInstance parseColumnResult(JaxbSqlResultSetMappingColumnResult result) { + return create( COLUMN_RESULT, null, MockHelper.stringValueArray( "name", result.getName() ) ); + } + + private void nestedColumnResultList(String name, List columnResults, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( columnResults ) ) { + AnnotationValue[] values = new AnnotationValue[columnResults.size()]; + for ( int i = 0; i < columnResults.size(); i++ ) { + AnnotationInstance annotationInstance = parseColumnResult( columnResults.get( i ) ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + } + } + + //@FieldResult + private AnnotationInstance parseFieldResult(JaxbSqlResultSetMappingFieldResult result) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", result.getName(), annotationValueList ); + MockHelper.stringValue( "column", result.getColumn(), annotationValueList ); + return create( FIELD_RESULT, null, annotationValueList ); + } + + + private void nestedFieldResultList(String name, List fieldResultList, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( fieldResultList ) ) { + AnnotationValue[] values = new AnnotationValue[fieldResultList.size()]; + for ( int i = 0; i < fieldResultList.size(); i++ ) { + AnnotationInstance annotationInstance = parseFieldResult( fieldResultList.get( i ) ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + } + } + + private AnnotationInstance parseNamedNativeQueries(Collection namedQueries) { + AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; + int i = 0; + for ( JaxbNamedNativeQuery namedQuery : namedQueries ) { + AnnotationInstance annotationInstance = parseNamedNativeQuery( namedQuery ); + values[i++] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + return create( + NAMED_NATIVE_QUERIES, null, + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } + + ); + } + + //@NamedNativeQuery + private AnnotationInstance parseNamedNativeQuery(JaxbNamedNativeQuery namedNativeQuery) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", namedNativeQuery.getName(), annotationValueList ); + MockHelper.stringValue( "query", namedNativeQuery.getQuery(), annotationValueList ); + MockHelper.stringValue( + "resultSetMapping", namedNativeQuery.getResultSetMapping(), annotationValueList + ); + MockHelper.classValue( + "resultClass", namedNativeQuery.getResultClass(), annotationValueList, indexBuilder.getServiceRegistry() + ); + nestedQueryHintList( "hints", namedNativeQuery.getHint(), annotationValueList ); + return + create( + NAMED_NATIVE_QUERY, null, annotationValueList + + ); + } + + + private AnnotationInstance parseNamedQueries(Collection namedQueries) { + AnnotationValue[] values = new AnnotationValue[namedQueries.size()]; + int i = 0; + for ( JaxbNamedQuery namedQuery : namedQueries ) { + AnnotationInstance annotationInstance = parseNamedQuery( namedQuery ); + values[i++] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + return create( + NAMED_QUERIES, null, + new AnnotationValue[] { AnnotationValue.createArrayValue( "value", values ) } + + ); + } + + + //@NamedQuery + private AnnotationInstance parseNamedQuery(JaxbNamedQuery namedQuery) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", namedQuery.getName(), annotationValueList ); + MockHelper.stringValue( "query", namedQuery.getQuery(), annotationValueList ); + MockHelper.enumValue( "lockMode", LOCK_MODE_TYPE, namedQuery.getLockMode(), annotationValueList ); + nestedQueryHintList( "hints", namedQuery.getHint(), annotationValueList ); + return create( NAMED_QUERY, null, annotationValueList ); + } + + //@QueryHint + private AnnotationInstance parseQueryHint(JaxbQueryHint queryHint) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", queryHint.getName(), annotationValueList ); + MockHelper.stringValue( "value", queryHint.getValue(), annotationValueList ); + return create( QUERY_HINT, null, annotationValueList ); + + } + + private void nestedQueryHintList(String name, List constraints, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( constraints ) ) { + AnnotationValue[] values = new AnnotationValue[constraints.size()]; + for ( int i = 0; i < constraints.size(); i++ ) { + AnnotationInstance annotationInstance = parseQueryHint( constraints.get( i ) ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + } + } + + + //@SequenceGenerator + private AnnotationInstance parseSequenceGenerator(JaxbSequenceGenerator generator) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", generator.getName(), annotationValueList ); + MockHelper.stringValue( "catalog", generator.getCatalog(), annotationValueList ); + MockHelper.stringValue( "schema", generator.getSchema(), annotationValueList ); + MockHelper.stringValue( "sequenceName", generator.getSequenceName(), annotationValueList ); + MockHelper.integerValue( "initialValue", generator.getInitialValue(), annotationValueList ); + MockHelper.integerValue( "allocationSize", generator.getAllocationSize(), annotationValueList ); + return + create( + SEQUENCE_GENERATOR, null, annotationValueList + + ); + } + + //@TableGenerator + private AnnotationInstance parseTableGenerator(JaxbTableGenerator generator) { + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", generator.getName(), annotationValueList ); + MockHelper.stringValue( "catalog", generator.getCatalog(), annotationValueList ); + MockHelper.stringValue( "schema", generator.getSchema(), annotationValueList ); + MockHelper.stringValue( "table", generator.getTable(), annotationValueList ); + MockHelper.stringValue( "pkColumnName", generator.getPkColumnName(), annotationValueList ); + MockHelper.stringValue( "valueColumnName", generator.getValueColumnName(), annotationValueList ); + MockHelper.stringValue( "pkColumnValue", generator.getPkColumnValue(), annotationValueList ); + MockHelper.integerValue( "initialValue", generator.getInitialValue(), annotationValueList ); + MockHelper.integerValue( "allocationSize", generator.getAllocationSize(), annotationValueList ); + nestedUniqueConstraintList( "uniqueConstraints", generator.getUniqueConstraint(), annotationValueList ); + nestedIndexConstraintList( "indexes", generator.getIndex(), annotationValueList ); + return + create( + TABLE_GENERATOR, null, annotationValueList + + ); + } + + @Override + protected AnnotationInstance push(AnnotationInstance annotationInstance) { + if ( annotationInstance != null ) { + return globalAnnotations.push( annotationInstance.name(), annotationInstance ); + } + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/GlobalAnnotations.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/GlobalAnnotations.java new file mode 100644 index 000000000000..44fb7fda7ea8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/GlobalAnnotations.java @@ -0,0 +1,293 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.internal.jaxb.JaxbId; +import org.hibernate.metamodel.source.internal.jaxb.JaxbNamedNativeQuery; +import org.hibernate.metamodel.source.internal.jaxb.JaxbNamedQuery; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSequenceGenerator; +import org.hibernate.metamodel.source.internal.jaxb.JaxbSqlResultSetMapping; +import org.hibernate.metamodel.source.internal.jaxb.JaxbTableGenerator; +import org.hibernate.metamodel.source.internal.jaxb.SchemaAware; +import org.hibernate.metamodel.source.spi.MappingException; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public class GlobalAnnotations implements JPADotNames { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GlobalAnnotations.class ); + + private final Map sequenceGeneratorMap = new HashMap(); + private final Map tableGeneratorMap = new HashMap(); + private final Map namedQueryMap = new HashMap(); + private final Map namedNativeQueryMap = new HashMap(); + private final Map sqlResultSetMappingMap = new HashMap(); + private final Map> annotationInstanceMap = new HashMap>(); + private final List indexedAnnotationInstanceList = new ArrayList(); + //--------------------------- + private final Set defaultNamedNativeQueryNames = new HashSet(); + private final Set defaultNamedQueryNames = new HashSet(); + private final Set defaultNamedGenerators = new HashSet(); + private final Set defaultSqlResultSetMappingNames = new HashSet(); + + Map> getAnnotationInstanceMap() { + return annotationInstanceMap; + } + + AnnotationInstance push(DotName name, AnnotationInstance annotationInstance) { + if ( name == null || annotationInstance == null ) { + return null; + } + List list = annotationInstanceMap.get( name ); + if ( list == null ) { + list = new ArrayList(); + annotationInstanceMap.put( name, list ); + } + list.add( annotationInstance ); + return annotationInstance; + } + + + void addIndexedAnnotationInstance(Collection annotationInstanceList) { + if ( CollectionHelper.isNotEmpty( annotationInstanceList ) ) { + indexedAnnotationInstanceList.addAll( annotationInstanceList ); + } + } + + /** + * do the orm xmls define global configurations? + */ + boolean hasGlobalConfiguration() { + return !( namedQueryMap.isEmpty() + && namedNativeQueryMap.isEmpty() + && sequenceGeneratorMap.isEmpty() + && tableGeneratorMap.isEmpty() + && sqlResultSetMappingMap.isEmpty() ); + } + + Map getNamedNativeQueryMap() { + return namedNativeQueryMap; + } + + Map getNamedQueryMap() { + return namedQueryMap; + } + + Map getSequenceGeneratorMap() { + return sequenceGeneratorMap; + } + + Map getSqlResultSetMappingMap() { + return sqlResultSetMappingMap; + } + + Map getTableGeneratorMap() { + return tableGeneratorMap; + } + + + public void filterIndexedAnnotations() { + for ( AnnotationInstance annotationInstance : indexedAnnotationInstanceList ) { + pushIfNotExist( annotationInstance ); + } + } + + private void pushIfNotExist(AnnotationInstance annotationInstance) { + DotName annName = annotationInstance.name(); + boolean isNotExist = false; + if ( annName.equals( SQL_RESULT_SET_MAPPINGS ) ) { + AnnotationInstance[] annotationInstances = annotationInstance.value().asNestedArray(); + for ( AnnotationInstance ai : annotationInstances ) { + pushIfNotExist( ai ); + } + } + else { + AnnotationValue value = annotationInstance.value( "name" ); + if ( value != null ) { + String name = value.asString(); + isNotExist = ( annName.equals( TABLE_GENERATOR ) && !tableGeneratorMap.containsKey( name ) ) || + ( annName.equals( SEQUENCE_GENERATOR ) && !sequenceGeneratorMap.containsKey( name ) ) || + ( annName.equals( NAMED_QUERY ) && !namedQueryMap.containsKey( name ) ) || + ( annName.equals( NAMED_NATIVE_QUERY ) && !namedNativeQueryMap.containsKey( name ) ) || + ( annName.equals( SQL_RESULT_SET_MAPPING ) && !sqlResultSetMappingMap.containsKey( name ) ); + } + } + if ( isNotExist ) { + push( annName, annotationInstance ); + } + } + + void collectGlobalMappings(JaxbEntityMappings entityMappings, EntityMappingsMocker.Default defaults) { + for ( JaxbSequenceGenerator generator : entityMappings.getSequenceGenerator() ) { + put( generator, defaults ); + defaultNamedGenerators.add( generator.getName() ); + } + for ( JaxbTableGenerator generator : entityMappings.getTableGenerator() ) { + put( generator, defaults ); + defaultNamedGenerators.add( generator.getName() ); + } + for ( JaxbNamedQuery namedQuery : entityMappings.getNamedQuery() ) { + put( namedQuery ); + defaultNamedQueryNames.add( namedQuery.getName() ); + } + for ( JaxbNamedNativeQuery namedNativeQuery : entityMappings.getNamedNativeQuery() ) { + put( namedNativeQuery ); + defaultNamedNativeQueryNames.add( namedNativeQuery.getName() ); + } + for ( JaxbSqlResultSetMapping sqlResultSetMapping : entityMappings.getSqlResultSetMapping() ) { + put( sqlResultSetMapping ); + defaultSqlResultSetMappingNames.add( sqlResultSetMapping.getName() ); + } + } + + void collectGlobalMappings(JaxbEntity entity, EntityMappingsMocker.Default defaults) { + for ( JaxbNamedQuery namedQuery : entity.getNamedQuery() ) { + if ( !defaultNamedQueryNames.contains( namedQuery.getName() ) ) { + put( namedQuery ); + } + else { + LOG.warn( "Named Query [" + namedQuery.getName() + "] duplicated." ); + } + } + for ( JaxbNamedNativeQuery namedNativeQuery : entity.getNamedNativeQuery() ) { + if ( !defaultNamedNativeQueryNames.contains( namedNativeQuery.getName() ) ) { + put( namedNativeQuery ); + } + else { + LOG.warn( "Named native Query [" + namedNativeQuery.getName() + "] duplicated." ); + } + } + for ( JaxbSqlResultSetMapping sqlResultSetMapping : entity.getSqlResultSetMapping() ) { + if ( !defaultSqlResultSetMappingNames.contains( sqlResultSetMapping.getName() ) ) { + put( sqlResultSetMapping ); + } + } + JaxbSequenceGenerator sequenceGenerator = entity.getSequenceGenerator(); + if ( sequenceGenerator != null ) { + if ( !defaultNamedGenerators.contains( sequenceGenerator.getName() ) ) { + put( sequenceGenerator, defaults ); + } + } + JaxbTableGenerator tableGenerator = entity.getTableGenerator(); + if ( tableGenerator != null ) { + if ( !defaultNamedGenerators.contains( tableGenerator.getName() ) ) { + put( tableGenerator, defaults ); + } + } + JaxbAttributes attributes = entity.getAttributes(); + if ( attributes != null ) { + for ( JaxbId id : attributes.getId() ) { + sequenceGenerator = id.getSequenceGenerator(); + if ( sequenceGenerator != null ) { + put( sequenceGenerator, defaults ); + } + tableGenerator = id.getTableGenerator(); + if ( tableGenerator != null ) { + put( tableGenerator, defaults ); + } + } + } + } + + /** + * Override SequenceGenerator using info definded in EntityMappings/Persistence-Metadata-Unit + */ + private static void overrideGenerator(SchemaAware generator, EntityMappingsMocker.Default defaults) { + if ( StringHelper.isEmpty( generator.getSchema() ) && defaults != null ) { + generator.setSchema( defaults.getSchema() ); + } + if ( StringHelper.isEmpty( generator.getCatalog() ) && defaults != null ) { + generator.setCatalog( defaults.getCatalog() ); + } + } + + private void checkQueryName(String name) { + if ( namedQueryMap.containsKey( name ) || namedNativeQueryMap.containsKey( name ) ) { + throw new MappingException( "Duplicated query mapping " + name, null ); + } + } + private void checkDuplicated(Object old, String name){ + if ( old != null ) { + LOG.duplicateGeneratorName( name ); + } + } + + private void put(JaxbNamedQuery query) { + if ( query != null ) { + checkQueryName( query.getName() ); + namedQueryMap.put( query.getName(), query ); + } + } + + private void put(JaxbSequenceGenerator generator, EntityMappingsMocker.Default defaults) { + if ( generator != null ) { + overrideGenerator( generator, defaults ); + Object old = sequenceGeneratorMap.put( generator.getName(), generator ); + checkDuplicated( old, generator.getName() ); + } + } + + private void put(JaxbTableGenerator generator, EntityMappingsMocker.Default defaults) { + if ( generator != null ) { + overrideGenerator( generator, defaults ); + Object old = tableGeneratorMap.put( generator.getName(), generator ); + checkDuplicated( old, generator.getName() ); + } + } + private void put(JaxbNamedNativeQuery query) { + if ( query != null ) { + checkQueryName( query.getName() ); + namedNativeQueryMap.put( query.getName(), query ); + } + } + + private void put(JaxbSqlResultSetMapping mapping) { + if ( mapping != null ) { + Object old = sqlResultSetMappingMap.put( mapping.getName(), mapping ); + if ( old != null ) { + throw new MappingException( "Duplicated SQL result set mapping " + mapping.getName(), null ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/IdMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/IdMocker.java new file mode 100644 index 000000000000..6e1d679091f1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/IdMocker.java @@ -0,0 +1,74 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbGeneratedValue; +import org.hibernate.metamodel.source.internal.jaxb.JaxbId; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class IdMocker extends PropertyMocker { + private final JaxbId id; + + IdMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbId id) { + super( indexBuilder, classInfo, defaults ); + this.id = id; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return id; + } + + @Override + protected void processExtra() { + create( ID ); + parseColumn( id.getColumn(), getTarget() ); + parseGeneratedValue( id.getGeneratedValue(), getTarget() ); + parseTemporalType( id.getTemporal(), getTarget() ); + } + + private AnnotationInstance parseGeneratedValue(JaxbGeneratedValue generatedValue, AnnotationTarget target) { + if ( generatedValue == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "generator", generatedValue.getGenerator(), annotationValueList ); + MockHelper.enumValue( + "strategy", GENERATION_TYPE, generatedValue.getStrategy(), annotationValueList + ); + + return create( GENERATED_VALUE, target, annotationValueList ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/IndexBuilder.java similarity index 81% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilder.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/IndexBuilder.java index 90e19ce82fb4..631cfe1b9888 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/IndexBuilder.java @@ -21,9 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.source.internal.jandex; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -31,35 +32,37 @@ import org.hibernate.AssertionFailure; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.xml.filter.IndexedAnnotationFilter; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.jandex.filter.IndexedAnnotationFilter; import org.hibernate.service.ServiceRegistry; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; -import org.jboss.logging.Logger; +import org.jboss.jandex.IndexView; /** * @author Strong Liu */ public class IndexBuilder { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - IndexBuilder.class.getName() - ); - private Map> annotations; - private Map> subclasses; - private Map> implementors; - private Map classes; - private Index index; - private Map>> classInfoAnnotationsMap; - private Map>> indexedClassInfoAnnotationsMap; - private ServiceRegistry serviceRegistry; + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( IndexBuilder.class ); - IndexBuilder(Index index, ServiceRegistry serviceRegistry) { + private IndexView index; + private final ServiceRegistry serviceRegistry; + + private final Map> annotations; + private final Map> subclasses; + private final Map> implementors; + private final Map classes; + private final Map>> classInfoAnnotationsMap; + private final Map>> indexedClassInfoAnnotationsMap; + + public IndexBuilder(IndexView index, ServiceRegistry serviceRegistry) { this.index = index; this.serviceRegistry = serviceRegistry; this.annotations = new HashMap>(); @@ -72,13 +75,13 @@ public class IndexBuilder { /** * Build new {@link Index} with mocked annotations from orm.xml. - * This method should be only called once per {@org.hibernate.metamodel.source.annotations.xml.mocker.IndexBuilder IndexBuilder} instance. + * This method should be only called once per {@link IndexBuilder} instance. * * @param globalDefaults Global defaults from , or null. * * @return Index. */ - Index build(EntityMappingsMocker.Default globalDefaults) { + public Index build(EntityMappingsMocker.Default globalDefaults) { //merge annotations that not overrided by xml into the new Index for ( ClassInfo ci : index.getKnownClasses() ) { DotName name = ci.name(); @@ -86,17 +89,19 @@ Index build(EntityMappingsMocker.Default globalDefaults) { //this class has been overrided by orm.xml continue; } - if ( ci.annotations() != null && !ci.annotations().isEmpty() ) { + ClassInfo mockedClassInfo = createClassInfo( name.toString() ); + if ( CollectionHelper.isNotEmpty( ci.annotations() ) ) { Map> tmp = new HashMap>( ci.annotations() ); DefaultConfigurationHelper.INSTANCE.applyDefaults( tmp, globalDefaults ); mergeAnnotationMap( tmp, annotations ); - classes.put( name, ci ); - if ( ci.superName() != null ) { - addSubClasses( ci.superName(), ci ); - } - if ( ci.interfaces() != null && ci.interfaces().length > 0 ) { - addImplementors( ci.interfaces(), ci ); - } + classInfoAnnotationsMap.get( name ).putAll( tmp ); +// classes.put( name, ci ); +// if ( ci.superName() != null ) { +// addSubClasses( ci.superName(), ci ); +// } +// if ( CollectionHelper.isNotEmpty( ci.interfaces() ) ) { +// addImplementors( ci.interfaces(), ci ); +// } } } return Index.create( @@ -166,9 +171,9 @@ public ClassInfo getIndexedClassInfo(DotName name) { void collectGlobalConfigurationFromIndex(GlobalAnnotations globalAnnotations) { for ( DotName annName : DefaultConfigurationHelper.GLOBAL_ANNOTATIONS ) { - List annotationInstanceList = index.getAnnotations( annName ); - if ( MockHelper.isNotEmpty( annotationInstanceList ) ) { - globalAnnotations.addIndexedAnnotationInstance( annotationInstanceList ); + Collection annotationInstances = index.getAnnotations( annName ); + if ( CollectionHelper.isNotEmpty( annotationInstances ) ) { + globalAnnotations.addIndexedAnnotationInstance( annotationInstances ); } } globalAnnotations.filterIndexedAnnotations(); @@ -218,16 +223,29 @@ ServiceRegistry getServiceRegistry() { return serviceRegistry; } - ClassInfo createClassInfo(String className) { + ClassInfo createClassInfo(String className, String optionalPerfix){ if ( StringHelper.isEmpty( className ) ) { throw new AssertionFailure( "Class Name used to create ClassInfo is empty." ); } + + ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + + Class clazz = null; + try { + clazz = classLoaderService.classForName( className ); + } + catch ( ClassLoadingException e ) { + if ( StringHelper.isNotEmpty( optionalPerfix ) ) { + className = StringHelper.qualify( optionalPerfix, className ); + clazz = classLoaderService.classForName( className ); + } + } DotName classDotName = DotName.createSimple( className ); if ( classes.containsKey( classDotName ) ) { //classInfoAnnotationsMap.put( classDotName, new HashMap>(classes.get( classDotName ).annotations()) ); return classes.get( classDotName ); } - Class clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( className ); + DotName superName = null; DotName[] interfaces = null; short access_flag; @@ -262,6 +280,10 @@ ClassInfo createClassInfo(String className) { return classInfo; } + ClassInfo createClassInfo(String className) { + return createClassInfo( className, null ); + } + private void addSubClasses(DotName superClassDotName, ClassInfo classInfo) { if ( superClassDotName != null ) { List classInfoList = subclasses.get( superClassDotName ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ListenerMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ListenerMocker.java new file mode 100644 index 000000000000..6a81959a256c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ListenerMocker.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListener; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners; +import org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * {@link javax.persistence.EntityListeners @EntityListeners} mocker + * + * @author Strong Liu + */ +public class ListenerMocker extends AbstractMocker { + private final ClassInfo classInfo; + + ListenerMocker(IndexBuilder indexBuilder, ClassInfo classInfo) { + super( indexBuilder ); + this.classInfo = classInfo; + } + + AnnotationInstance parse(JaxbEntityListeners entityListeners) { + if ( entityListeners.getEntityListener().isEmpty() ) { + throw new MappingException( "No child element of found under ." ); + } + List annotationValueList = new ArrayList( 1 ); + List clazzNameList = new ArrayList( entityListeners.getEntityListener().size() ); + for ( JaxbEntityListener listener : entityListeners.getEntityListener() ) { + MockHelper.addToCollectionIfNotNull( clazzNameList, listener.getClazz() ); + parseEntityListener( listener, clazzNameList ); + } + MockHelper.classArrayValue( "value", clazzNameList, annotationValueList, indexBuilder.getServiceRegistry() ); + return create( ENTITY_LISTENERS, classInfo, annotationValueList ); + } + + private void parseEntityListener(JaxbEntityListener listener, List clazzNameList) { + String clazz = listener.getClazz(); + String defaultPackageName = classInfo!=null ? StringHelper.qualifier(classInfo.name().toString()) : null; + ClassInfo tempClassInfo = indexBuilder.createClassInfo( clazz,defaultPackageName ); + if ( !clazz.equals( tempClassInfo.name().toString() ) ) { + clazzNameList.remove( clazz ); + clazzNameList.add( tempClassInfo.name().toString() ); + } + ListenerMocker mocker = createListenerMocker( indexBuilder, tempClassInfo ); + mocker.parse( listener.getPostLoad(), POST_LOAD ); + mocker.parse( listener.getPostPersist(), POST_PERSIST ); + mocker.parse( listener.getPostRemove(), POST_REMOVE ); + mocker.parse( listener.getPostUpdate(), POST_UPDATE ); + mocker.parse( listener.getPrePersist(), PRE_PERSIST ); + mocker.parse( listener.getPreRemove(), PRE_REMOVE ); + mocker.parse( listener.getPreUpdate(), PRE_UPDATE ); + indexBuilder.finishEntityObject( tempClassInfo.name(), null ); + } + + protected ListenerMocker createListenerMocker(IndexBuilder indexBuilder, ClassInfo classInfo) { + return new ListenerMocker( indexBuilder, classInfo ); + } + AnnotationInstance parse(LifecycleCallback callback, DotName target) { + if ( callback == null ) { + return null; + } + return create( target, getListenerTarget( callback.getMethodName() ) ); + } + private AnnotationTarget getListenerTarget(String methodName) { + return MockHelper.getTarget( + indexBuilder.getServiceRegistry(), classInfo, methodName, MockHelper.TargetType.METHOD + ); + } + + @Override + protected AnnotationInstance push(AnnotationInstance annotationInstance) { + if ( annotationInstance != null && annotationInstance.target() != null ) { + indexBuilder.addAnnotationInstance( classInfo.name(), annotationInstance ); + } + return annotationInstance; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ManyToManyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ManyToManyMocker.java new file mode 100644 index 000000000000..f880e96b56f2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ManyToManyMocker.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbManyToMany; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class ManyToManyMocker extends PropertyMocker { + private final JaxbManyToMany manyToMany; + + ManyToManyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbManyToMany manyToMany) { + super( indexBuilder, classInfo, defaults ); + this.manyToMany = manyToMany; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return manyToMany; + } + + @Override + protected void processExtra() { + List annotationValueList = new ArrayList(); + MockHelper.classValue( + "targetEntity", manyToMany.getTargetEntity(), annotationValueList, indexBuilder.getServiceRegistry() + ); + MockHelper.enumValue( "fetch", FETCH_TYPE, manyToMany.getFetch(), annotationValueList ); + MockHelper.stringValue( "mappedBy", manyToMany.getMappedBy(), annotationValueList ); + MockHelper.cascadeValue( "cascade", manyToMany.getCascade(), isDefaultCascadePersist(), annotationValueList ); + create( MANY_TO_MANY, annotationValueList ); + parseMapKeyClass( manyToMany.getMapKeyClass(), getTarget() ); + parseMapKeyTemporal( manyToMany.getMapKeyTemporal(), getTarget() ); + parseMapKeyEnumerated( manyToMany.getMapKeyEnumerated(), getTarget() ); + parseMapKey( manyToMany.getMapKey(), getTarget() ); + parseAttributeOverrides( manyToMany.getMapKeyAttributeOverride(), getTarget() ); + parseMapKeyJoinColumnList( manyToMany.getMapKeyJoinColumn(), getTarget() ); + parseOrderColumn( manyToMany.getOrderColumn(), getTarget() ); + parseJoinTable( manyToMany.getJoinTable(), getTarget() ); + if ( manyToMany.getOrderBy() != null ) { + create( ORDER_BY, MockHelper.stringValueArray( "value", manyToMany.getOrderBy() ) ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToOneMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ManyToOneMocker.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToOneMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ManyToOneMocker.java index c3dca779a1fe..f6043d8e5f79 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/ManyToOneMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/ManyToOneMocker.java @@ -21,13 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.source.internal.jandex; import java.util.ArrayList; import java.util.List; -import org.hibernate.internal.jaxb.mapping.orm.JaxbAccessType; -import org.hibernate.internal.jaxb.mapping.orm.JaxbManyToOne; +import org.hibernate.metamodel.source.internal.jaxb.JaxbManyToOne; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; @@ -35,8 +35,8 @@ /** * @author Strong Liu */ -class ManyToOneMocker extends PropertyMocker { - private JaxbManyToOne manyToOne; +public class ManyToOneMocker extends PropertyMocker { + private final JaxbManyToOne manyToOne; ManyToOneMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbManyToOne manyToOne) { super( indexBuilder, classInfo, defaults ); @@ -44,8 +44,8 @@ class ManyToOneMocker extends PropertyMocker { } @Override - protected String getFieldName() { - return manyToOne.getName(); + protected PersistentAttribute getPersistentAttribute() { + return manyToOne; } @Override @@ -58,8 +58,8 @@ protected void processExtra() { MockHelper.booleanValue( "optional", manyToOne.isOptional(), annotationValueList ); MockHelper.cascadeValue( "cascade", manyToOne.getCascade(), isDefaultCascadePersist(), annotationValueList ); create( MANY_TO_ONE, annotationValueList ); - parserJoinColumnList( manyToOne.getJoinColumn(), getTarget() ); - parserJoinTable( manyToOne.getJoinTable(), getTarget() ); + parseJoinColumnList( manyToOne.getJoinColumn(), getTarget() ); + parseJoinTable( manyToOne.getJoinTable(), getTarget() ); if ( manyToOne.getMapsId() != null ) { create( MAPS_ID, MockHelper.stringValueArray( "value", manyToOne.getMapsId() ) ); } @@ -67,14 +67,4 @@ protected void processExtra() { create( ID ); } } - - @Override - protected JaxbAccessType getAccessType() { - return manyToOne.getAccess(); - } - - @Override - protected void setAccessType(JaxbAccessType accessType) { - manyToOne.setAccess( accessType ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/MappedSuperclassMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/MappedSuperclassMocker.java new file mode 100644 index 000000000000..9960906cca59 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/MappedSuperclassMocker.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityListeners; +import org.hibernate.metamodel.source.internal.jaxb.JaxbIdClass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMappedSuperclass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostLoad; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostPersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPostUpdate; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPrePersist; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreRemove; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPreUpdate; +import org.hibernate.metamodel.source.internal.jaxb.ManagedType; + +/** + * Mock to {@link javax.persistence.MappedSuperclass @MappedSuperClass} + * + * @author Strong Liu + */ +public class MappedSuperclassMocker extends AbstractEntityObjectMocker { + private JaxbMappedSuperclass mappedSuperclass; + + MappedSuperclassMocker(IndexBuilder indexBuilder, JaxbMappedSuperclass mappedSuperclass, EntityMappingsMocker.Default defaults) { + super( indexBuilder, defaults ); + this.mappedSuperclass = mappedSuperclass; + } + + @Override + protected ManagedType getEntityElement() { + return mappedSuperclass; + } + + @Override + protected void processExtra() { + create( MAPPED_SUPERCLASS ); + } + + @Override + protected JaxbAttributes getAttributes() { + return mappedSuperclass.getAttributes(); + } + @Override + protected boolean isExcludeDefaultListeners() { + return mappedSuperclass.getExcludeDefaultListeners() != null; + } + + @Override + protected boolean isExcludeSuperclassListeners() { + return mappedSuperclass.getExcludeSuperclassListeners() != null; + } + + @Override + protected JaxbIdClass getIdClass() { + return mappedSuperclass.getIdClass(); + } + + @Override + protected JaxbEntityListeners getEntityListeners() { + return mappedSuperclass.getEntityListeners(); + } + + @Override + protected JaxbPrePersist getPrePersist() { + return mappedSuperclass.getPrePersist(); + } + + @Override + protected JaxbPreRemove getPreRemove() { + return mappedSuperclass.getPreRemove(); + } + + @Override + protected JaxbPreUpdate getPreUpdate() { + return mappedSuperclass.getPreUpdate(); + } + + @Override + protected JaxbPostPersist getPostPersist() { + return mappedSuperclass.getPostPersist(); + } + + @Override + protected JaxbPostUpdate getPostUpdate() { + return mappedSuperclass.getPostUpdate(); + } + + @Override + protected JaxbPostRemove getPostRemove() { + return mappedSuperclass.getPostRemove(); + } + + @Override + protected JaxbPostLoad getPostLoad() { + return mappedSuperclass.getPostLoad(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MockHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/MockHelper.java similarity index 88% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MockHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/MockHelper.java index a2e71bdcc7c1..50edd406abc0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/MockHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/MockHelper.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.source.internal.jandex; import java.beans.Introspector; import java.lang.reflect.Field; @@ -29,12 +29,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import javax.persistence.CascadeType; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.mapping.orm.JaxbCascadeType; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.annotations.JPADotNames; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jaxb.JaxbCascadeType; import org.hibernate.service.ServiceRegistry; import org.jboss.jandex.AnnotationInstance; @@ -51,7 +53,7 @@ */ public class MockHelper { - static final AnnotationValue[] EMPTY_ANNOTATION_VALUE_ARRAY = new AnnotationValue[0]; + public static final AnnotationValue[] EMPTY_ANNOTATION_VALUE_ARRAY = new AnnotationValue[0]; static final Type[] EMPTY_TYPE_ARRAY = new Type[0]; /** @@ -62,7 +64,7 @@ public class MockHelper { * @param annotationValueList */ static void stringArrayValue(String name, List values, List annotationValueList) { - if ( isNotEmpty( values ) ) { + if ( CollectionHelper.isNotEmpty( values ) ) { AnnotationValue[] annotationValues = new AnnotationValue[values.size()]; for ( int j = 0; j < values.size(); j++ ) { annotationValues[j] = stringValue( "", values.get( j ) ); @@ -149,13 +151,11 @@ static void nestedAnnotationValue(String name, AnnotationInstance value, List classNameList, List list, ServiceRegistry serviceRegistry) { - if ( isNotEmpty( classNameList ) ) { + if ( CollectionHelper.isNotEmpty( classNameList ) ) { List clazzValueList = new ArrayList( classNameList.size() ); for ( String clazz : classNameList ) { @@ -172,7 +172,7 @@ name, toArray( clazzValueList ) public static AnnotationValue[] toArray(List list) { AnnotationValue[] values = EMPTY_ANNOTATION_VALUE_ARRAY; - if ( isNotEmpty( list ) ) { + if ( CollectionHelper.isNotEmpty( list ) ) { values = list.toArray( new AnnotationValue[list.size()] ); } return values; @@ -191,32 +191,26 @@ static void cascadeValue(String name, JaxbCascadeType cascadeType, boolean isCas enumList.add( javax.persistence.CascadeType.PERSIST ); } if ( cascadeType != null ) { - if ( cascadeType.getCascadeAll() != null ) { - enumList.add( javax.persistence.CascadeType.ALL ); - } - if ( cascadeType.getCascadePersist() != null && !isCascadePersistDefault ) { - enumList.add( javax.persistence.CascadeType.PERSIST ); - } - if ( cascadeType.getCascadeMerge() != null ) { - enumList.add( javax.persistence.CascadeType.MERGE ); - } - if ( cascadeType.getCascadeRemove() != null ) { - enumList.add( javax.persistence.CascadeType.REMOVE ); - } - if ( cascadeType.getCascadeRefresh() != null ) { - enumList.add( javax.persistence.CascadeType.REFRESH ); - } - if ( cascadeType.getCascadeDetach() != null ) { - enumList.add( javax.persistence.CascadeType.DETACH ); - } + addIfNotNull( cascadeType.getCascadeAll(), enumList, CascadeType.ALL ); + addIfNotNull( cascadeType.getCascadePersist(), enumList, CascadeType.PERSIST ); + addIfNotNull( cascadeType.getCascadeMerge(), enumList, CascadeType.MERGE ); + addIfNotNull( cascadeType.getCascadeRemove(), enumList, CascadeType.REMOVE ); + addIfNotNull( cascadeType.getCascadeRefresh(), enumList, CascadeType.REFRESH ); + addIfNotNull( cascadeType.getCascadeDetach(), enumList , CascadeType.DETACH ); } if ( !enumList.isEmpty() ) { MockHelper.enumArrayValue( name, JPADotNames.CASCADE_TYPE, enumList, annotationValueList ); } } + private static void addIfNotNull(Object expect, List enumList, CascadeType value) { + if ( expect != null ) { + enumList.add( value); + } + } + static void enumArrayValue(String name, DotName typeName, List valueList, List list) { - if ( isNotEmpty( valueList ) ) { + if ( CollectionHelper.isNotEmpty( valueList ) ) { List enumValueList = new ArrayList( valueList.size() ); for ( Enum e : valueList ) { @@ -270,11 +264,6 @@ else if ( t1.getClass() == MethodInfo.class ) { return false; } - public static boolean isNotEmpty(Collection collection) { - return collection != null && !collection.isEmpty(); - } - - static AnnotationInstance create(DotName name, AnnotationTarget target, List annotationValueList) { return create( name, target, toArray( annotationValueList ) @@ -283,7 +272,7 @@ name, target, toArray( annotationValueList ) } static String buildSafeClassName(String className, String defaultPackageName) { - if ( className.indexOf( '.' ) < 0 && StringHelper.isNotEmpty( defaultPackageName ) ) { + if ( className!= null && className.indexOf( '.' ) < 0 && StringHelper.isNotEmpty( defaultPackageName ) ) { className = StringHelper.qualify( defaultPackageName, className ); } return className; @@ -316,9 +305,9 @@ private static MethodInfo getMethodInfo(ClassInfo classInfo, Method method) { ); } - enum TargetType {METHOD, FIELD, PROPERTY} + public enum TargetType {METHOD, FIELD, PROPERTY} - static AnnotationTarget getTarget(ServiceRegistry serviceRegistry, ClassInfo classInfo, String name, TargetType type) { + public static AnnotationTarget getTarget(ServiceRegistry serviceRegistry, ClassInfo classInfo, String name, TargetType type) { Class clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( classInfo.toString() ); switch ( type ) { case FIELD: @@ -403,9 +392,9 @@ private static Method getMethod(Class theClass, String propertyName) { Method.setAccessible( methods, true ); for ( Method method : methods ) { // if the method has parameters, skip it - if ( method.getParameterTypes().length != 0 ) { - continue; - } +// if ( method.getParameterTypes().length != 0 ) { +// continue; +// } // if the method is a "bridge", skip it if ( method.isBridge() ) { continue; @@ -451,7 +440,7 @@ private static Type getType(Class clazz) { return Type.create( DotName.createSimple( clazz.getName() ), getTypeKind( clazz ) ); } - private static Type.Kind getTypeKind(Class clazz) { + public static Type.Kind getTypeKind(Class clazz) { Type.Kind kind; if ( clazz == Void.TYPE ) { kind = Type.Kind.VOID; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/OneToManyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/OneToManyMocker.java new file mode 100644 index 000000000000..dc38cdcdd717 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/OneToManyMocker.java @@ -0,0 +1,76 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbOneToMany; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class OneToManyMocker extends PropertyMocker { + private final JaxbOneToMany oneToMany; + + OneToManyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbOneToMany oneToMany) { + super( indexBuilder, classInfo, defaults ); + this.oneToMany = oneToMany; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return oneToMany; + } + + @Override + protected void processExtra() { + List annotationValueList = new ArrayList(); + MockHelper.classValue( + "targetEntity", MockHelper.buildSafeClassName( oneToMany.getTargetEntity(), getDefaults().getPackageName() ), annotationValueList, indexBuilder.getServiceRegistry() + ); + MockHelper.enumValue( "fetch", FETCH_TYPE, oneToMany.getFetch(), annotationValueList ); + MockHelper.stringValue( "mappedBy", oneToMany.getMappedBy(), annotationValueList ); + MockHelper.booleanValue( "orphanRemoval", oneToMany.isOrphanRemoval(), annotationValueList ); + MockHelper.cascadeValue( "cascade", oneToMany.getCascade(), isDefaultCascadePersist(), annotationValueList ); + create( ONE_TO_MANY, getTarget(), annotationValueList ); + parseAttributeOverrides( oneToMany.getMapKeyAttributeOverride(), getTarget() ); + parseMapKeyJoinColumnList( oneToMany.getMapKeyJoinColumn(), getTarget() ); + parseMapKey( oneToMany.getMapKey(), getTarget() ); + parseMapKeyColumn( oneToMany.getMapKeyColumn(), getTarget() ); + parseMapKeyClass( oneToMany.getMapKeyClass(), getTarget() ); + parseMapKeyTemporal( oneToMany.getMapKeyTemporal(), getTarget() ); + parseMapKeyEnumerated( oneToMany.getMapKeyEnumerated(), getTarget() ); + parseJoinColumnList( oneToMany.getJoinColumn(), getTarget() ); + parseOrderColumn( oneToMany.getOrderColumn(), getTarget() ); + parseJoinTable( oneToMany.getJoinTable(), getTarget() ); + if ( oneToMany.getOrderBy() != null ) { + create( ORDER_BY, getTarget(), MockHelper.stringValueArray( "value", oneToMany.getOrderBy() ) ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/OneToOneMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/OneToOneMocker.java new file mode 100644 index 000000000000..d36c6fe6ffa5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/OneToOneMocker.java @@ -0,0 +1,78 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbOneToOne; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class OneToOneMocker extends PropertyMocker { + private JaxbOneToOne oneToOne; + + OneToOneMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbOneToOne oneToOne) { + super( indexBuilder, classInfo, defaults ); + this.oneToOne = oneToOne; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return oneToOne; + } + + @Override + protected void processExtra() { + List annotationValueList = new ArrayList(); + MockHelper.classValue( + "targetEntity", + StringHelper.qualifyIfNot( getDefaults().getPackageName(), oneToOne.getTargetEntity() ), + annotationValueList, + indexBuilder.getServiceRegistry() + ); + MockHelper.enumValue( "fetch", FETCH_TYPE, oneToOne.getFetch(), annotationValueList ); + MockHelper.booleanValue( "optional", oneToOne.isOptional(), annotationValueList ); + MockHelper.booleanValue( "orphanRemoval", oneToOne.isOrphanRemoval(), annotationValueList ); + MockHelper.stringValue( "mappedBy", oneToOne.getMappedBy(), annotationValueList ); + MockHelper.cascadeValue( "cascade", oneToOne.getCascade(), isDefaultCascadePersist(), annotationValueList ); + create( ONE_TO_ONE, annotationValueList ); + + parsePrimaryKeyJoinColumnList( oneToOne.getPrimaryKeyJoinColumn(), getTarget() ); + parseJoinColumnList( oneToOne.getJoinColumn(), getTarget() ); + parseJoinTable( oneToOne.getJoinTable(), getTarget() ); + if ( oneToOne.getMapsId() != null ) { + create( MAPS_ID, MockHelper.stringValueArray( "value", oneToOne.getMapsId() ) ); + } + if ( oneToOne.isId() != null && oneToOne.isId() ) { + create( ID ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PersistenceMetadataMocker.java similarity index 88% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMocker.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PersistenceMetadataMocker.java index 02820e5c9849..ff3f6f494023 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PersistenceMetadataMocker.java @@ -1,10 +1,9 @@ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.source.internal.jandex; import java.util.HashMap; import java.util.Map; -import org.hibernate.internal.jaxb.mapping.orm.JaxbPersistenceUnitDefaults; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitDefaults; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; @@ -15,7 +14,7 @@ /** * @author Strong Liu */ -class PersistenceMetadataMocker extends AbstractMocker { +public class PersistenceMetadataMocker extends AbstractMocker { private final JaxbPersistenceUnitDefaults persistenceUnitDefaults; private final GlobalAnnotations globalAnnotations = new GlobalAnnotations(); /** @@ -49,12 +48,13 @@ class PersistenceMetadataMocker extends AbstractMocker { * NOTE: These mocked annotations do not have {@link AnnotationTarget target}. */ final void process() { - parserAccessType( persistenceUnitDefaults.getAccess(), null ); + parseAccessType( persistenceUnitDefaults.getAccess(), null ); if ( persistenceUnitDefaults.getDelimitedIdentifiers() != null ) { create( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS, null ); } if ( persistenceUnitDefaults.getEntityListeners() != null ) { - new DefaultListenerMocker( indexBuilder, null ).parser( persistenceUnitDefaults.getEntityListeners() ); + + new DefaultListenerMocker( indexBuilder, null ).parse( persistenceUnitDefaults.getEntityListeners() ); } indexBuilder.finishGlobalConfigurationMocking( globalAnnotations ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PropertyMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PropertyMocker.java new file mode 100644 index 000000000000..a03118b9361e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PropertyMocker.java @@ -0,0 +1,256 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.AccessType; +import javax.persistence.EnumType; +import javax.persistence.TemporalType; + +import org.hibernate.HibernateException; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMapKey; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMapKeyClass; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMapKeyColumn; +import org.hibernate.metamodel.source.internal.jaxb.JaxbMapKeyJoinColumn; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; + +/** + * @author Strong Liu + */ +public abstract class PropertyMocker extends AnnotationMocker { + protected ClassInfo classInfo; + private AnnotationTarget target; + + PropertyMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults) { + super( indexBuilder, defaults ); + this.classInfo = classInfo; + } + + protected abstract PersistentAttribute getPersistentAttribute(); + protected abstract void processExtra(); + + @Override + protected DotName getTargetName() { + return classInfo.name(); + } + + protected void resolveTarget() { + AccessType xmlDefinedAccessType = getPersistentAttribute().getAccess(); + if ( xmlDefinedAccessType == null ) { + // could be PU default + xmlDefinedAccessType = getDefaults().getAccess(); + } + + if ( xmlDefinedAccessType == null ) { + // attribute in orm.xml did not define access + + //attribute in the entity class has @Access + AccessType accessType = AccessHelper.getAccessFromAttributeAnnotation( + getTargetName(), + getPersistentAttribute().getName(), + indexBuilder + ); + if ( accessType == null ) { + accessType = AccessHelper.getEntityAccess( getTargetName(), indexBuilder ); + } + if ( accessType == null ) { + accessType = AccessHelper.getAccessFromIdPosition( getTargetName(), indexBuilder ); + } + if (accessType == null ) { + //this should only for determin @Id position + accessType = AccessHelper.getAccessFromDefault( indexBuilder ); + } + if ( accessType == null ) { + accessType = AccessType.PROPERTY; + + } + getPersistentAttribute().setAccess( accessType ); + } + else { + // attribute in orm.xml did define access + List accessTypeValueList = new ArrayList(); + MockHelper.enumValue( "value", ACCESS_TYPE, xmlDefinedAccessType, accessTypeValueList ); + create( ACCESS, accessTypeValueList ); + } + } + + @Override + protected AnnotationTarget getTarget() { + if ( target == null ) { + target = getTargetFromAttributeAccessType( getPersistentAttribute().getAccess() ); + } + return target; + } + + protected AnnotationTarget getTargetFromAttributeAccessType(AccessType accessType) { + if ( accessType == null ) { + throw new IllegalArgumentException( "access type can't be null." ); + } + switch ( accessType ) { + case FIELD: + return MockHelper.getTarget( + indexBuilder.getServiceRegistry(), + classInfo, + getPersistentAttribute().getName(), + MockHelper.TargetType.FIELD + ); + case PROPERTY: + return MockHelper.getTarget( + indexBuilder.getServiceRegistry(), + classInfo, + getPersistentAttribute().getName(), + MockHelper.TargetType.PROPERTY + ); + default: + throw new HibernateException( "can't determin access type [" + accessType + "]" ); + } + } + + + @Override + final void process() { + resolveTarget(); + processExtra(); + } + + protected AnnotationInstance parseMapKeyColumn(JaxbMapKeyColumn mapKeyColumn, AnnotationTarget target) { + if ( mapKeyColumn == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", mapKeyColumn.getName(), annotationValueList ); + MockHelper.stringValue( "columnDefinition", mapKeyColumn.getColumnDefinition(), annotationValueList ); + MockHelper.stringValue( "table", mapKeyColumn.getTable(), annotationValueList ); + MockHelper.booleanValue( "nullable", mapKeyColumn.isNullable(), annotationValueList ); + MockHelper.booleanValue( "insertable", mapKeyColumn.isInsertable(), annotationValueList ); + MockHelper.booleanValue( "updatable", mapKeyColumn.isUpdatable(), annotationValueList ); + MockHelper.booleanValue( "unique", mapKeyColumn.isUnique(), annotationValueList ); + MockHelper.integerValue( "length", mapKeyColumn.getLength(), annotationValueList ); + MockHelper.integerValue( "precision", mapKeyColumn.getPrecision(), annotationValueList ); + MockHelper.integerValue( "scale", mapKeyColumn.getScale(), annotationValueList ); + return create( MAP_KEY_COLUMN, target, annotationValueList ); + } + + protected AnnotationInstance parseMapKeyClass(JaxbMapKeyClass mapKeyClass, AnnotationTarget target) { + if ( mapKeyClass == null ) { + return null; + } + return create( + MAP_KEY_CLASS, target, MockHelper.classValueArray( + "value", mapKeyClass.getClazz(), indexBuilder.getServiceRegistry() + ) + ); + } + + protected AnnotationInstance parseMapKeyTemporal(TemporalType temporalType, AnnotationTarget target) { + if ( temporalType == null ) { + return null; + } + return create( + MAP_KEY_TEMPORAL, target, + MockHelper.enumValueArray( "value", TEMPORAL_TYPE, temporalType ) + ); + } + + protected AnnotationInstance parseMapKeyEnumerated(EnumType enumType, AnnotationTarget target) { + if ( enumType == null ) { + return null; + } + return create( + MAP_KEY_ENUMERATED, target, + MockHelper.enumValueArray( "value", ENUM_TYPE, enumType ) + ); + } + + protected AnnotationInstance parseMapKey(JaxbMapKey mapKey, AnnotationTarget target) { + if ( mapKey == null ) { + return null; + } + return create( MAP_KEY, target, MockHelper.stringValueArray( "name", mapKey.getName() ) ); + } + + private AnnotationValue[] nestedMapKeyJoinColumnList(String name, List columns, List annotationValueList) { + if ( CollectionHelper.isNotEmpty( columns ) ) { + AnnotationValue[] values = new AnnotationValue[columns.size()]; + for ( int i = 0; i < columns.size(); i++ ) { + AnnotationInstance annotationInstance = parseMapKeyJoinColumn( columns.get( i ), null ); + values[i] = MockHelper.nestedAnnotationValue( + "", annotationInstance + ); + } + MockHelper.addToCollectionIfNotNull( + annotationValueList, AnnotationValue.createArrayValue( name, values ) + ); + return values; + } + return MockHelper.EMPTY_ANNOTATION_VALUE_ARRAY; + } + + protected AnnotationInstance parseMapKeyJoinColumnList(List joinColumnList, AnnotationTarget target) { + if ( CollectionHelper.isNotEmpty( joinColumnList ) ) { + if ( joinColumnList.size() == 1 ) { + return parseMapKeyJoinColumn( joinColumnList.get( 0 ), target ); + } + else { + AnnotationValue[] values = nestedMapKeyJoinColumnList( "value", joinColumnList, null ); + return create( + MAP_KEY_JOIN_COLUMNS, + target, + values + ); + } + } + return null; + + } + + //@MapKeyJoinColumn + private AnnotationInstance parseMapKeyJoinColumn(JaxbMapKeyJoinColumn column, AnnotationTarget target) { + if ( column == null ) { + return null; + } + List annotationValueList = new ArrayList(); + MockHelper.stringValue( "name", column.getName(), annotationValueList ); + MockHelper.stringValue( "columnDefinition", column.getColumnDefinition(), annotationValueList ); + MockHelper.stringValue( "table", column.getTable(), annotationValueList ); + MockHelper.stringValue( + "referencedColumnName", column.getReferencedColumnName(), annotationValueList + ); + MockHelper.booleanValue( "unique", column.isUnique(), annotationValueList ); + MockHelper.booleanValue( "nullable", column.isNullable(), annotationValueList ); + MockHelper.booleanValue( "insertable", column.isInsertable(), annotationValueList ); + MockHelper.booleanValue( "updatable", column.isUpdatable(), annotationValueList ); + return create( MAP_KEY_JOIN_COLUMN, target, annotationValueList ); + } + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/PseudoJpaDotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PseudoJpaDotNames.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/PseudoJpaDotNames.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PseudoJpaDotNames.java index de9a703dba1f..5da6e29758b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/PseudoJpaDotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/PseudoJpaDotNames.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.source.internal.jandex; import org.jboss.jandex.DotName; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/TransientMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/TransientMocker.java new file mode 100644 index 000000000000..5f5e21fcb260 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/TransientMocker.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import javax.persistence.AccessType; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbTransient; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class TransientMocker extends PropertyMocker { + private final JaxbTransient transientObj; + private final PersistentAttribute wrapper; + + TransientMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, final JaxbTransient transientObj) { + super( indexBuilder, classInfo, defaults ); + this.transientObj = transientObj; + this.wrapper = new PersistentAttribute() { + @Override + public String getName() { + return transientObj.getName(); + } + + @Override + public AccessType getAccess() { + return AccessType.FIELD; + } + + @Override + public void setAccess(AccessType accessType) { + } + + @Override + public String getCustomAccess() { + return null; + } + + @Override + public void setCustomAccess(String customAccess) { + + } + }; + } + + @Override + protected void processExtra() { + create( TRANSIENT ); + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return wrapper; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/Unifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/Unifier.java new file mode 100644 index 000000000000..4977852292d7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/Unifier.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import java.util.List; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.xml.spi.BindResult; + +import org.jboss.jandex.IndexView; + +/** + * Responsible for consolidating mapping information supplied by annotations and mapping information + * supplied by XML into a unified view. + *

      + * Ultimately we are building a Jandex {@link org.jboss.jandex.IndexView} which is a de-typed (and + * classloading safe!) representation of annotations. We add virtual annotation information into the + * Jandex to represent XML supplied information. + * + * @author Steve Ebersole + * @author Strong Liu + */ +public class Unifier { + private static final CoreMessageLogger log = CoreLogging.messageLogger( Unifier.class ); + + // todo : per Jason, it is bad if we create a CompositeIndex where multiple of the aggregated indexes contain the same classes. + + public static IndexView unify( + IndexView initialJandex, + List> xmlBindings, + ServiceRegistry serviceRegistry) { + if ( xmlBindings == null || xmlBindings.isEmpty() ) { + // if there is no XML information, just return the original index + return initialJandex; + } + + JaxbPersistenceUnitMetadata persistenceUnitMetadata = null; + + for ( BindResult xmlBinding : xmlBindings ) { + if ( xmlBinding.getRoot().getPersistenceUnitMetadata() != null ) { + if ( persistenceUnitMetadata == null ) { + log.debugf( "Using located in %s", xmlBinding.getOrigin() ); + persistenceUnitMetadata = xmlBinding.getRoot().getPersistenceUnitMetadata(); + } + else { + // todo : parameterize duplicateMetadata() to accept the origin + log.duplicateMetadata(); + log.debugf( + "Encountered in %s after previously " + + "encountered one; keeping original", + xmlBinding.getOrigin() + ); + } + } + } + + // for now, simply hook into the existing code... + return new EntityMappingsMocker( xmlBindings, initialJandex, serviceRegistry ).mockNewIndex(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/VersionMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/VersionMocker.java new file mode 100644 index 000000000000..a237aa0cb732 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/VersionMocker.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbVersion; +import org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute; + +import org.jboss.jandex.ClassInfo; + +/** + * @author Strong Liu + */ +public class VersionMocker extends PropertyMocker { + private final JaxbVersion version; + + VersionMocker(IndexBuilder indexBuilder, ClassInfo classInfo, EntityMappingsMocker.Default defaults, JaxbVersion version) { + super( indexBuilder, classInfo, defaults ); + this.version = version; + } + + @Override + protected PersistentAttribute getPersistentAttribute() { + return version; + } + + @Override + protected void processExtra() { + create( VERSION ); + parseColumn( version.getColumn(), getTarget() ); + parseTemporalType( version.getTemporal(), getTarget() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/AbstractAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/AbstractAnnotationFilter.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/AbstractAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/AbstractAnnotationFilter.java index ff1530e03a8a..407adad531ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/AbstractAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/AbstractAnnotationFilter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.source.internal.jandex.filter; import java.util.Arrays; import java.util.HashSet; @@ -29,11 +29,11 @@ import java.util.Map; import java.util.Set; -import org.hibernate.metamodel.source.annotations.xml.mocker.IndexBuilder; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; + /** * @author Strong Liu */ @@ -76,4 +76,4 @@ protected void process(DotName annName, AnnotationInstance annotationInstance, L protected DotName[] targetAnnotation() { return EMPTY_DOTNAME_ARRAY; } -} +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/ExclusiveAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/ExclusiveAnnotationFilter.java similarity index 91% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/ExclusiveAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/ExclusiveAnnotationFilter.java index a666ffadc20f..2492aeed42fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/ExclusiveAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/ExclusiveAnnotationFilter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.source.internal.jandex.filter; import java.util.ArrayList; import java.util.Collections; @@ -31,23 +31,24 @@ import java.util.Map; import java.util.Set; -import org.hibernate.metamodel.source.annotations.xml.mocker.MockHelper; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.DotName; +import org.hibernate.metamodel.source.internal.jandex.MockHelper; + /** * @author Strong Liu */ class ExclusiveAnnotationFilter extends AbstractAnnotationFilter { public static ExclusiveAnnotationFilter INSTANCE = new ExclusiveAnnotationFilter(); - private DotName[] targetNames; - private List exclusiveGroupList; + private final DotName[] targetNames; + private final List exclusiveGroupList; private ExclusiveAnnotationFilter() { - this.exclusiveGroupList = getExclusiveGroupList(); + this.exclusiveGroupList = new ArrayList(); + fillExclusiveGroupList(); Set names = new HashSet(); for ( ExclusiveGroup group : exclusiveGroupList ) { names.addAll( group.getNames() ); @@ -55,9 +56,7 @@ private ExclusiveAnnotationFilter() { targetNames = names.toArray( new DotName[names.size()] ); } - private List getExclusiveGroupList() { - if ( exclusiveGroupList == null ) { - exclusiveGroupList = new ArrayList(); + private void fillExclusiveGroupList() { ExclusiveGroup group = new ExclusiveGroup(); group.add( ENTITY ); group.add( MAPPED_SUPERCLASS ); @@ -113,8 +112,6 @@ private List getExclusiveGroupList() { group.scope = Scope.ATTRIBUTE; exclusiveGroupList.add( group ); - } - return exclusiveGroupList; } @Override @@ -171,7 +168,7 @@ public Set getNames() { Scope scope = Scope.ATTRIBUTE; @Override - public Iterator iterator() { + public Iterator iterator() { return names.iterator(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/IndexedAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/IndexedAnnotationFilter.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/IndexedAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/IndexedAnnotationFilter.java index 9a2aaeac5226..67baced47ff9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/IndexedAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/IndexedAnnotationFilter.java @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.source.internal.jandex.filter; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.xml.mocker.IndexBuilder; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/NameAnnotationFilter.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameAnnotationFilter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/NameAnnotationFilter.java index 5635134bca06..0c15509609d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/xml/filter/NameAnnotationFilter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/NameAnnotationFilter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.filter; +package org.hibernate.metamodel.source.internal.jandex.filter; import java.util.List; @@ -39,20 +39,20 @@ protected void process(DotName annName, AnnotationInstance annotationInstance, L indexedAnnotationInstanceList.clear(); } - public static NameTargetAnnotationFilter INSTANCE = new NameTargetAnnotationFilter(); - + public static NameAnnotationFilter INSTANCE = new NameAnnotationFilter(); + private static final DotName[] TARGET_ANNOTATIONS = new DotName[] { + CACHEABLE, + TABLE, + EXCLUDE_DEFAULT_LISTENERS, + EXCLUDE_SUPERCLASS_LISTENERS, + ID_CLASS, + INHERITANCE, + DISCRIMINATOR_VALUE, + DISCRIMINATOR_COLUMN, + ENTITY_LISTENERS + }; @Override protected DotName[] targetAnnotation() { - return new DotName[] { - CACHEABLE, - TABLE, - EXCLUDE_DEFAULT_LISTENERS, - EXCLUDE_SUPERCLASS_LISTENERS, - ID_CLASS, - INHERITANCE, - DISCRIMINATOR_VALUE, - DISCRIMINATOR_COLUMN, - ENTITY_LISTENERS - }; + return TARGET_ANNOTATIONS; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/NameTargetAnnotationFilter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/NameTargetAnnotationFilter.java new file mode 100644 index 000000000000..305114bc4bb7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/filter/NameTargetAnnotationFilter.java @@ -0,0 +1,94 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jandex.filter; + +import java.util.Iterator; +import java.util.List; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.DotName; + +import org.hibernate.metamodel.source.internal.jandex.MockHelper; + +/** + * @author Strong Liu + */ +class NameTargetAnnotationFilter extends AbstractAnnotationFilter { + @Override + protected void process(DotName annName, AnnotationInstance annotationInstance, List indexedAnnotationInstanceList) { + AnnotationTarget target = annotationInstance.target(); + + for ( Iterator iter = indexedAnnotationInstanceList.iterator(); iter.hasNext(); ) { + AnnotationInstance ann = iter.next(); + if ( MockHelper.targetEquals( target, ann.target() ) ) { + iter.remove(); + } + } + } + + public static NameTargetAnnotationFilter INSTANCE = new NameTargetAnnotationFilter(); + private static final DotName[] TARGET_ANNOTATIONS = new DotName[] { + LOB, + ID, + BASIC, + GENERATED_VALUE, + VERSION, + TRANSIENT, + ACCESS, + POST_LOAD, + POST_PERSIST, + POST_REMOVE, + POST_UPDATE, + PRE_PERSIST, + PRE_REMOVE, + PRE_UPDATE, + EMBEDDED_ID, + EMBEDDED, + MANY_TO_ONE, + MANY_TO_MANY, + ONE_TO_ONE, + ONE_TO_MANY, + ELEMENT_COLLECTION, + COLLECTION_TABLE, + COLUMN, + ENUMERATED, + JOIN_TABLE, + TEMPORAL, + ORDER_BY, + ORDER_COLUMN, + JOIN_COLUMN, + JOIN_COLUMNS, + MAPS_ID, + MAP_KEY_TEMPORAL, + MAP_KEY, + MAP_KEY_CLASS, + MAP_KEY_COLUMN, + MAP_KEY_ENUMERATED + }; + @Override + protected DotName[] targetAnnotation() { + return TARGET_ANNOTATIONS; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/AttributesContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/AttributesContainer.java new file mode 100644 index 000000000000..7216175c458a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/AttributesContainer.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +import java.util.List; + +/** + * Common interface for JAXB bindings which are containers of attributes. + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface AttributesContainer { + + List getTransient(); + + List getBasic(); + + List getElementCollection(); + + List getEmbedded(); + + List getManyToMany(); + + List getManyToOne(); + + List getOneToMany(); + + List getOneToOne(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/LifecycleCallback.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/LifecycleCallback.java new file mode 100644 index 000000000000..1f800f892ec5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/LifecycleCallback.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +/** + * Common interface for all the JAXB bindings representing lifecycle callbacks. + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface LifecycleCallback { + public String getMethodName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/ManagedType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/ManagedType.java new file mode 100644 index 000000000000..2befc6630b10 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/ManagedType.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +import javax.persistence.AccessType; + +/** + * Common interface for JAXB bindings representing entities, mapped-superclasses and embeddables (JPA collective + * calls these "managed types" in terms of its Metamodel api). + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface ManagedType { + String getClazz(); + + void setClazz(String className); + + Boolean isMetadataComplete(); + + void setMetadataComplete(Boolean isMetadataComplete); + public AccessType getAccess(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/Parameterized.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/Parameterized.java new file mode 100644 index 000000000000..eea52887c8e0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/Parameterized.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +import java.util.List; + +/** + * @author Steve Ebersole + */ +public interface Parameterized { + public List getParam(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/PersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/PersistentAttribute.java new file mode 100644 index 000000000000..5879373a81c3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/PersistentAttribute.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +import javax.persistence.AccessType; + +/** + * Common interface for JAXB bindings that represent persistent attributes. + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface PersistentAttribute { + String getName(); + + AccessType getAccess(); + void setAccess(AccessType accessType); + + String getCustomAccess(); + void setCustomAccess(String customAccess); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/SchemaAware.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/SchemaAware.java new file mode 100644 index 000000000000..515d9dedf977 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/SchemaAware.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +/** + * Common interface for JAXB bindings that understand database schema (tables, sequences, etc). + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface SchemaAware { + String getSchema(); + + void setSchema(String schema); + + String getCatalog(); + + void setCatalog(String catalog); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/ToolingHintContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/ToolingHintContainer.java new file mode 100644 index 000000000000..0d647be6c7db --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/ToolingHintContainer.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb; + +import java.util.List; + +/** + * Common interface for JAXB bindings which are containers of tooling hints. + * + * @author Steve Ebersole + */ +public interface ToolingHintContainer { + public List getToolingHint(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/ComponentSourceElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/ComponentSourceElement.java new file mode 100644 index 000000000000..bfd35f4db905 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/ComponentSourceElement.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +/** + * @author Steve Ebersole + */ +public interface ComponentSourceElement extends MetaAttributeContainer { + public String getAccess(); + public String getClazz(); + public String getName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/EntityElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/EntityElement.java new file mode 100644 index 000000000000..1f7ad3bb1a06 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/EntityElement.java @@ -0,0 +1,74 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +import java.util.List; + +/** + * @author Steve Ebersole + */ +public interface EntityElement extends MetaAttributeContainer { + public String getName(); + public String getEntityName(); + + public boolean isAbstract(); + public Boolean isLazy(); + public String getProxy(); + public int getBatchSize(); + public boolean isDynamicInsert(); + public boolean isDynamicUpdate(); + public boolean isSelectBeforeUpdate(); + + public List getTuplizer(); + public String getPersister(); + + public JaxbLoaderElement getLoader(); + public JaxbSqlDmlElement getSqlInsert(); + public JaxbSqlDmlElement getSqlUpdate(); + public JaxbSqlDmlElement getSqlDelete(); + + public List getSynchronize(); + + public List getFetchProfile(); + + public List getResultset(); + + public List getSqlQuery(); + public List getQuery(); + + public List getProperty(); + public List getProperties(); + public List getManyToOne(); + public List getOneToOne(); + public List getComponent(); + public List getDynamicComponent(); + public List getAny(); + public List getMap(); + public List getSet(); + public List getList(); + public List getBag(); + public List getIdbag(); + public List getArray(); + public List getPrimitiveArray(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java new file mode 100644 index 000000000000..b9f68240d60e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java @@ -0,0 +1,822 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +import java.util.Date; + +import javax.persistence.FetchType; + +import org.hibernate.FlushMode; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.*; +import org.hibernate.metamodel.source.internal.jaxb.JaxbCacheElement; +import org.hibernate.xml.spi.Origin; + +import org.jboss.logging.Logger; + +/** + * Transforms a JAXB binding of a hbm.xml file into a unified orm.xml representation + * + * @author Steve Ebersole + */ +public class HbmXmlTransformer { + private static final Logger log = Logger.getLogger( HbmXmlTransformer.class ); + + /** + * Singleton access + */ + public static final HbmXmlTransformer INSTANCE = new HbmXmlTransformer(); + + private Origin origin; + private JaxbEntityMappings ormRoot; + + public JaxbEntityMappings transform(JaxbHibernateMapping hbmXmlMapping, Origin origin) { + this.origin = origin; + + ormRoot = new JaxbEntityMappings(); + ormRoot.setDescription( + "Hibernate orm.xml document auto-generated from legacy hbm.xml format via transformation " + + "(generated at " + new Date().toString() + ")" + ); + + final JaxbPersistenceUnitMetadata metadata = new JaxbPersistenceUnitMetadata(); + ormRoot.setPersistenceUnitMetadata( metadata ); + metadata.setDescription( + "Defines information which applies to the persistence unit overall, not just to this mapping file.\n\n" + + "This transformation only specifies xml-mapping-metadata-complete." + ); + + transferToolingHints( hbmXmlMapping, ormRoot ); + + ormRoot.setPackage( hbmXmlMapping.getPackage() ); + ormRoot.setSchema( hbmXmlMapping.getSchema() ); + ormRoot.setCatalog( hbmXmlMapping.getCatalog() ); + ormRoot.setCustomAccess( hbmXmlMapping.getDefaultAccess() ); + ormRoot.setDefaultCascade( hbmXmlMapping.getDefaultCascade() ); + ormRoot.setAutoImport( hbmXmlMapping.isAutoImport() ); + ormRoot.setDefaultLazy( hbmXmlMapping.isDefaultLazy() ); + + transferTypeDefs( hbmXmlMapping, ormRoot ); + transferIdentifierGenerators( hbmXmlMapping, ormRoot ); + transferFilterDefs( hbmXmlMapping, ormRoot ); + transferFetchProfiles( hbmXmlMapping, ormRoot ); + transferImports( hbmXmlMapping, ormRoot ); + + transferResultSetMappings( hbmXmlMapping, ormRoot ); + transferNamedQuery( hbmXmlMapping, ormRoot ); + transferNamedSqlQuery( hbmXmlMapping, ormRoot ); + + transferDatabaseObjects( hbmXmlMapping, ormRoot ); + + transferEntities( hbmXmlMapping, ormRoot ); + + return ormRoot; + } + + private void transferToolingHints(JaxbMetaContainerElement hbmMetaContainer, JaxbEntityMappings entityMappings) { + if ( hbmMetaContainer.getMeta().isEmpty() ) { + return; + } + + for ( JaxbMetaElement hbmMetaElement : hbmMetaContainer.getMeta() ) { + final JaxbHbmToolingHint toolingHint = new JaxbHbmToolingHint(); + entityMappings.getToolingHint().add( toolingHint ); + toolingHint.setName( hbmMetaElement.getName() ); + toolingHint.setInheritable( hbmMetaElement.isInheritable() ); + toolingHint.setValue( hbmMetaElement.getValue() ); + } + } + + private void transferTypeDefs(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getTypedef().isEmpty() ) { + return; + } + + for ( JaxbTypedefElement hbmXmlTypeDef : hbmXmlMapping.getTypedef() ) { + final JaxbHbmTypeDef typeDef = new JaxbHbmTypeDef(); + ormRoot.getTypeDef().add( typeDef ); + typeDef.setName( hbmXmlTypeDef.getName() ); + typeDef.setClazz( hbmXmlTypeDef.getClazz() ); + + if ( !hbmXmlTypeDef.getParam().isEmpty() ) { + for ( JaxbParamElement hbmParam : hbmXmlTypeDef.getParam() ) { + final JaxbHbmParam param = new JaxbHbmParam(); + typeDef.getParam().add( param ); + param.setName( hbmParam.getName() ); + param.setValue( hbmParam.getValue() ); + } + } + } + } + + private void transferFilterDefs(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getFilterDef().isEmpty() ) { + return; + } + + for ( JaxbFilterDefElement hbmFilterDef : hbmXmlMapping.getFilterDef() ) { + JaxbHbmFilterDef filterDef = new JaxbHbmFilterDef(); + ormRoot.getFilterDef().add( filterDef ); + filterDef.setName( hbmFilterDef.getName() ); + + boolean foundCondition = false; + for ( Object content : hbmFilterDef.getContent() ) { + if ( String.class.isInstance( content ) ) { + foundCondition = true; + filterDef.setCondition( (String) content ); + } + else { + JaxbFilterParamElement hbmFilterParam = (JaxbFilterParamElement) content; + JaxbHbmFilterDef.JaxbFilterParam param = new JaxbHbmFilterDef.JaxbFilterParam(); + filterDef.getFilterParam().add( param ); + param.setName( hbmFilterParam.getParameterName() ); + param.setType( hbmFilterParam.getParameterValueTypeName() ); + } + } + + if ( !foundCondition ) { + filterDef.setCondition( hbmFilterDef.getCondition() ); + } + } + } + + private void transferIdentifierGenerators(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getIdentifierGenerator().isEmpty() ) { + return; + } + + for ( JaxbIdentifierGeneratorElement hbmGenerator : hbmXmlMapping.getIdentifierGenerator() ) { + final JaxbHbmIdGeneratorDef generatorDef = new JaxbHbmIdGeneratorDef(); + ormRoot.getIdentifierGeneratorDef().add( generatorDef ); + generatorDef.setName( hbmGenerator.getName() ); + generatorDef.setClazz( hbmGenerator.getClazz() ); + } + } + + private void transferImports(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getImport().isEmpty() ) { + return; + } + + for ( JaxbImportElement hbmImport : hbmXmlMapping.getImport() ) { + final JaxbEntityMappings.JaxbImport ormImport = new JaxbEntityMappings.JaxbImport(); + ormRoot.getImport().add( ormImport ); + ormImport.setClazz( hbmImport.getClazz() ); + ormImport.setRename( hbmImport.getRename() ); + } + } + + private void transferResultSetMappings(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getResultset().isEmpty() ) { + return; + } + + // todo : implement this; or decide to not support it in transformation + log.debugf( "skipping hbm.xml definitions" ); + } + + private void transferFetchProfiles(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getFetchProfile().isEmpty() ) { + return; + } + + for ( JaxbFetchProfileElement hbmFetchProfile : hbmXmlMapping.getFetchProfile() ) { + final JaxbHbmFetchProfile fetchProfile = new JaxbHbmFetchProfile(); + ormRoot.getFetchProfile().add( fetchProfile ); + fetchProfile.setName( hbmFetchProfile.getName() ); + + if ( hbmFetchProfile.getFetch().isEmpty() ) { + // really this should be an error, right? + continue; + } + for ( JaxbFetchProfileElement.JaxbFetch hbmFetch : hbmFetchProfile.getFetch() ) { + final JaxbHbmFetchProfile.JaxbFetch fetch = new JaxbHbmFetchProfile.JaxbFetch(); + fetchProfile.getFetch().add( fetch ); + fetch.setEntity( hbmFetch.getEntity() ); + fetch.setAssociation( hbmFetch.getAssociation() ); + fetch.setStyle( hbmFetch.getStyle().value() ); + } + } + } + + private void transferNamedQuery(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getQuery().isEmpty() ) { + return; + } + + for ( JaxbQueryElement hbmQuery : hbmXmlMapping.getQuery() ) { + final JaxbNamedQuery query = new JaxbNamedQuery(); + ormRoot.getNamedQuery().add( query ); + query.setName( hbmQuery.getName() ); + query.setCacheable( hbmQuery.isCacheable() ); + query.setCacheMode( convert( hbmQuery.getCacheMode() ) ); + query.setCacheRegion( hbmQuery.getCacheRegion() ); + query.setComment( hbmQuery.getComment() ); + query.setFetchSize( hbmQuery.getFetchSize() ); + query.setFlushMode( interpret( hbmQuery.getFlushMode() ) ); + query.setFetchSize( hbmQuery.getFetchSize() ); + query.setReadOnly( hbmQuery.isReadOnly() ); + query.setTimeout( hbmQuery.getTimeout() ); + + // JaxbQueryElement#content elements can be either the query or parameters + for ( Object content : hbmQuery.getContent() ) { + if ( String.class.isInstance( content ) ) { + query.setQuery( (String) content ); + } + else { + final JaxbQueryParamElement hbmQueryParam = (JaxbQueryParamElement) content; + final JaxbQueryParamType queryParam = new JaxbQueryParamType(); + query.getQueryParam().add( queryParam ); + queryParam.setName( hbmQueryParam.getName() ); + queryParam.setType( hbmQueryParam.getType() ); + } + } + } + } + + private JaxbCacheModeType convert(JaxbCacheModeAttribute cacheMode) { + final String value = cacheMode == null ? null : cacheMode.value(); + if ( StringHelper.isEmpty( value ) ) { + return JaxbCacheModeType.NORMAL; + } + + return JaxbCacheModeType.fromValue( value ); + } + + private FlushMode interpret(JaxbFlushModeAttribute flushMode) { + final String value = flushMode == null ? null : flushMode.value(); + if ( StringHelper.isEmpty( value ) ) { + return null; + } + + return FlushMode.valueOf( value ); + } + + private void transferNamedSqlQuery(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + if ( hbmXmlMapping.getSqlQuery().isEmpty() ) { + return; + } + + for ( JaxbSqlQueryElement hbmQuery : hbmXmlMapping.getSqlQuery() ) { + final JaxbNamedNativeQuery query = new JaxbNamedNativeQuery(); + ormRoot.getNamedNativeQuery().add( query ); + query.setName( hbmQuery.getName() ); + query.setCacheable( hbmQuery.isCacheable() ); + query.setCacheMode( convert( hbmQuery.getCacheMode() ) ); + query.setCacheRegion( hbmQuery.getCacheRegion() ); + query.setComment( hbmQuery.getComment() ); + query.setFetchSize( hbmQuery.getFetchSize() ); + query.setFlushMode( interpret( hbmQuery.getFlushMode() ) ); + query.setFetchSize( hbmQuery.getFetchSize() ); + query.setReadOnly( hbmQuery.isReadOnly() ); + query.setTimeout( hbmQuery.getTimeout() ); + + // JaxbQueryElement#content elements can be either the query or parameters + for ( Object content : hbmQuery.getContent() ) { + if ( String.class.isInstance( content ) ) { + query.setQuery( (String) content ); + } + else { + final JaxbQueryParamElement hbmQueryParam = (JaxbQueryParamElement) content; + final JaxbQueryParamType queryParam = new JaxbQueryParamType(); + query.getQueryParam().add( queryParam ); + queryParam.setName( hbmQueryParam.getName() ); + queryParam.setType( hbmQueryParam.getType() ); + } + } + } + } + + private void transferDatabaseObjects(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + // todo : implement + } + + private void transferEntities(JaxbHibernateMapping hbmXmlMapping, JaxbEntityMappings ormRoot) { + // thoughts... + // 1) We only need to transfer the "extends" attribute if the model is dynamic (map mode), + // otherwise it will be discovered via jandex + // 2) ?? Have abstract hbm class mappings become MappedSuperclass mappings ?? + + if ( !hbmXmlMapping.getClazz().isEmpty() ) { + for ( JaxbClassElement hbmClass : hbmXmlMapping.getClazz() ) { + final JaxbEntity entity = new JaxbEntity(); + ormRoot.getEntity().add( entity ); + transferEntity( hbmClass, entity ); + } + } + + if ( !hbmXmlMapping.getSubclass().isEmpty() ) { + for ( JaxbSubclassElement hbmSubclass : hbmXmlMapping.getSubclass() ) { + final JaxbEntity entity = new JaxbEntity(); + ormRoot.getEntity().add( entity ); + + transferDiscriminatorSubclass( hbmSubclass, entity ); + } + } + + if ( !hbmXmlMapping.getJoinedSubclass().isEmpty() ) { + for ( JaxbJoinedSubclassElement hbmSubclass : hbmXmlMapping.getJoinedSubclass() ) { + final JaxbEntity entity = new JaxbEntity(); + ormRoot.getEntity().add( entity ); + + transferJoinedSubclass( hbmSubclass, entity ); + } + } + + if ( !hbmXmlMapping.getUnionSubclass().isEmpty() ) { + for ( JaxbUnionSubclassElement hbmSubclass : hbmXmlMapping.getUnionSubclass() ) { + final JaxbEntity entity = new JaxbEntity(); + ormRoot.getEntity().add( entity ); + + transferUnionSubclass( hbmSubclass, entity ); + } + } + +// +// +// +// + + } + + private void transferEntity(JaxbClassElement hbmClass, JaxbEntity entity) { + entity.setMetadataComplete( true ); + entity.setName( hbmClass.getEntityName() ); + entity.setClazz( hbmClass.getName() ); + entity.setAbstract( hbmClass.isAbstract() ); + entity.setMutable( hbmClass.isMutable() ); + entity.setLazy( hbmClass.isLazy() ); + entity.setProxy( hbmClass.getProxy() ); + + entity.setBatchSize( hbmClass.getBatchSize() ); + + entity.setTable( new JaxbTable() ); + entity.getTable().setCatalog( hbmClass.getCatalog() ); + entity.getTable().setSchema( hbmClass.getSchema() ); + entity.getTable().setName( hbmClass.getTable() ); + entity.getTable().setComment( hbmClass.getComment() ); + entity.getTable().setCheck( hbmClass.getCheck() ); + entity.setSubselect( hbmClass.getSubselect() ); + if ( !hbmClass.getSynchronize().isEmpty() ) { + for ( JaxbSynchronizeElement hbmSync : hbmClass.getSynchronize() ) { + final JaxbSynchronizeType sync = new JaxbSynchronizeType(); + sync.setTable( hbmSync.getTable() ); + entity.getSynchronize().add( sync ); + } + } + + entity.setDynamicInsert( hbmClass.isDynamicInsert() ); + entity.setDynamicUpdate( hbmClass.isDynamicUpdate() ); + entity.setSelectBeforeUpdate( hbmClass.isSelectBeforeUpdate() ); + + if ( hbmClass.getLoader() != null ) { + entity.setLoader( new JaxbHbmLoader() ); + entity.getLoader().setQueryRef( hbmClass.getLoader().getQueryRef() ); + } + if ( hbmClass.getSqlInsert() != null ) { + entity.setSqlInsert( new JaxbHbmCustomSql() ); + entity.getSqlInsert().setValue( hbmClass.getSqlInsert().getValue() ); + entity.getSqlInsert().setCheck( convert( hbmClass.getSqlInsert().getCheck() ) ); + entity.getSqlInsert().setValue( hbmClass.getSqlInsert().getValue() ); + } + if ( hbmClass.getSqlUpdate() != null ) { + entity.setSqlUpdate( new JaxbHbmCustomSql() ); + entity.getSqlUpdate().setValue( hbmClass.getSqlUpdate().getValue() ); + entity.getSqlUpdate().setCheck( convert( hbmClass.getSqlUpdate().getCheck() ) ); + entity.getSqlUpdate().setValue( hbmClass.getSqlUpdate().getValue() ); + } + if ( hbmClass.getSqlDelete() != null ) { + entity.setSqlDelete( new JaxbHbmCustomSql() ); + entity.getSqlDelete().setValue( hbmClass.getSqlDelete().getValue() ); + entity.getSqlDelete().setCheck( convert( hbmClass.getSqlDelete().getCheck() ) ); + entity.getSqlDelete().setValue( hbmClass.getSqlDelete().getValue() ); + } + entity.setRowid( hbmClass.getRowid() ); + entity.setWhere( hbmClass.getWhere() ); + + entity.setPersister( hbmClass.getPersister() ); + if ( !hbmClass.getTuplizer().isEmpty() ) { + if ( hbmClass.getTuplizer().size() > 1 ) { + log.warn( "More than one entity-mode per entity not supported" ); + + } + final JaxbTuplizerElement tuplizerElement = hbmClass.getTuplizer().get( 0 ); + entity.setEntityMode( tuplizerElement.getEntityMode().value() ); + entity.setTuplizer( tuplizerElement.getClazz() ); + } + + entity.setOptimisticLock( hbmClass.getOptimisticLock().value() ); + if ( hbmClass.getOptimisticLock() == JaxbOptimisticLockAttribute.VERSION ) { + // todo : transfer version/timestamp + //final JaxbVersionElement hbmVersion = hbmClass.getVersion(); + //final JaxbTimestampElement hbmTimestamp = hbmClass.getTimestamp(); + + // oddly the jpa xsd allows multiple elements :? + } + + + transferDiscriminator( entity, hbmClass ); + entity.setDiscriminatorValue( hbmClass.getDiscriminatorValue() ); + entity.setPolymorphism( hbmClass.getPolymorphism().value() ); + + if ( hbmClass.getMultiTenancy() != null ) { + entity.setMultiTenancy( new JaxbHbmMultiTenancy() ); + transferColumn( + entity.getMultiTenancy().getColumn(), + hbmClass.getMultiTenancy().getColumn(), + null, + true, + true + ); + entity.getMultiTenancy().setFormula( hbmClass.getMultiTenancy().getFormula() ); + entity.getMultiTenancy().setBindAsParam( hbmClass.getMultiTenancy().isBindAsParam() ); + entity.getMultiTenancy().setShared( hbmClass.getMultiTenancy().isShared() ); + } + + if ( hbmClass.getCache() != null ) { + entity.setCache( new JaxbCacheElement() ); + entity.getCache().setRegion( hbmClass.getCache().getRegion() ); + entity.getCache().setUsage( hbmClass.getCache().getUsage().value() ); + entity.getCache().setInclude( hbmClass.getCache().getInclude().value() ); + } + + // todo : transfer named queries + // todo : transfer filters + // todo : transfer fetch-profiles + + transferAttributes( entity, hbmClass ); + } + + private JaxbHbmCustomSqlCheckEnum convert(JaxbCheckAttribute check) { + if ( check == null ) { + return null; + } + return JaxbHbmCustomSqlCheckEnum.valueOf( check.value() ); + } + + private void transferColumn( + JaxbColumn column, + JaxbColumnElement hbmColumn, + String tableName, + boolean insertable, + boolean updateable) { + column.setTable( tableName ); + column.setName( hbmColumn.getName() ); + column.setComment( hbmColumn.getComment() ); + column.setCheck( hbmColumn.getCheck() ); + column.setDefault( hbmColumn.getDefault() ); + column.setNullable( !hbmColumn.isNotNull() ); + column.setColumnDefinition( hbmColumn.getSqlType() ); + column.setInsertable( insertable ); + column.setUpdatable( updateable ); + column.setLength( hbmColumn.getLength() ); + column.setPrecision( hbmColumn.getPrecision() ); + column.setScale( hbmColumn.getScale() ); + column.setRead( hbmColumn.getRead() ); + column.setWrite( hbmColumn.getWrite() ); + column.setUnique( hbmColumn.isUnique() ); + } + + private void transferDiscriminator(JaxbEntity entity, JaxbClassElement hbmClass) { + if ( hbmClass.getDiscriminator() == null ) { + return; + } + + if ( StringHelper.isNotEmpty( hbmClass.getDiscriminator().getColumnAttribute() ) ) { + entity.getDiscriminatorColumn().setName( hbmClass.getDiscriminator().getColumnAttribute() ); + } + else if ( StringHelper.isEmpty( hbmClass.getDiscriminator().getFormulaAttribute() ) ) { + entity.setDiscriminatorFormula( hbmClass.getDiscriminator().getFormulaAttribute() ); + } + else if ( StringHelper.isEmpty( hbmClass.getDiscriminator().getFormula().trim() ) ) { + entity.setDiscriminatorFormula( hbmClass.getDiscriminator().getFormulaAttribute().trim() ); + } + else { + entity.getDiscriminatorColumn().setName( hbmClass.getDiscriminator().getColumn().getName() ); + entity.getDiscriminatorColumn().setColumnDefinition( hbmClass.getDiscriminator().getColumn().getSqlType() ); + entity.getDiscriminatorColumn().setLength( hbmClass.getDiscriminator().getColumn().getLength() ); + entity.getDiscriminatorColumn().setForceInSelect( hbmClass.getDiscriminator().isForce() ); + } + } + + private void transferAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + entity.setAttributes( new JaxbAttributes() ); + + transferIdentifier( entity, hbmClass ); + transferBasicAttributes( entity, hbmClass ); + transferEmbeddedAttributes( entity, hbmClass ); + transferOneToOneAttributes( entity, hbmClass ); + transferManyToOneAttributes( entity, hbmClass ); + transferManyToManyAttributes( entity, hbmClass ); + transferAnyAttributes( entity, hbmClass ); + transferManyToAnyAttributes( entity, hbmClass ); + transferPrimitiveArrayAttributes( entity, hbmClass ); + transferPropertiesGrouping( entity, hbmClass ); + } + + private void transferIdentifier(JaxbEntity entity, JaxbClassElement hbmClass) { + final JaxbIdElement hbmId = hbmClass.getId(); + if ( hbmId != null ) { + // simple id + final JaxbId id = new JaxbId(); + id.setName( hbmId.getName() ); + id.setCustomAccess( hbmId.getAccess() ); + if ( StringHelper.isNotEmpty( hbmId.getTypeAttribute() ) ) { + id.getType().setName( hbmId.getTypeAttribute() ); + } + else { + if ( hbmId.getType() != null ) { + id.setType( new JaxbHbmType() ); + id.getType().setName( hbmId.getType().getName() ); + if ( !hbmId.getType().getParam().isEmpty() ) { + for ( JaxbParamElement hbmParam : hbmId.getType().getParam() ) { + final JaxbHbmParam param = new JaxbHbmParam(); + param.setName( hbmParam.getName() ); + param.setValue( hbmParam.getValue() ); + id.getType().getParam().add( param ); + } + } + } + } + id.setUnsavedValue( hbmId.getUnsavedValue() ); + if ( StringHelper.isNotEmpty( hbmId.getColumnAttribute() ) ) { + id.getColumn().setName( hbmId.getColumnAttribute() ); + } + else { + if ( hbmId.column != null ) { + assert hbmId.column.size() == 1; + transferColumn( id.getColumn(), hbmId.getColumn().get( 0 ), null, true, false ); + } + } + entity.getAttributes().getId().add( id ); + return; + } + + final JaxbCompositeIdElement hbmCompositeId = hbmClass.getCompositeId(); + assert hbmCompositeId != null; + + // we have one of 2 forms of composite id... + final boolean isAggregate; + if ( StringHelper.isNotEmpty( hbmCompositeId.getClazz() ) ) { + // we have . + if ( hbmCompositeId.isMapped() ) { + // user explicitly said the class is an "IdClass" + isAggregate = false; + } + else { + isAggregate = true; + } + } + else { + // there was no class specified, can only be non-aggregated + isAggregate = false; + } + + if ( isAggregate ) { + entity.getAttributes().getEmbeddedId().setName( hbmCompositeId.getName() ); + entity.getAttributes().getEmbeddedId().setCustomAccess( hbmCompositeId.getAccess() ); + + final JaxbEmbeddable embeddable = new JaxbEmbeddable(); + embeddable.setClazz( hbmCompositeId.getClazz() ); + for ( Object hbmCompositeAttribute : hbmCompositeId.getKeyPropertyOrKeyManyToOne() ) { + if ( JaxbKeyPropertyElement.class.isInstance( hbmCompositeAttribute ) ) { + final JaxbKeyPropertyElement keyProp = (JaxbKeyPropertyElement) hbmCompositeAttribute; + final JaxbBasic basic = new JaxbBasic(); + basic.setName( keyProp.getName() ); + basic.setCustomAccess( keyProp.getAccess() ); + if ( StringHelper.isNotEmpty( keyProp.getColumnAttribute() ) ) { + final JaxbColumn column = new JaxbColumn(); + column.setName( keyProp.getColumnAttribute() ); + basic.getColumnOrFormula().add( column ); + } + else { + for ( JaxbColumnElement hbmColumn : keyProp.getColumn() ) { + final JaxbColumn column = new JaxbColumn(); + transferColumn( column, hbmColumn, null, true, false ); + basic.getColumnOrFormula().add( column ); + } + } + embeddable.getAttributes().getBasic().add( basic ); + } + else { + final JaxbKeyManyToOneElement keyManyToOne = (JaxbKeyManyToOneElement) hbmCompositeAttribute; + final JaxbManyToOne manyToOne = new JaxbManyToOne(); + manyToOne.setName( keyManyToOne.getName() ); + manyToOne.setCustomAccess( keyManyToOne.getAccess() ); + if ( StringHelper.isNotEmpty( keyManyToOne.getEntityName() ) ) { + manyToOne.setTargetEntity( keyManyToOne.getEntityName() ); + } + else { + manyToOne.setTargetEntity( keyManyToOne.getClazz() ); + } + // todo : cascade + if ( "true".equals( keyManyToOne.getLazy().value() ) ) { + manyToOne.setFetch( FetchType.LAZY ); + } + manyToOne.getForeignKey().setName( keyManyToOne.getForeignKey() ); + if ( StringHelper.isNotEmpty( keyManyToOne.getColumnAttribute() ) ) { + final JaxbJoinColumn joinColumn = new JaxbJoinColumn(); + joinColumn.setName( keyManyToOne.getColumnAttribute() ); + manyToOne.getJoinColumn().add( joinColumn ); + } + else { + for ( JaxbColumnElement hbmColumn : keyManyToOne.getColumn() ) { + final JaxbJoinColumn joinColumn = new JaxbJoinColumn(); + joinColumn.setName( hbmColumn.getName() ); + joinColumn.setNullable( !hbmColumn.isNotNull() ); + joinColumn.setUnique( hbmColumn.isUnique() ); + manyToOne.getJoinColumn().add( joinColumn ); + } + } + embeddable.getAttributes().getManyToOne().add( manyToOne ); + } + } + ormRoot.getEmbeddable().add( embeddable ); + } + else { + entity.getIdClass().setClazz( hbmCompositeId.getClazz() ); + for ( Object hbmCompositeAttribute : hbmCompositeId.getKeyPropertyOrKeyManyToOne() ) { + if ( JaxbKeyPropertyElement.class.isInstance( hbmCompositeAttribute ) ) { + final JaxbKeyPropertyElement keyProp = (JaxbKeyPropertyElement) hbmCompositeAttribute; + final JaxbId id = new JaxbId(); + id.setName( keyProp.getName() ); + id.setCustomAccess( keyProp.getAccess() ); + if ( StringHelper.isNotEmpty( keyProp.getColumnAttribute() ) ) { + id.getColumn().setName( keyProp.getColumnAttribute() ); + } + else { + if ( keyProp.column != null ) { + assert keyProp.column.size() == 1; + transferColumn( id.getColumn(), keyProp.getColumn().get( 0 ), null, true, false ); + } + } + entity.getAttributes().getId().add( id ); + } + else { + final JaxbKeyManyToOneElement keyManyToOne = (JaxbKeyManyToOneElement) hbmCompositeAttribute; + final JaxbManyToOne manyToOne = new JaxbManyToOne(); + manyToOne.setName( keyManyToOne.getName() ); + manyToOne.setId( true ); + manyToOne.setCustomAccess( keyManyToOne.getAccess() ); + if ( StringHelper.isNotEmpty( keyManyToOne.getEntityName() ) ) { + manyToOne.setTargetEntity( keyManyToOne.getEntityName() ); + } + else { + manyToOne.setTargetEntity( keyManyToOne.getClazz() ); + } + // todo : cascade + if ( "true".equals( keyManyToOne.getLazy().value() ) ) { + manyToOne.setFetch( FetchType.LAZY ); + } + manyToOne.getForeignKey().setName( keyManyToOne.getForeignKey() ); + if ( StringHelper.isNotEmpty( keyManyToOne.getColumnAttribute() ) ) { + final JaxbJoinColumn joinColumn = new JaxbJoinColumn(); + joinColumn.setName( keyManyToOne.getColumnAttribute() ); + manyToOne.getJoinColumn().add( joinColumn ); + } + else { + for ( JaxbColumnElement hbmColumn : keyManyToOne.getColumn() ) { + final JaxbJoinColumn joinColumn = new JaxbJoinColumn(); + joinColumn.setName( hbmColumn.getName() ); + joinColumn.setNullable( !hbmColumn.isNotNull() ); + joinColumn.setUnique( hbmColumn.isUnique() ); + manyToOne.getJoinColumn().add( joinColumn ); + } + } + entity.getAttributes().getManyToOne().add( manyToOne ); + } + } + } + } + + private void transferBasicAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + for ( JaxbPropertyElement hbmProp : hbmClass.getProperty() ) { + final JaxbBasic basic = new JaxbBasic(); + basic.setName( hbmProp.getName() ); + basic.setOptional( hbmProp.isNotNull() != null && !hbmProp.isNotNull() ); + basic.setFetch( FetchType.EAGER ); + basic.setCustomAccess( hbmProp.getAccess() ); + basic.setOptimisticLock( hbmProp.isOptimisticLock() ); + + if ( StringHelper.isNotEmpty( hbmProp.getTypeAttribute() ) ) { + basic.getType().setName( hbmProp.getTypeAttribute() ); + } + else { + if ( hbmProp.getType() != null ) { + basic.setType( new JaxbHbmType() ); + basic.getType().setName( hbmProp.getType().getName() ); + for ( JaxbParamElement hbmParam : hbmProp.getType().getParam() ) { + final JaxbHbmParam param = new JaxbHbmParam(); + param.setName( hbmParam.getName() ); + param.setValue( hbmParam.getValue() ); + basic.getType().getParam().add( param ); + } + } + } + + if ( StringHelper.isNotEmpty( hbmProp.getFormulaAttribute() ) ) { + basic.getColumnOrFormula().add( hbmProp.getFormulaAttribute() ); + } + else if ( StringHelper.isNotEmpty( hbmProp.getColumnAttribute() ) ) { + final JaxbColumn column = new JaxbColumn(); + column.setName( hbmProp.getColumnAttribute() ); + basic.getColumnOrFormula().add( column ); + } + else if ( !hbmProp.getFormula().isEmpty() ) { + for ( String formula : hbmProp.getFormula() ) { + basic.getColumnOrFormula().add( formula ); + } + } + else { + for ( JaxbColumnElement hbmColumn : hbmProp.getColumn() ) { + final JaxbColumn column = new JaxbColumn(); + transferColumn( column, hbmColumn, null, hbmProp.isInsert(), hbmProp.isUpdate() ); + basic.getColumnOrFormula().add( column ); + } + } + entity.getAttributes().getBasic().add( basic ); + } + } + + private void transferEmbeddedAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + + } + + private void transferOneToOneAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + + } + + private void transferManyToOneAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + + } + + private void transferManyToManyAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + + } + + private void transferAnyAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + + } + + private void transferManyToAnyAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + + } + + private void transferPrimitiveArrayAttributes(JaxbEntity entity, JaxbClassElement hbmClass) { + if ( !hbmClass.getPrimitiveArray().isEmpty() ) { + log.warnf( + "Entity mapping [%s : %s] from hbm.xml [%s] used construct " + + "which is not supported in transformation; skipping", + hbmClass.getName(), + hbmClass.getEntityName(), + origin + ); + } + } + + private void transferPropertiesGrouping(JaxbEntity entity, JaxbClassElement hbmClass) { + if ( !hbmClass.getProperties().isEmpty() ) { + log.warnf( + "Entity mapping [%s : %s] from hbm.xml [%s] used construct " + + "which is not supported in transformation; skipping", + hbmClass.getName(), + hbmClass.getEntityName(), + origin + ); + } + } + + private void transferDiscriminatorSubclass(JaxbSubclassElement hbmSubclass, JaxbEntity entity) { + // todo : implement + } + + private void transferJoinedSubclass(JaxbJoinedSubclassElement hbmSubclass, JaxbEntity entity) { + // todo : implement + } + + private void transferUnionSubclass(JaxbUnionSubclassElement hbmSubclass, JaxbEntity entity) { + // todo : implement + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/IdBagPluralAttributeElementAdapter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/IdBagPluralAttributeElementAdapter.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/IdBagPluralAttributeElementAdapter.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/IdBagPluralAttributeElementAdapter.java index fad92698bbcb..e999e7120c5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/IdBagPluralAttributeElementAdapter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/IdBagPluralAttributeElementAdapter.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.metamodel.source.internal.jaxb.hbm; /** * Adaptive implementation of the {@link PluralAttributeElement} for {@code } mappings which diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/JoinElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/JoinElementSource.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/JoinElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/JoinElementSource.java index 4ff687415d6f..5138ca632214 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/JoinElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/JoinElementSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.metamodel.source.internal.jaxb.hbm; import java.util.List; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/MetaAttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/MetaAttributeContainer.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/MetaAttributeContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/MetaAttributeContainer.java index 6a178cb8f03d..e0220076e642 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/MetaAttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/MetaAttributeContainer.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.metamodel.source.internal.jaxb.hbm; import java.util.List; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/PluralAttributeElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/PluralAttributeElement.java similarity index 82% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/PluralAttributeElement.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/PluralAttributeElement.java index adf766fbe05d..89c69473e6aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/PluralAttributeElement.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/PluralAttributeElement.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.metamodel.source.internal.jaxb.hbm; import java.util.List; @@ -30,7 +30,7 @@ * * @author Steve Ebersole */ -public interface PluralAttributeElement extends MetaAttributeContainer { +public interface PluralAttributeElement extends TableInformationSource, MetaAttributeContainer { public String getName(); public String getAccess(); @@ -42,20 +42,15 @@ public interface PluralAttributeElement extends MetaAttributeContainer { public JaxbManyToManyElement getManyToMany(); public JaxbManyToAnyElement getManyToAny(); - public String getSchema(); - public String getCatalog(); - public String getTable(); public String getComment(); public String getCheck(); - public String getSubselect(); - public String getSubselectAttribute(); public String getWhere(); public JaxbLoaderElement getLoader(); - public JaxbSqlInsertElement getSqlInsert(); - public JaxbSqlUpdateElement getSqlUpdate(); - public JaxbSqlDeleteElement getSqlDelete(); - public JaxbSqlDeleteAllElement getSqlDeleteAll(); + public JaxbSqlDmlElement getSqlInsert(); + public JaxbSqlDmlElement getSqlUpdate(); + public JaxbSqlDmlElement getSqlDelete(); + public JaxbSqlDmlElement getSqlDeleteAll(); public List getSynchronize(); @@ -67,7 +62,7 @@ public interface PluralAttributeElement extends MetaAttributeContainer { public JaxbLazyAttributeWithExtra getLazy(); public JaxbOuterJoinAttribute getOuterJoin(); - public String getBatchSize(); + public int getBatchSize(); public boolean isInverse(); public boolean isMutable(); public boolean isOptimisticLock(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/QuerySourceElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/QuerySourceElement.java new file mode 100644 index 000000000000..c8d380a18730 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/QuerySourceElement.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +import java.io.Serializable; +import java.util.List; + +/** + * TODO javadoc + * + * @author Strong Liu + */ +public interface QuerySourceElement { + List getContent(); + JaxbCacheModeAttribute getCacheMode(); + String getCacheRegion(); + boolean isCacheable(); + String getComment(); + Integer getFetchSize(); + JaxbFlushModeAttribute getFlushMode(); + String getName(); + boolean isReadOnly(); + Integer getTimeout(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/ReturnElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/ReturnElement.java new file mode 100644 index 000000000000..4c549c8bc3d6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/ReturnElement.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +import java.util.List; + +/** + * @author Strong Liu + */ +public interface ReturnElement { + public String getAlias(); + public JaxbLockModeAttribute getLockMode(); + public List getReturnProperty(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/SingularAttributeSource.java new file mode 100644 index 000000000000..21b3ee7855e7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/SingularAttributeSource.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +/** + * @author Steve Ebersole + */ +public interface SingularAttributeSource extends MetaAttributeContainer { + public String getName(); + + public String getTypeAttribute(); + + public JaxbTypeElement getType(); + + public String getAccess(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SubEntityElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/SubEntityElement.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SubEntityElement.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/SubEntityElement.java index 3d0dfd828419..5b03606bb038 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/mapping/hbm/SubEntityElement.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/SubEntityElement.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb.mapping.hbm; +package org.hibernate.metamodel.source.internal.jaxb.hbm; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/TableInformationSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/TableInformationSource.java new file mode 100644 index 000000000000..a2aacab1adc0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/TableInformationSource.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.hbm; + +/** + * @author Steve Ebersole + */ +public interface TableInformationSource { + public String getSchema(); + + public String getCatalog(); + + public String getTable(); + + public String getSubselect(); + + public String getSubselectAttribute(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/AccessTypeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/AccessTypeMarshalling.java new file mode 100644 index 000000000000..f41b3b870728 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/AccessTypeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.AccessType; + +/** + * Marshalling support for dealing with JPA AccessType enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class AccessTypeMarshalling { + public static AccessType fromXml(String name) { + return AccessType.valueOf( name ); + } + + public static String toXml(AccessType accessType) { + return accessType.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/DiscriminatorTypeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/DiscriminatorTypeMarshalling.java new file mode 100644 index 000000000000..96e139b91517 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/DiscriminatorTypeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.DiscriminatorType; + +/** + * Marshalling support for dealing with JPA DiscriminatorType enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class DiscriminatorTypeMarshalling { + public static DiscriminatorType fromXml(String name) { + return DiscriminatorType.valueOf( name ); + } + + public static String toXml(DiscriminatorType discriminatorType) { + return discriminatorType.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/EnumTypeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/EnumTypeMarshalling.java new file mode 100644 index 000000000000..7d704b9a3dc7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/EnumTypeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.EnumType; + +/** + * Marshalling support for dealing with JPA EnumType enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class EnumTypeMarshalling { + public static EnumType fromXml(String name) { + return EnumType.valueOf( name ); + } + + public static String toXml(EnumType enumType) { + return enumType.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/FetchTypeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/FetchTypeMarshalling.java new file mode 100644 index 000000000000..d9eada84c8ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/FetchTypeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.FetchType; + +/** + * Marshalling support for dealing with JPA FetchType enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class FetchTypeMarshalling { + public static FetchType fromXml(String name) { + return FetchType.valueOf( name ); + } + + public static String toXml(FetchType fetchType) { + return fetchType.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/FlushModeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/FlushModeMarshalling.java new file mode 100644 index 000000000000..18ae1347d9ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/FlushModeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import org.hibernate.FlushMode; + +/** + * Marshalling support for dealing with Hibernate FlushMode enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class FlushModeMarshalling { + public static FlushMode fromXml(String name) { + return FlushMode.interpretExternalSetting( name ); + } + + public static String toXml(FlushMode flushMode) { + return flushMode.toExternalForm(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/LockModeTypeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/LockModeTypeMarshalling.java new file mode 100644 index 000000000000..9f0ffc4a361f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/LockModeTypeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.LockModeType; + +/** + * Marshalling support for dealing with JPA LockModeType enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class LockModeTypeMarshalling { + public static LockModeType fromXml(String name) { + return LockModeType.valueOf( name ); + } + + public static String toXml(LockModeType lockModeType) { + return lockModeType.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/ParameterModeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/ParameterModeMarshalling.java new file mode 100644 index 000000000000..1c8b1893c626 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/ParameterModeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.ParameterMode; + +/** + * Marshalling support for dealing with JPA ParameterMode enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class ParameterModeMarshalling { + public static ParameterMode fromXml(String name) { + return ParameterMode.valueOf( name ); + } + + public static String toXml(ParameterMode parameterMode) { + return parameterMode.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/TemporalTypeMarshalling.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/TemporalTypeMarshalling.java new file mode 100644 index 000000000000..a5e704cc8381 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/marshalling/TemporalTypeMarshalling.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.internal.jaxb.marshalling; + +import javax.persistence.TemporalType; + +/** + * Marshalling support for dealing with JPA TemporalType enums. Plugged into JAXB for binding + * + * @author Steve Ebersole + */ +public class TemporalTypeMarshalling { + public static TemporalType fromXml(String name) { + return TemporalType.valueOf( name ); + } + + public static String toXml(TemporalType temporalType) { + return temporalType.name(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AggregatedCompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AggregatedCompositeIdentifierSource.java new file mode 100644 index 000000000000..bbe2709bb928 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AggregatedCompositeIdentifierSource.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is + * {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE aggregated-composite}. This equates to an identifier which is + * made up of multiple values which are defined as part of a component/embedded. + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface AggregatedCompositeIdentifierSource extends CompositeIdentifierSource { + /** + * Obtain the source descriptor for the identifier attribute. + * + * @return The identifier attribute source. + */ + public EmbeddedAttributeSource getIdentifierAttributeSource(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AssociationSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AssociationSource.java new file mode 100644 index 000000000000..790aca81c136 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AssociationSource.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Set; + +/** + * @author Gail Badner + */ +public interface AssociationSource extends CascadeStyleSource { + + public AttributeSource getAttributeSource(); + + /** + * Obtain the name of the referenced entity. + * + * @return The name of the referenced entity + */ + public String getReferencedEntityName(); + + public boolean isIgnoreNotFound(); + + /** + * Returns the attribute source that is owned by this {@link AssociationSource}, + * if there is one. + *

      + * Specifically, this method returns the {@link AttributeSource} that is + * "mappedBy" this {@link AssociationSource}. + * + * @return + */ + public Set getOwnedAssociationSources(); + + public void addMappedByAssociationSource(MappedByAssociationSource attributeSource); + + public boolean isMappedBy(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeRelationalValueSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeRelationalValueSourceContainer.java new file mode 100644 index 000000000000..b57141f13d48 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeRelationalValueSourceContainer.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Contract for a container of {@link RelationalValueSource} references for an attribute. + * + * It provides the default table that contains the relational values for the singular attribute. + * + * See {@link RelationalValueSourceContainer} for additional details. + * + * @author Gail Badner + */ +public interface AttributeRelationalValueSourceContainer extends RelationalValueSourceContainer { + /** + * @return returns the default name of the table that contains the relational values. + */ + public String getContainingTableName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSource.java new file mode 100644 index 000000000000..0b9d38984f09 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSource.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; + +/** + * Contract for sources of persistent attribute descriptions. + * + * @author Steve Ebersole + */ +public interface AttributeSource extends ToolingHintSourceContainer { + /** + * Obtain the attribute name. + * + * @return The attribute name. {@code null} ais NOT allowed! + */ + public String getName(); + + public AttributePath getAttributePath(); + public AttributeRole getAttributeRole(); + + /** + * Attributes are coarsely speaking either singular or plural. This method + * reports whether this attribute is singular (false indicates it is plural + * instead). Singular attributes are castable to + * {@link org.hibernate.metamodel.source.spi.SingularAttributeSource} for + * further processing, whereas plural attributes are castable to + * {@link org.hibernate.metamodel.source.spi.PluralAttributeSource} for + * further processing. + */ + public boolean isSingular(); + + /** + * Obtain information about the Hibernate type ({@link org.hibernate.type.Type}) for this attribute. + * + * @return The Hibernate type information + */ + public HibernateTypeSource getTypeInformation(); + + /** + * Obtain the name of the property accessor style used to access this attribute. + * + * @return The property accessor style for this attribute. + * + * @see org.hibernate.property.PropertyAccessor + */ + public String getPropertyAccessorName(); + + /** + * If the containing entity is using optimistic locking, should this + * attribute participate in that locking? Meaning, should changes in the + * value of this attribute at runtime indicate that the entity is now dirty + * in terms of optimistic locking? + * + * @return {@code true} indicates it should be included; {@code false}, it should not. + */ + public boolean isIncludedInOptimisticLocking(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSourceContainer.java new file mode 100644 index 000000000000..d05767100fa2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSourceContainer.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.LocalBindingContext; + +/** + * Contract for a container of {@link AttributeSource} references. Entities, + * MappedSuperclasses and composites (Embeddables) all contain attributes. + *

      + * Think of this as the corollary to what JPA calls a ManagedType on the + * source side of things. + * + * @author Steve Ebersole + */ +public interface AttributeSourceContainer { + public AttributePath getAttributePathBase(); + public AttributeRole getAttributeRoleBase(); + + /** + * Obtain this container's attribute sources. + * + * @return The attribute sources. + */ + public List attributeSources(); + + /** + * Obtain the local binding context associated with this container. + * + * @return The local binding context + */ + public LocalBindingContext getLocalBindingContext(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSourceResolutionContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSourceResolutionContext.java new file mode 100644 index 000000000000..ac3a4f53549d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/AttributeSourceResolutionContext.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Column; + +/** + * + * @author Gail Badner + */ +public interface AttributeSourceResolutionContext { + public IdentifierSource resolveIdentifierSource(String entityName); + public AttributeSource resolveAttributeSource(String entityName, String attributeName); + public List resolveIdentifierColumns(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CascadeStyleSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CascadeStyleSource.java new file mode 100644 index 000000000000..206349bf6b2e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CascadeStyleSource.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Set; + +import org.hibernate.engine.spi.CascadeStyle; + +/** + * Describes sources which can be cascaded. + * + * @author Steve Ebersole + */ +public interface CascadeStyleSource { + /** + * Obtain the cascade styles to be applied to this association. + * + * @return The cascade styles. + */ + public Set getCascadeStyles(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CollectionIdSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CollectionIdSource.java new file mode 100644 index 000000000000..a73e7c6bf5c4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CollectionIdSource.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Steve Ebersole + */ +public interface CollectionIdSource { + /** + * Obtain source information about the column for the collection id. + * + * @return The collection id column info. + */ + public ColumnSource getColumnSource(); + + /** + * Obtain information about the Hibernate type ({@link org.hibernate.type.Type}) for the collection id + * + * @return The Hibernate type information + */ + public HibernateTypeSource getTypeInformation(); + + /** + * Obtain the name of the identifier value generator. + * + * @return The identifier value generator name + */ + public String getGeneratorName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ColumnBindingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ColumnBindingDefaults.java new file mode 100644 index 000000000000..4a67c1f618d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ColumnBindingDefaults.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Steve Ebersole + */ +public interface ColumnBindingDefaults { + /** + * How should non-specification of value insertion by the individual value sources here be + * interpreted in terms of defaulting that value. + * + * @return {@code true} Indicates that insertions are enabled by default for all value sources which + * do not explicitly specify. + */ + boolean areValuesIncludedInInsertByDefault(); + + /** + * How should non-specification of value updating by the individual value sources here be + * interpreted in terms of defaulting that value. + * + * @return {@code true} Indicates that updates are enabled by default for all value sources which + * do not explicitly specify. + */ + boolean areValuesIncludedInUpdateByDefault(); + + /** + * How should non-specification of value nullability by the individual value sources here be + * interpreted in terms of defaulting that value. + * + * @return {@code true} Indicates that insertions are enabled by default for all value sources which + * do not explicitly specify. + */ + boolean areValuesNullableByDefault(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ColumnSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ColumnSource.java new file mode 100644 index 000000000000..9c4f5f7b60ba --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ColumnSource.java @@ -0,0 +1,130 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.JdbcDataType; + +/** + * Contract for source information pertaining to a physical column definition specific to a particular attribute + * context. + *

      + * Conceptual note: this really describes a column from the perspective of its binding to an attribute. + * This is especially important for {@link #isIncludedInInsert} and {@link #isIncludedInUpdate}. There it is + * not the column itself being described. + * + * @author Steve Ebersole + */ +public interface ColumnSource extends RelationalValueSource { + /** + * Obtain the name of the column. + * + * @return The name of the column. Can be {@code null}, in which case a naming strategy is applied. + */ + public String getName(); + + /** + * A SQL fragment to apply to the column value on read. + * + * @return The SQL read fragment + */ + public String getReadFragment(); + + /** + * A SQL fragment to apply to the column value on write. + * + * @return The SQL write fragment + */ + public String getWriteFragment(); + + /** + * Is this column nullable? + * + * @return {@code true} indicates it is nullable; {@code false} non-nullable. + */ + public TruthValue isNullable(); + + /** + * Obtain a specified default value for the column + * + * @return THe column default + */ + public String getDefaultValue(); + + /** + * Obtain the free-hand definition of the column's type. + * + * @return The free-hand column type + */ + public String getSqlType(); + + /** + * The deduced (and dialect convertible) type for this column + * + * @return The column's SQL data type. + */ + public JdbcDataType getDatatype(); + + /** + * Obtain the source for the specified column size. + * + * @return The source for the column size. + */ + public SizeSource getSizeSource(); + + /** + * Is this column unique? + * + * @return {@code true} indicates it is unique; {@code false} non-unique. + */ + public boolean isUnique(); + + /** + * Obtain the specified check constraint condition + * + * @return Check constraint condition + */ + public String getCheckCondition(); + + /** + * Obtain the specified SQL comment + * + * @return SQL comment + */ + public String getComment(); + + /** + * Is the described column written to as part of inserts for the attribute being mapped. + * + * @return {@code true} indicates the column is written on insert from this attribute + */ + public TruthValue isIncludedInInsert(); + + /** + * Is the described column written to as part of updates for the attribute being mapped. + * + * @return {@code true} indicates the column is written on update from this attribute + */ + public TruthValue isIncludedInUpdate(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CompositeIdentifierSource.java new file mode 100644 index 000000000000..8b484a280705 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/CompositeIdentifierSource.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * @author Steve Ebersole + */ +public interface CompositeIdentifierSource extends IdentifierSource { + /** + * Handle silly SpecJ reading of the JPA spec. They believe composite identifiers should have "partial generation" + * capabilities. + * + * @todo See todo on {@link IdentifierSource#getIdentifierGeneratorDescriptor()} wrt "generator source"... + * + * @param identifierAttributeName The name of the individual attribute within the composite identifier. + * + * @return The generator for the named attribute (within the composite). + */ + public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ConstraintSource.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ConstraintSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ConstraintSource.java index 0f59e50fb310..2fdfd0eacb2d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ConstraintSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ConstraintSource.java @@ -21,7 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; + +import java.util.List; + /** * Contract describing source of table constraints @@ -40,9 +43,8 @@ public interface ConstraintSource { * @return The logical table name. Can be {@code null} in the case of the "primary table". */ public String getTableName(); - - /** - * @return returns the names of the column which are part of this constraint - */ - Iterable columnNames(); + + public List columnNames(); + + public List orderings(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DerivedValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/DerivedValueSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DerivedValueSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/DerivedValueSource.java index 85b2738c497b..c3110ac0fddd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DerivedValueSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/DerivedValueSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; /** * Contract describing source of a derived value (formula). diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/DiscriminatorSource.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/DiscriminatorSource.java index c2fcc9c92741..78a49b4b6a00 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/DiscriminatorSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/DiscriminatorSource.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; /** * Contract for sources of information about a mapped discriminator. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddableSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddableSource.java new file mode 100644 index 000000000000..1926dc60c9e0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddableSource.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Represents the binding source for an "embeddable" (in JPA terms) + * or "composite" (in legacy Hibernate terms). + *

      + * Note that this really models the JPA concept of an Embedded, more + * than the Embeddable. + * + * @author Steve Ebersole + */ +public interface EmbeddableSource extends AttributeSourceContainer { + public JavaTypeDescriptor getTypeDescriptor(); + + public String getParentReferenceAttributeName(); + + public String getExplicitTuplizerClassName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddableSourceContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddableSourceContributor.java new file mode 100644 index 000000000000..fdf12e874e48 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddableSourceContributor.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Contract for things that can contain EmbeddableSource definitions. + * + * @author Steve Ebersole + */ +public interface EmbeddableSourceContributor { + /** + * Gets the source information about the embeddable/composition. + * + * @return The EmbeddableSource + */ + public EmbeddableSource getEmbeddableSource(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddedAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddedAttributeSource.java new file mode 100644 index 000000000000..9405a7a620ab --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EmbeddedAttributeSource.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Represents the binding source for a singular attribute that is "embedded" + * or "composite". + * + * @author Steve Ebersole + */ +public interface EmbeddedAttributeSource extends SingularAttributeSource, EmbeddableSourceContributor { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EntityHierarchySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EntityHierarchySource.java new file mode 100644 index 000000000000..95339dcd86a7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EntityHierarchySource.java @@ -0,0 +1,136 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.EntityMode; +import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +/** + * Models the source-agnostic view of an entity hierarchy. + * + * @author Steve Ebersole + */ +public interface EntityHierarchySource { + /** + * Obtain the hierarchy's root type source. + * + * @return The root type source. + */ + public EntitySource getRoot(); + + /** + * The inheritance type/strategy for the hierarchy. + *

      + * NOTE : The entire hierarchy must comply with the same inheritance strategy. + * + * @return The inheritance type. + */ + public InheritanceType getHierarchyInheritanceType(); + + /** + * Obtain source information about this entity's identifier. + * + * @return Identifier source information. + */ + public IdentifierSource getIdentifierSource(); + + /** + * Obtain the source information about the attribute used for optimistic locking. + * + * @return the source information about the attribute used for optimistic locking + */ + public VersionAttributeSource getVersionAttributeSource(); + + /** + * Obtain the source information about the discriminator attribute for single table inheritance + * + * @return the source information about the discriminator attribute for single table inheritance + */ + public DiscriminatorSource getDiscriminatorSource(); + + /** + * Obtain the source information about the multi-tenancy discriminator for this entity + * + * @return the source information about the multi-tenancy discriminator for this entity + */ + public MultiTenancySource getMultiTenancySource(); + + /** + * Obtain the entity mode for this entity. + * + * @return The entity mode. + */ + public EntityMode getEntityMode(); + + /** + * Is this root entity mutable? + * + * @return {@code true} indicates mutable; {@code false} non-mutable. + */ + public boolean isMutable(); + + /** + * Should explicit polymorphism (querying) be applied to this entity? + * + * @return {@code true} indicates explicit polymorphism; {@code false} implicit. + */ + public boolean isExplicitPolymorphism(); + + /** + * Obtain the specified extra where condition to be applied to this entity. + * + * @return The extra where condition + */ + public String getWhere(); + + /** + * Obtain the row-id name for this entity + * + * @return The row-id name + */ + public String getRowId(); + + /** + * Obtain the optimistic locking style for this entity. + * + * @return The optimistic locking style. + */ + public OptimisticLockStyle getOptimisticLockStyle(); + + /** + * Obtain the caching configuration for this entity. + * + * @return The caching configuration. + */ + public Caching getCaching(); + + /** + * Obtain the natural id caching configuration for this entity. + * + * @return The natural id caching configuration. + */ + public Caching getNaturalIdCaching(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EntitySource.java similarity index 77% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EntitySource.java index f118d9c49e95..b6494f61e15c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/EntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/EntitySource.java @@ -21,38 +21,19 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; -import java.util.List; -import javax.persistence.Entity; -import javax.persistence.EntityListeners; -import javax.persistence.MappedSuperclass; +import java.util.Set; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.source.LocalBindingContext; +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.binding.CustomSQL; /** * Contract describing source of an entity * * @author Steve Ebersole */ -public interface EntitySource extends SubclassEntityContainer, AttributeSourceContainer { - - /** - * Obtain the origin of this source. - * - * @return The origin of this source. - */ - public Origin getOrigin(); - - /** - * Obtain the binding context local to this entity source. - * - * @return The local binding context - */ - public LocalBindingContext getLocalBindingContext(); - +public interface EntitySource extends IdentifiableTypeSource, ToolingHintSourceContainer { /** * Obtain the entity name * @@ -79,14 +60,14 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo * * @return The primary table. */ - public TableSource getPrimaryTable(); + public TableSpecificationSource getPrimaryTable(); /** * Obtain the secondary tables for this entity * * @return returns an iterator over the secondary tables for this entity */ - public Iterable getSecondaryTables(); + public Set getSecondaryTables(); /** * Obtain the name of a custom tuplizer class to be used. @@ -184,16 +165,9 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo /** * Obtain any additional table names on which to synchronize (auto flushing) this entity. * - * @return Additional synchronized table names. + * @return Additional synchronized table names or 0 sized String array, never return null. */ - public List getSynchronizedTableNames(); - - /** - * Obtain the meta-attribute sources associated with this entity. - * - * @return The meta-attribute sources. - */ - public Iterable metaAttributes(); + public String[] getSynchronizedTableNames(); /** * Get the actual discriminator value in case of a single table inheritance @@ -208,9 +182,12 @@ public interface EntitySource extends SubclassEntityContainer, AttributeSourceCo */ public Iterable getConstraints(); - /** - * @return the list of classes (this {@link Entity entity}/{@link MappedSuperclass mapped superclass}, or - * {@link EntityListeners entity listeners}) that define JPA callbacks for this entity/mapped superclass. - */ - List getJpaCallbackClasses(); + /** + * Obtain the filters for this entity. + * + * @return returns an array of the filters for this entity. + */ + public FilterSource[] getFilterSources(); + + public TruthValue quoteIdentifiersLocalToEntity(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FetchProfileSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FetchProfileSource.java new file mode 100644 index 000000000000..eaecffbb2d40 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FetchProfileSource.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Defines a source of fetch profile information + * + * @author Steve Ebersole + */ +public interface FetchProfileSource { + /** + * Defines a source of an association fetch information within a fetch profile + */ + public static interface AssociationOverrideSource { + /** + * Retrieve the name of the entity containing the association. + * + * @return The entity name. + */ + public String getEntityName(); + + /** + * Retrieve the name of the association attribute on the entity. + * + * @return The attribute name + */ + public String getAttributeName(); + + /** + * Retrieve the name of the fetch mode to be applied to the association as part of this profile. + * + * @return the fetch mode name. + */ + public String getFetchModeName(); + } + + /** + * Retrieve the name of the profile. + * + * @return The profile name. + */ + public String getName(); + + /** + * Retrieve the association fetching overrides associated with this profile. + * + * @return The association fetching overrides + */ + public Iterable getAssociationOverrides(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FetchableAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FetchableAttributeSource.java new file mode 100644 index 000000000000..a4b35f0dae79 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FetchableAttributeSource.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; + +/** + * Describes source for attributes which can be fetched. + * + * @author Steve Ebersole + */ +public interface FetchableAttributeSource { + public FetchTiming getFetchTiming(); + + public FetchStyle getFetchStyle(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterDefinitionSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterDefinitionSource.java new file mode 100644 index 000000000000..c0b3ca74d3e3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterDefinitionSource.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describe the source of filer def information. Generally either {@code } or + * {@link org.hibernate.annotations.FilterDef @FilterDef} + * + * @author Steve Ebersole + */ +public interface FilterDefinitionSource { + /** + * Retrieve the name of the filter. Would match the related {@link FilterSource#getName} + * + * @return The filter name + * + * @see FilterSource#getName + */ + public String getName(); + + /** + * Retrieve the condition specified as part of the def. Defines the condition to use + * in related filters when {@link FilterSource#getCondition} is null. + * + * @return The "default" condition for associated filters. + * + * @see FilterSource#getCondition + */ + public String getCondition(); + + /** + * Retrieve parameter sources associated with this filer def. + * + * @return The parameter sources. Can be null. + */ + public Iterable getParameterSources(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterParameterSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterParameterSource.java new file mode 100644 index 000000000000..615a5f1f3f01 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterParameterSource.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source of filter parameter information + * + * @author Steve Ebersole + */ +public interface FilterParameterSource { + /** + * Retrieve the name of the parameter being described. + * + * @return The name + */ + public String getParameterName(); + + /** + * The Hibernate type name that can be used to handle bound parameter values. + * + * @return the type + */ + public String getParameterValueTypeName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterSource.java new file mode 100644 index 000000000000..ddaeac61ff45 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/FilterSource.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Map; + +/** + * Defines the source of filter information. May have an associated {@link FilterDefinitionSource}. + * Relates to both {@code } and {@link org.hibernate.annotations.Filter @Filter} + * + * @author Steve Ebersole + */ +public interface FilterSource { + /** + * Get the name of the filter being described. + * + * @return The name. + */ + public String getName(); + + /** + * Get the condition associated with the filter. Can be {@code null} in the case of a filter described + * further by a "filter def" which contains the condition text. + * + * @return The condition defined on the filter. + * + * @see {@link FilterDefinitionSource#getCondition()} + */ + public String getCondition(); + + /** + * Should Hibernate perform automatic alias injection into the supplied condition string? The default it to + * perform auto injection *unless* explicit alias(es) are supplied. + * + * @return {@code true} indicates auto injection should occur; {@code false} that it should not + */ + public boolean shouldAutoInjectAliases(); + + /** + * Get the map of explicit alias to table name mappings. + * + * @return The alias to table map + */ + public Map getAliasToTableMap(); + + /** + * Get the map of explicit alias to entity name mappings. + * + * @return The alias to entity map + */ + public Map getAliasToEntityMap(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ForeignKeyContributingSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ForeignKeyContributingSource.java new file mode 100644 index 000000000000..d6fb96e93f46 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ForeignKeyContributingSource.java @@ -0,0 +1,137 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Additional contract for things which describe foreign keys. + * + * @author Steve Ebersole + */ +public interface ForeignKeyContributingSource { + /** + * Retrieve the name of the foreign key as supplied by the user, or {@code null} if the user supplied none. + * + * @return The user supplied foreign key name. + */ + public String getExplicitForeignKeyName(); + + /** + * Primarily exists to support JPA's @ForeignKey(NO_CONSTRAINT). + * + * @return True if the FK constraint should be created, false if not. + */ + public boolean createForeignKeyConstraint(); + + /** + * Is "cascade delete" enabled for the foreign key? In other words, if a record in the parent (referenced) + * table is deleted, should the corresponding records in the child table automatically be deleted? + * + * @return true, if the cascade delete is enabled; false, otherwise. + */ + public boolean isCascadeDeleteEnabled(); + + /** + * Retrieve the delegate for resolving foreign key target columns. This corresponds directly to + * HBM {@code } and JPA {@link javax.persistence.JoinColumn} mappings. + *

      + * By default foreign keys target the primary key of the targeted table. {@code } and + * {@link javax.persistence.JoinColumn} mappings represents ways to instead target non-PK columns. Implementers + * should return {@code null} to indicate targeting primary key columns. + * + * @return The delegate, or {@code null} + */ + public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate(); + + /** + * By default foreign keys target the columns defined as the primary key of the targeted table. This contract + * helps account for cases where other columns should be targeted instead. + */ + public static interface JoinColumnResolutionDelegate { + /** + * Resolve the (other, non-PK) columns which should targeted by the foreign key. + * + * @param context The context for resolving those columns. + * + * @return The resolved target columns. + */ + public List getJoinColumns(JoinColumnResolutionContext context); + + public TableSpecification getReferencedTable(JoinColumnResolutionContext context); + + /** + * Retrieves the explicitly named attribute that maps to the non-PK foreign-key target columns. + * + * @return The explicitly named referenced attribute, or {@code null}. This most likely always {@code null} + * from annotations cases. + */ + public String getReferencedAttributeName(); + } + + /** + * Means to allow the {@link JoinColumnResolutionDelegate} access to the relational values it needs. + */ + public static interface JoinColumnResolutionContext { + /** + * Given an attribute name, resolve the columns. This is used in the HBM {@code property-ref/>} case. + * + * @param attributeName The name of the referenced property. + * + * @return The corresponding referenced columns + */ + public List resolveRelationalValuesForAttribute(String attributeName); + + public TableSpecification resolveTableForAttribute(String attributeName); + + /** + * Resolve a column reference given the logical names of both the table and the column. Used in the + * {@link javax.persistence.JoinColumn} case + * + * @param logicalColumnName The logical column name. + * @param logicalTableName The logical table name. + * @param logicalSchemaName The logical schema name. + * @param logicalCatalogName The logical catalog name. + * + * @return The column. + */ + public Column resolveColumn(String logicalColumnName, String logicalTableName, String logicalSchemaName, String logicalCatalogName); + + /** + * Resolve a table reference given the logical names of the table and the column. Used in the + * {@link javax.persistence.JoinColumn} case + * + * @param logicalTableName The logical table name. + * @param logicalSchemaName The logical schema name. + * @param logicalCatalogName The logical catalog name. + * + * @return The column. + */ + public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/HibernateTypeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/HibernateTypeSource.java new file mode 100644 index 000000000000..9b27c1a0828d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/HibernateTypeSource.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Source-agnostic descriptor for explicit user-supplied Hibernate type information + * + * @author Steve Ebersole + */ +public interface HibernateTypeSource { + /** + * Obtain the supplied Hibernate type name. + * + * @return The Hibernate type name + */ + String getName(); + + /** + * Obtain any supplied Hibernate type parameters. + * + * @return The Hibernate type parameters. + */ + Map getParameters(); + + /** + * Obtain the attribute's java type if possible. + * + * @return The java type of the attribute or null. + */ + JavaTypeDescriptor getJavaType(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifiableTypeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifiableTypeSource.java new file mode 100644 index 000000000000..fdbb24e9f8d6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifiableTypeSource.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Collection; +import java.util.List; + +import org.hibernate.metamodel.spi.LocalBindingContext; +import org.hibernate.xml.spi.Origin; + +/** + * Common contract between Entity and MappedSuperclass sources. The + * terminology is taken from JPA's {@link javax.persistence.metamodel.IdentifiableType} + * + * @author Steve Ebersole + */ +public interface IdentifiableTypeSource extends AttributeSourceContainer { + /** + * Obtain the origin of this source. + * + * @return The origin of this source. + */ + public Origin getOrigin(); + + /** + * Obtain the binding context local to this entity source. + * + * @return The local binding context + */ + public LocalBindingContext getLocalBindingContext(); + + /** + * Get the hierarchy this belongs to. + * + * @return The hierarchy this belongs to. + */ + public EntityHierarchySource getHierarchy(); + + /** + * Get the name of this type. + *

      + * Ultimately this is the value used to resolve + * {@link org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor} + * and {@link org.hibernate.metamodel.spi.domain.Type} references. It + * requires a little bit of decoding on the source side of things to + * account for entity-mode, entity-name, class-name and contextual + * default package name. + * + * @return The name of this type. + */ + public String getTypeName(); + + public IdentifiableTypeSource getSuperType(); + + /** + * Access the subtype sources for types extending from this type source, + * + * @return Sub-type sources + */ + public Collection getSubTypes(); + + /** + * Access to the sources describing JPA lifecycle callbacks. + * + * @return JPA lifecycle callback sources + */ + public List getJpaCallbackClasses(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifierGeneratorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifierGeneratorSource.java new file mode 100644 index 000000000000..e3044af9c90d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifierGeneratorSource.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Map; + +/** + * @author Steve Ebersole + */ +public interface IdentifierGeneratorSource { + /** + * Retrieve the name of the generator specification. This is the name used in + * {@link javax.persistence.GeneratedValue}, not the name of the underlying table/sequence! + * + * @return The generator name + */ + public String getGeneratorName(); + + /** + * Retrieve the name of the generator implementation name. This is either

        + *
      • an FQN naming the {@link org.hibernate.id.IdentifierGenerator} implementation
      • + *
      • the recognized "short name" of a built-in {@link org.hibernate.id.IdentifierGenerator} implementation
      • + *
      + * + * @return the generator implementation name + */ + public String getGeneratorImplementationName(); + + /** + * Retrieve the generator config parameters + * + * @return generator configuration parameters + */ + public Map getParameters(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifierSource.java new file mode 100644 index 000000000000..b828eebad0e6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IdentifierSource.java @@ -0,0 +1,77 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; + +/** + * Contract describing source of identifier information for the entity. + * + * @author Steve Ebersole + */ +public interface IdentifierSource extends ToolingHintSourceContainer { + /** + * Obtain the identifier generator source. + * + * @todo this should name a source as well, no? + * Basically, not sure it should be up to the sources to build binding objects. + * IdentifierGeneratorSource, possibly as a hierarchy as well to account for differences + * in "global" versus "local" declarations + * + * @return The generator source. + */ + IdentifierGeneratorDefinition getIdentifierGeneratorDescriptor(); + + /** + * Obtain the nature of this identifier source. + * + * @return The identifier source's nature. + */ + public EntityIdentifierNature getNature(); + + /** + * Returns the "unsaved" entity identifier value. + * + * @todo Not sure this is relevant for anything other than simple identifiers. Move to SimpleIdentifierSource ? + * + * @return the "unsaved" entity identifier value + */ + public String getUnsavedValue(); + + /** + * Retrieve the class specified as the {@link javax.persistence.IdClass}, if one. + * + * @return The class specified as the {@link javax.persistence.IdClass}, or {@code null} if none. + */ + public Class getLookupIdClass(); + + /** + * Obtain the property accessor name for the {@link javax.persistence.IdClass}, if one. + * + * @return The property accessor name for the {@link javax.persistence.IdClass}, or {@code null} if none. + **/ + public String getIdClassPropertyAccessorName(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/InLineViewSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/InLineViewSource.java new file mode 100644 index 000000000000..57aa707027db --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/InLineViewSource.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes in-line view source information. Generally, either {@link org.hibernate.annotations.Subselect} + * or {@code } + * + * @author Steve Ebersole + */ +public interface InLineViewSource extends TableSpecificationSource { + /** + * Obtain the {@code SQL SELECT} statement to use. Cannot be null! + * + * @return The {@code SQL SELECT} statement + */ + public String getSelectStatement(); + + public String getLogicalName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IndexConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IndexConstraintSource.java new file mode 100644 index 000000000000..c5fa4114b3c6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IndexConstraintSource.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Defining a index constraint source + * + * @author Brett Meyer + */ +public interface IndexConstraintSource extends ConstraintSource { + public boolean isUnique(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IndexedPluralAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IndexedPluralAttributeSource.java new file mode 100644 index 000000000000..930985debda1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/IndexedPluralAttributeSource.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * + */ +public interface IndexedPluralAttributeSource extends PluralAttributeSource { + PluralAttributeIndexSource getIndexSource(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/InvalidMappingException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/InvalidMappingException.java new file mode 100644 index 000000000000..9f9e0c87db4d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/InvalidMappingException.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.source.spi; + +import org.hibernate.xml.spi.Origin; + +/** + * @author Brett Meyer + */ +public class InvalidMappingException extends org.hibernate.InvalidMappingException { + + private final Origin origin; + + public InvalidMappingException(Origin origin) { + super( + String.format( "Could not parse mapping document: %s (%s)", origin.getName(), origin.getType() ), + origin + ); + this.origin = origin; + } + + public InvalidMappingException(Origin origin, Throwable e) { + super( + String.format( "Could not parse mapping document: %s (%s)", origin.getName(), origin.getType() ), + origin.getType().name(), + origin.getName(), + e + ); + this.origin = origin; + } + + public Origin getOrigin() { + return origin; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/JoinedSubclassEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/JoinedSubclassEntitySource.java new file mode 100644 index 000000000000..f0f3a52659b0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/JoinedSubclassEntitySource.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +/** + * @author Strong Liu + */ +public interface JoinedSubclassEntitySource extends SubclassEntitySource, ForeignKeyContributingSource { + /** + * The {@code PrimaryKeyJoinColumns} mapping for the joined-subclass. + * + * @return The {@code PrimaryKeyJoinColumnSource} lists defined on the joined subclass or null otherwise. + */ + public List getPrimaryKeyColumnSources(); + boolean isCascadeDeleteEnabled(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/JpaCallbackSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/JpaCallbackSource.java new file mode 100644 index 000000000000..1c9762696dda --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/JpaCallbackSource.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.lang.annotation.Annotation; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import javax.persistence.PostLoad; +import javax.persistence.PostPersist; +import javax.persistence.PostRemove; +import javax.persistence.PostUpdate; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +public interface JpaCallbackSource { + + /** + * @param callbackType {@link PrePersist}, {@link PreRemove}, {@link PreUpdate}, {@link PostLoad}, + * {@link PostPersist}, {@link PostRemove}, or {@link PostUpdate} + * @return the name of the JPA callback method defined for the associated {@link Entity entity} or {@link MappedSuperclass + * mapped superclass} and for the supplied callback annotation class. + */ + String getCallbackMethod(Class callbackType); + + /** + * @return the name of the instantiated container where the JPA callbacks for the associated {@link Entity entity} or + * {@link MappedSuperclass mapped superclass} are defined. This can be either the entity/mapped superclass itself or an + * {@link EntityListeners entity listener}. + */ + String getName(); + + /** + * @return true if this callback class represents callbacks defined within an {@link EntityListeners entity + * listener}. + */ + boolean isListener(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappedByAssociationSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappedByAssociationSource.java new file mode 100644 index 000000000000..64c08e829b25 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappedByAssociationSource.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface MappedByAssociationSource extends AssociationSource { + + String getMappedBy(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappedSuperclassSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappedSuperclassSource.java new file mode 100644 index 000000000000..446486c418e0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappedSuperclassSource.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Steve Ebersole + */ +public interface MappedSuperclassSource extends IdentifiableTypeSource { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingDefaults.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingDefaults.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingDefaults.java index bb66dc64f080..db200fe92e6f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingDefaults.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingDefaults.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.source.spi; import org.hibernate.cache.spi.access.AccessType; @@ -62,6 +62,13 @@ public interface MappingDefaults { */ public String getIdColumnName(); + /** + * Identifies the default column name to use for the tenant identifier column if non is specified in the mapping. + * + * @return The default tenant identifier column name + */ + public String getTenantIdColumnName(); + /** * Identifies the default column name to use for the discriminator column if none specified in the mapping. * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingException.java similarity index 84% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingException.java index 47bd55cf87a9..fa0e540e08e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingException.java @@ -22,17 +22,16 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.source.spi; -import org.hibernate.HibernateException; -import org.hibernate.internal.jaxb.Origin; +import org.hibernate.xml.spi.Origin; /** * Indicates a problem parsing a mapping document. * * @author Steve Ebersole */ -public class MappingException extends HibernateException { +public class MappingException extends org.hibernate.MappingException { private final Origin origin; public MappingException(String message, Origin origin) { @@ -45,6 +44,11 @@ public MappingException(String message, Throwable root, Origin origin) { this.origin = origin; } + @Override + public String getMessage() { + return super.getMessage() + " : origin(" + origin.getName() + ")"; + } + public Origin getOrigin() { return origin; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingNotFoundException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingNotFoundException.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingNotFoundException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingNotFoundException.java index a0702f165ef4..f80957114793 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MappingNotFoundException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MappingNotFoundException.java @@ -22,9 +22,9 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.source.spi; -import org.hibernate.internal.jaxb.Origin; +import org.hibernate.xml.spi.Origin; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetaAttributeContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MetaAttributeContext.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/MetaAttributeContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MetaAttributeContext.java index 461c03186322..2f9fb8b4ed25 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/MetaAttributeContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MetaAttributeContext.java @@ -21,13 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.source.spi; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.hibernate.metamodel.binding.MetaAttribute; +import org.hibernate.metamodel.spi.binding.MetaAttribute; /** * @author Steve Ebersole @@ -67,7 +67,7 @@ public Iterable getLocalKeys() { public MetaAttribute getMetaAttribute(String key) { MetaAttribute value = getLocalMetaAttribute( key ); - if ( value == null ) { + if ( value == null && parentContext != null ) { // recursive call value = parentContext.getMetaAttribute( key ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MultiTenancySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MultiTenancySource.java new file mode 100644 index 000000000000..ddbadf3049c4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/MultiTenancySource.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Steve Ebersole + */ +public interface MultiTenancySource { + /** + * Obtain the column/formula information about the multi-tenancy discriminator. + * + * @return The column/formula information + */ + public RelationalValueSource getRelationalValueSource(); + + public boolean isShared(); + + public boolean bindAsParameter(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/NonAggregatedCompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/NonAggregatedCompositeIdentifierSource.java new file mode 100644 index 000000000000..550a51eacf50 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/NonAggregatedCompositeIdentifierSource.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +/** + * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is + * {@link org.hibernate.id.EntityIdentifierNature#NON_AGGREGATED_COMPOSITE }. + * + * @author Steve Ebersole + */ +public interface NonAggregatedCompositeIdentifierSource extends CompositeIdentifierSource { + /** + * Obtain the source descriptor for the identifier attribute. + * + * @return The identifier attribute source. + */ + public List getAttributeSourcesMakingUpIdentifier(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/Orderable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/Orderable.java new file mode 100644 index 000000000000..514579eaeb38 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/Orderable.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Contact to define if a plural attribute source is orderable or not. + * + * @author Steve Ebersole + */ +public interface Orderable { + /** + * If the source of plural attribute is supposed to be applied the order by when loading. + * + * @return true for applying the order by or false means not. + */ + boolean isOrdered(); + + /** + * The order by clause used during loading this plural attribute. + * + *

      + * If the ordering element is not specified, ordering by + * the primary key of the associated entity is assumed + * + * {@see javax.persistence.OrderBy#value()} + * + * @return The order by clause used during loading this plural attribute from DB. + */ + String getOrder(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSource.java similarity index 89% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSource.java index aeb60a31ea81..dd4b4d39a962 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/PluralAttributeElementSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSource.java @@ -21,12 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; + +import org.hibernate.metamodel.spi.PluralAttributeElementNature; /** * @author Steve Ebersole + * @author Gail Badner */ public interface PluralAttributeElementSource { public PluralAttributeElementNature getNature(); - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceAssociation.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceAssociation.java new file mode 100644 index 000000000000..fc729c0579a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceAssociation.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface PluralAttributeElementSourceAssociation extends PluralAttributeElementSource, AssociationSource { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceBasic.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceBasic.java new file mode 100644 index 000000000000..984785501c0a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceBasic.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source for the elements of persistent collections (plural + * attributes) where the elements are basic types + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementSourceBasic extends PluralAttributeElementSource, RelationalValueSourceContainer { + public HibernateTypeSource getExplicitHibernateTypeSource(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceEmbedded.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceEmbedded.java new file mode 100644 index 000000000000..4cce967a729f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceEmbedded.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source for the elements of persistent collections (plural + * attributes) where the elements are composites/embeddables. + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementSourceEmbedded + extends PluralAttributeElementSource, + EmbeddableSourceContributor, CascadeStyleSource, ToolingHintSourceContainer { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceManyToAny.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceManyToAny.java new file mode 100644 index 000000000000..609ea26adfb2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceManyToAny.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source for the elements of persistent collections (plural + * attributes) where the elements are defined by Hibernate's any mapping + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementSourceManyToAny + extends PluralAttributeElementSource, AssociationSource { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceManyToMany.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceManyToMany.java new file mode 100644 index 000000000000..d299d674ae86 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceManyToMany.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.engine.FetchTiming; + +/** + * Describes the source for the elements of persistent collections (plural + * attributes) where the elements are many-to-many association + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementSourceManyToMany + extends PluralAttributeElementSource, AssociationSource, RelationalValueSourceContainer, ForeignKeyContributingSource, Orderable { + public String getReferencedEntityName(); + + public String getReferencedEntityAttributeName(); + + public boolean isIgnoreNotFound(); + + public String getExplicitForeignKeyName(); + + public boolean isUnique(); + + public FilterSource[] getFilterSources(); + + public String getWhere(); + + public FetchTiming getFetchTiming(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceOneToMany.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceOneToMany.java new file mode 100644 index 000000000000..ed74ef81bd86 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceOneToMany.java @@ -0,0 +1,36 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source for the elements of persistent collections (plural + * attributes) where the elements are a one-to-many association + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementSourceOneToMany extends PluralAttributeElementSource, AssociationSource { + public String getReferencedEntityName(); + + public boolean isIgnoreNotFound(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceResolver.java new file mode 100644 index 000000000000..03d9d5a3d465 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeElementSourceResolver.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface PluralAttributeElementSourceResolver { + PluralAttributeElementSource resolvePluralAttributeElementSource(AttributeSourceResolutionContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeIndexSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeIndexSource.java new file mode 100644 index 000000000000..367044fc2797 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeIndexSource.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; + +/** + * Highly abstract concept of the index of an "indexed persistent collection". + * More concretely (and generally more usefully) categorized as either:

        + *
      • {@link PluralAttributeSequentialIndexSource} - for list/array indexes
      • + *
      • {@link PluralAttributeMapKeySource} - for map keys
      • + *
      + * + */ +public interface PluralAttributeIndexSource extends RelationalValueSourceContainer { + PluralAttributeIndexNature getNature(); + List getDefaultNamingStrategies(); + /** + * Obtain information about the Hibernate index type ({@link org.hibernate.type.Type}) + * for this plural attribute index. + * + * @return The Hibernate type information + */ + public HibernateTypeSource getTypeInformation(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeIndexSourceResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeIndexSourceResolver.java new file mode 100644 index 000000000000..06fae6b0b178 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeIndexSourceResolver.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface PluralAttributeIndexSourceResolver { + PluralAttributeIndexSource resolvePluralAttributeIndexSource(AttributeSourceResolutionContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeKeySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeKeySource.java new file mode 100644 index 000000000000..bc617905407a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeKeySource.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source mapping of plural-attribute (collection) foreign-key information. + * + * @author Steve Ebersole + */ +public interface PluralAttributeKeySource extends ForeignKeyContributingSource, RelationalValueSourceContainer { + public boolean isCascadeDeleteEnabled(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySource.java new file mode 100644 index 000000000000..b08af902efdb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySource.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes source information about the key of a persistent map. At high + * level this broken down further into 2 categories:
        + *
      • {@link PluralAttributeMapKeySourceEntityAttribute}
      • + *
      • + *
          + *
        • {@link PluralAttributeMapKeySourceBasic}
        • + *
        • {@link PluralAttributeMapKeySourceEmbedded}
        • + *
        • {@link PluralAttributeMapKeySourceToOne}
        • + *
        + *
      • + *
      + *

      + * {@link PluralAttributeMapKeySourceEntityAttribute} is only relevant from + * annotations when using {@link javax.persistence.MapKey}. + * + * @author Steve Ebersole + */ +public interface PluralAttributeMapKeySource extends PluralAttributeIndexSource { + public static enum Nature { + BASIC, + EMBEDDED, + TO_ONE + } + + public Nature getMapKeyNature(); + + /** + * Is this plural attribute index source for an attribute of the referenced entity + * (relevant only for one-to-many and many-to-many associations)? + * + * If this method returns {@code true}, then this object can safely + * be cast to {@link PluralAttributeMapKeySourceEntityAttribute}. + * + * @return true, if this plural attribute index source for an attribute of the referenced + * entity; false, otherwise. + */ + public boolean isReferencedEntityAttribute(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceBasic.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceBasic.java new file mode 100644 index 000000000000..f9bc9ed7fecb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceBasic.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface PluralAttributeMapKeySourceBasic extends PluralAttributeIndexSource { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceEmbedded.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceEmbedded.java new file mode 100644 index 000000000000..9d1cb9a88f97 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceEmbedded.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface PluralAttributeMapKeySourceEmbedded + extends PluralAttributeIndexSource, EmbeddableSourceContributor { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceEntityAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceEntityAttribute.java new file mode 100644 index 000000000000..dbd0a1fecebe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceEntityAttribute.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Represents a map key where the map key value is actually the attribute value + * from the referenced entity. + * + * Only relevant to one-to-many and many-to-many associations mapped using + * the JPA {@link javax.persistence.MapKey} annotation. + * + * @author Gail Badner + * @author Steve Ebersole + */ +public interface PluralAttributeMapKeySourceEntityAttribute extends PluralAttributeIndexSource { + /** + * The attribute name as reported by {@link javax.persistence.MapKey#name()} + * + * @return The attribute name; {@code null} indicates that the associated entity's + * id attribute should be used. + */ + public String getAttributeName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceToOne.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceToOne.java new file mode 100644 index 000000000000..82625a82b329 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeMapKeySourceToOne.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Steve Ebersole + */ +public interface PluralAttributeMapKeySourceToOne extends PluralAttributeMapKeySource { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeSequentialIndexSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeSequentialIndexSource.java new file mode 100644 index 000000000000..0c9e156a4608 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeSequentialIndexSource.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Defines the index of a persistent list/array + * + * @author Gail Badner + * @author Steve Ebersole + */ +public interface PluralAttributeSequentialIndexSource extends PluralAttributeIndexSource { + /** + * Hibernate allows specifying the base value to use when storing the index + * to the database. This reports that "offset" value. + * + * @return The index base value. + */ + int base(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeSource.java new file mode 100644 index 000000000000..cd2e8c6ee25b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/PluralAttributeSource.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.CustomSQL; + +/** + * @author Steve Ebersole + */ +public interface PluralAttributeSource + extends AttributeSource, FetchableAttributeSource, PluralAttributeElementSourceResolver { + public PluralAttributeNature getNature(); + + public CollectionIdSource getCollectionIdSource(); + + public PluralAttributeKeySource getKeySource(); + + public PluralAttributeElementSource getElementSource(); + + public FilterSource[] getFilterSources(); + + public JavaTypeDescriptor getElementTypeDescriptor(); + + public TableSpecificationSource getCollectionTableSpecificationSource(); + + public String getCollectionTableComment(); + + public String getCollectionTableCheck(); + + public Caching getCaching(); + + public String getCustomPersisterClassName(); + + public String getWhere(); + + public boolean isInverse(); + + public boolean isMutable(); + + public String getCustomLoaderName(); + + public CustomSQL getCustomSqlInsert(); + + public CustomSQL getCustomSqlUpdate(); + + public CustomSQL getCustomSqlDelete(); + + public CustomSQL getCustomSqlDeleteAll(); + + public String getMappedBy(); + + public int getBatchSize(); + + public boolean usesJoinTable(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/RelationalValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/RelationalValueSource.java new file mode 100644 index 000000000000..3f2a7bab6b3d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/RelationalValueSource.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Unifying interface for {@link ColumnSource} and {@link DerivedValueSource}. + * + * @author Steve Ebersole + * + * @see ColumnSource + * @see DerivedValueSource + */ +public interface RelationalValueSource { + /** + * @return returns the name of the table that contains this value. + */ + public String getContainingTableName(); + + /** + * Retrieve the nature of this relational value. Is it a column? Or is it a derived value (formula)? + * + * @return The nature. + */ + public Nature getNature(); + + public static enum Nature { + COLUMN( ColumnSource.class ), + DERIVED( DerivedValueSource.class ); + + private final Class specificContractClass; + + private Nature(Class specificContractClass) { + this.specificContractClass = specificContractClass; + } + + public Class getSpecificContractClass() { + return specificContractClass; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/RelationalValueSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/RelationalValueSourceContainer.java new file mode 100644 index 000000000000..95e74d99c05d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/RelationalValueSourceContainer.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +/** + * Contract for a container of {@link RelationalValueSource} references. Multiple types of things operate as sources + * of "relational value" information; some examples include:

        + *
      • id attribute(s) mappings
      • + *
      • basic attribute mappings
      • + *
      • composite attribute mappings
      • + *
      • plural attribute mappings
      • + *
      • etc
      • + *
      + * + * Not only does it provide access to the relational value sources ({@link #relationalValueSources()}, it also defines + * contextual information for those sources in terms of default values. + * + * See {@link RelationalValueSource} for additional details. + * + * @author Steve Ebersole + */ +public interface RelationalValueSourceContainer extends ColumnBindingDefaults { + /** + * Obtain the contained {@link RelationalValueSource} references. + * + * @return The contained {@link RelationalValueSource} references. + */ + public List relationalValueSources(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SecondaryTableSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SecondaryTableSource.java new file mode 100644 index 000000000000..53e5e84f4874 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SecondaryTableSource.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.spi.binding.CustomSQL; + +/** + * @author Steve Ebersole + */ +public interface SecondaryTableSource extends ForeignKeyContributingSource { + /** + * Obtain the table being joined to. + * + * @return The joined table. + */ + public TableSpecificationSource getTableSource(); + + /** + * Retrieves the columns defines as making up this secondary tables primary key. Each entry should have + * a corresponding entry in the foreign-key columns described by the {@link ForeignKeyContributingSource} + * aspect of this contract. + * + * @return The columns defining the primary key for this secondary table + */ + public List getPrimaryKeyColumnSources(); + + public String getComment(); + + public FetchStyle getFetchStyle(); + + public boolean isInverse(); + + public boolean isOptional(); + + public boolean isCascadeDeleteEnabled(); + + /** + * Obtain the custom SQL to be used for inserts for this entity + * + * @return The custom insert SQL + */ + public CustomSQL getCustomSqlInsert(); + + /** + * Obtain the custom SQL to be used for updates for this entity + * + * @return The custom update SQL + */ + public CustomSQL getCustomSqlUpdate(); + + /** + * Obtain the custom SQL to be used for deletes for this entity + * + * @return The custom delete SQL + */ + public CustomSQL getCustomSqlDelete(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SimpleIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SimpleIdentifierSource.java similarity index 86% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SimpleIdentifierSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SimpleIdentifierSource.java index 90585ae216fb..14741ca9bc1e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SimpleIdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SimpleIdentifierSource.java @@ -21,10 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; /** - * Contract describing source of a simple identifier mapping. + * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE simple}. * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SingularAttributeSource.java new file mode 100644 index 000000000000..ece74136878b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SingularAttributeSource.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.SingularAttributeNature; + +/** + * Source-agnostic description of information needed to bind a singular attribute. + * + * @author Steve Ebersole + */ +public interface SingularAttributeSource extends AttributeSource, AttributeRelationalValueSourceContainer { + /** + * Determine whether this is a virtual attribute or whether it physically exists on the users domain model. + * + * @return {@code true} indicates the attribute is virtual, meaning it does NOT exist on the domain model; + * {@code false} indicates the attribute physically exists. + */ + public boolean isVirtualAttribute(); + + /** + * Obtain the nature of this attribute type. + * + * @return The attribute type nature + */ + public SingularAttributeNature getSingularAttributeNature(); + + /** + * Obtain a description of if/when the attribute value is generated by the database. + * + * @return The attribute value generation information + */ + public PropertyGeneration getGeneration(); + + /** + * Should the attribute be (bytecode enhancement) lazily loaded? + * + * @return {@code true} to indicate the attribute should be lazily loaded. + */ + public boolean isLazy(); + + /** + * Retrieve the natural id mutability + * + * @return The mutability, see enum for meanings + */ + public NaturalIdMutability getNaturalIdMutability(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SizeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SizeSource.java new file mode 100644 index 000000000000..14b82258150d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SizeSource.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface SizeSource { + /** + * Is length defined? + * + * @return true, if length is defined; false, otherwise. + */ + boolean isLengthDefined(); + + /** + * If length is defined (as determined by {@link #isLengthDefined()}), then + * the length is returned. + * + * @return the length, if defined. + * @throws UnsupportedOperationException if length is not defined. + */ + int getLength(); + + /** + * Is precision defined? + * + * @return true, if precision is defined; false, otherwise. + */ + boolean isPrecisionDefined(); + + /** + * If precision is defined (as determined by {@link #isPrecisionDefined()}), then + * the precision is returned. + * + * @return the precision, if defined. + * @throws UnsupportedOperationException if precision is not defined. + * + * @see {@link #isPrecisionDefined()} + */ + int getPrecision(); + + /** + * Is scale defined? + * + * @return true, if scale is defined; false, otherwise. + */ + boolean isScaleDefined(); + + + /** + * If scale is defined (as determined by {@link #isScaleDefined()}), then + * the scale is returned. + * + * @return the scale, if defined. + * @throws UnsupportedOperationException if scale is not defined. + * + * @see {@link #isScaleDefined()} + */ + int getScale(); + + SizeSource NULL = new SizeSource() { + @Override + public boolean isLengthDefined() { + return false; + } + + @Override + public int getLength() { + return 0; + } + + @Override + public boolean isPrecisionDefined() { + return false; + } + + @Override + public int getPrecision() { + return 0; + } + + @Override + public boolean isScaleDefined() { + return false; + } + + @Override + public int getScale() { + return 0; + } + }; + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/Sortable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/Sortable.java new file mode 100644 index 000000000000..a4c9e532918d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/Sortable.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Contact to define if the source of plural attribute is sortable or not. + * + * @author Steve Ebersole + */ +public interface Sortable { + /** + * If the source of plural attribute is supposed to be sorted. + * + * @return true the attribute will be sortable or false means not. + */ + boolean isSorted(); + + /** + * The comparator class name which will be used to sort the attribute. + * + * @return Qualified class name which implements {@link java.util.Comparator} contact. + */ + String getComparatorName(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntityContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SubclassEntityContainer.java similarity index 85% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntityContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SubclassEntityContainer.java index a73a9ed28340..7c766d52f6cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntityContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SubclassEntityContainer.java @@ -21,15 +21,14 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; /** - * Contract for elements within a {@link EntityHierarchy} which can contain sub elements. Essentially this + * Contract for elements within a {@link EntityHierarchySource} which can contain sub elements. Essentially this * abstracts that common aspect away from both root and sub entities. * * @author Steve Ebersole */ public interface SubclassEntityContainer { - public void add(SubclassEntitySource subclassEntitySource); public Iterable subclassEntitySources(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SubclassEntitySource.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntitySource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SubclassEntitySource.java index 636226758e9e..a9767a1dae5e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SubclassEntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/SubclassEntitySource.java @@ -21,10 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; /** * @author Steve Ebersole + * @author Strong Liu */ public interface SubclassEntitySource extends EntitySource { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TableSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TableSource.java new file mode 100644 index 000000000000..b90291a38044 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TableSource.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Contract describing source of table information + * + * @author Steve Ebersole + */ +public interface TableSource extends TableSpecificationSource { + /** + * Obtain the supplied table name. + * + * @return The table name, or {@code null} is no name specified. + */ + String getExplicitTableName(); + + String getRowId(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TableSpecificationSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TableSpecificationSource.java new file mode 100644 index 000000000000..af57ae42787d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TableSpecificationSource.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Contract describing source of "table specification" information. + * + * @author Steve Ebersole + * + * @see org.hibernate.metamodel.spi.relational.TableSpecification + */ +public interface TableSpecificationSource { + /** + * Obtain the supplied schema name + * + * @return The schema name. If {@code null}, the binder will apply the default. + */ + public String getExplicitSchemaName(); + + /** + * Obtain the supplied catalog name + * + * @return The catalog name. If {@code null}, the binder will apply the default. + */ + public String getExplicitCatalogName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToOneAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToOneAttributeSource.java new file mode 100644 index 000000000000..0b1d8606d273 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToOneAttributeSource.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.List; + +import org.hibernate.metamodel.internal.binder.Binder; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Further contract for sources of {@code *-to-one} style associations. + * + * @author Steve Ebersole + */ +public interface ToOneAttributeSource + extends SingularAttributeSource, + ToOneAttributeSourceNatureResolver, + ForeignKeyContributingSource, + FetchableAttributeSource, + AssociationSource { + + public boolean isUnique(); + public boolean isUnWrapProxy(); + ForeignKeyDirection getForeignKeyDirection(); + public List getDefaultNamingStrategies(final String entityName, final String tableName, final AttributeBinding referencedAttributeBinding); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToOneAttributeSourceNatureResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToOneAttributeSourceNatureResolver.java new file mode 100644 index 000000000000..7b251e80960a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToOneAttributeSourceNatureResolver.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Gail Badner + */ +public interface ToOneAttributeSourceNatureResolver { + + /** + * Perform any steps to completely resolve this attribute source. + * + * If this is a {@link MappedByAssociationSource}, resolution must + * resolve the association owner, and this association must be added + * to the owner's "owned" associations. + * + * @param context + */ + void resolveToOneAttributeSource(AttributeSourceResolutionContext context); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToolingHintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToolingHintSource.java new file mode 100644 index 000000000000..d045744ae345 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToolingHintSource.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * Describes the source of a tooling hint. + *

      + * This is equivalent to the legacy {@link org.hibernate.mapping.MetaAttribute} and only + * comes from {@code hbm} via the {@code } element(s) and the new unified + * XML schema as a {@code }. + * + * @author Steve Ebersole + */ +public interface ToolingHintSource { + /** + * Obtain the supplied meta-attribute name + * + * @return The meta-attribute name + */ + public String getName(); + + /** + * Obtain the supplied meta-attribute value. + * + * @return The meta-attribute value + */ + public String getValue(); + + /** + * Is the meta-attribute value inheritable? + * + * @return Is the value inheritable? + */ + public boolean isInheritable(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToolingHintSourceContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToolingHintSourceContainer.java new file mode 100644 index 000000000000..b769339b15dc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/ToolingHintSourceContainer.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Collection; + +/** + * Describes the source of tooling hints. + * + * @author Strong Liu + * @author Steve Ebersole + */ +public interface ToolingHintSourceContainer { + /** + * Obtain the tooling hint sources associated with this container. + * + * @return The tooling hint sources. + */ + public Collection getToolingHintSources(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TypeDescriptorSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TypeDescriptorSource.java new file mode 100644 index 000000000000..3e77f801098e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/TypeDescriptorSource.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +import java.util.Map; + +/** + * Describes the source of a custom type description. For example, {@code } or + * {@link org.hibernate.annotations.TypeDef @TypeDefinition} + * + * @author Steve Ebersole + */ +public interface TypeDescriptorSource { + /** + * Retrieve the name of the type def. + * + * @return The name. + */ + String getName(); + + /** + * Retrieve the name of the class implementing {@link org.hibernate.type.Type}, + * {@link org.hibernate.usertype.UserType}, etc. + * + * @return The implementation class name. + */ + String getTypeImplementationClassName(); + + /** + * For what are termed "basic types" there is a registry that contain the type keyed by various + * keys. This is the mechanism that allows a "string type" to reference to by "string", "java.lang.String", + * etc in the mapping. This method returns the keys under which this type should be registered in + * that registry. + *

      + * Note that if the type def contains registration keys, it should be considered illegal for its + * corresponding {@link HibernateTypeSource} to define parameters. + * + * @return The registration keys for the type built from this type def. + */ + String[] getRegistrationKeys(); + + /** + * Types accept configuration. The values here represent the user supplied values that will be given + * to the type instance after instantiation + * + * @return The configuration parameters from the underlying source. + */ + Map getParameters(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/UniqueConstraintSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/UniqueConstraintSource.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/UniqueConstraintSource.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/UniqueConstraintSource.java index 0a247b09cf92..4e9511e385e3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/UniqueConstraintSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/UniqueConstraintSource.java @@ -21,7 +21,8 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.source.spi; + /** * Defining a unique constraint source diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/VersionAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/VersionAttributeSource.java new file mode 100644 index 000000000000..9953d1011081 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/VersionAttributeSource.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.source.spi; + +/** + * @author Steve Ebersole + */ +public interface VersionAttributeSource extends SingularAttributeSource { + public String getUnsavedValue(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/XsdException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/XsdException.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/XsdException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/XsdException.java index fac0104bf971..e921b011e42d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/XsdException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/XsdException.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source; +package org.hibernate.metamodel.source.spi; import org.hibernate.HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/package-info.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/package-info.java new file mode 100644 index 000000000000..c01c20c7addd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/spi/package-info.java @@ -0,0 +1,28 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +/** + * todo : Move org.hibernate.metamodel.spi.source here + */ +package org.hibernate.metamodel.source.spi; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AbstractAttributeKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AbstractAttributeKey.java new file mode 100644 index 000000000000..7f2eda3d704d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AbstractAttributeKey.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.internal.util.StringHelper; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractAttributeKey { + private final AbstractAttributeKey parent; + private final String property; + private final String fullPath; + + protected AbstractAttributeKey() { + this( null, "" ); + } + + protected AbstractAttributeKey(String base) { + this( null, base ); + } + + protected AbstractAttributeKey(AbstractAttributeKey parent, String property) { + this.parent = parent; + this.property = property; + + final String prefix; + if ( parent != null ) { + final String resolvedParent = parent.getFullPath(); + if ( StringHelper.isEmpty( resolvedParent ) ) { + prefix = ""; + } + else { + prefix = resolvedParent + getDelimiter(); + } + } + else { + prefix = ""; + } + + this.fullPath = prefix + property; + } + + protected abstract char getDelimiter(); + + public abstract AbstractAttributeKey append(String property); + + public AbstractAttributeKey getParent() { + return parent; + } + + public String getProperty() { + return property; + } + + public String getFullPath() { + return fullPath; + } + + public boolean isRoot() { + return parent == null; + } + + @Override + public String toString() { + return getFullPath(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final AbstractAttributeKey that = (AbstractAttributeKey) o; + return this.fullPath.equals( that.fullPath ); + + } + + @Override + public int hashCode() { + return fullPath.hashCode(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AbstractPersistentAttributeMemberResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AbstractPersistentAttributeMemberResolver.java new file mode 100644 index 000000000000..54e6fac33e19 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AbstractPersistentAttributeMemberResolver.java @@ -0,0 +1,220 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.persistence.AccessType; + +import org.hibernate.HibernateException; +import org.hibernate.metamodel.reflite.internal.ModifierUtils; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.reflite.spi.VoidDescriptor; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; + +/** + * "Template" support for writing PersistentAttributeMemberResolver + * implementations. + * + * @author Steve Ebersole + */ +public abstract class AbstractPersistentAttributeMemberResolver implements PersistentAttributeMemberResolver { + + /** + * This is the call that represents the bulk of the work needed to resolve + * the persistent attribute members. It is the strategy specific portion + * for sure. + *

      + * The expectation is to + * Here is the call that most likely changes per strategy. This occurs + * immediately after we have determined all the fields and methods marked as + * transient. The expectation is to + * + * @param transientFieldNames The set of all field names found to have been + * annotated as @Transient + * @param transientMethodNames The set of all method names found to have been + * annotated as @Transient + * @param managedTypeDescriptor The ManagedType Java type descriptor + * @param classLevelAccessType The AccessType determined for the class default + * @param localBindingContext The local binding context + */ + protected abstract List resolveAttributesMembers( + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext); + + @Override + public List resolveAttributesMembers( + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext) { + + final Set transientFieldNames = new HashSet(); + final Set transientMethodNames = new HashSet(); + collectMembersMarkedTransient( + transientFieldNames, + transientMethodNames, + managedTypeDescriptor, + localBindingContext + ); + + return resolveAttributesMembers( + transientFieldNames, + transientMethodNames, + managedTypeDescriptor, + classLevelAccessType, + localBindingContext + ); + } + + protected void collectMembersMarkedTransient( + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor, + LocalBindingContext localBindingContext) { + List transientMembers = managedTypeDescriptor.getJandexClassInfo() + .annotations() + .get( JPADotNames.TRANSIENT ); + if ( transientMembers == null ) { + return; + } + + for ( AnnotationInstance transientMember : transientMembers ) { + AnnotationTarget target = transientMember.target(); + + // todo : would could limit these to "persistable" fields/methods, but not sure its worth the processing to check.. + + if ( target instanceof FieldInfo ) { + transientFieldNames.add( ( (FieldInfo) target ).name() ); + } + else if ( target instanceof MethodInfo ) { + transientMethodNames.add( ( (MethodInfo) target ).name() ); + } + else { + throw localBindingContext.makeMappingException( + "@Transient should only be defined on field or method : " + target + ); + } + } + } + + + protected FieldDescriptor findFieldDescriptor(JavaTypeDescriptor javaTypeDescriptor, String name) { + for ( FieldDescriptor fieldDescriptor : javaTypeDescriptor.getDeclaredFields() ) { + // perform a series of opt-out checks + if ( ! fieldDescriptor.getName().equals( name ) ) { + continue; + } + + if ( ! isPersistable( fieldDescriptor ) ) { + continue; + } + + // no opt-outs above, we found it... + return fieldDescriptor; + } + + throw new HibernateException( + "Unable to locate persistent field [" + name + "] - class " + + javaTypeDescriptor.getName().toString() + ); + } + + @SuppressWarnings("RedundantIfStatement") + protected boolean isPersistable(FieldDescriptor fieldDescriptor) { + if ( Modifier.isTransient( fieldDescriptor.getModifiers() ) ) { + return false; + } + + if ( ModifierUtils.isSynthetic( fieldDescriptor ) ) { + return false; + } + + return true; + } + + protected MethodDescriptor findMethodDescriptor(JavaTypeDescriptor javaTypeDescriptor, String name) { + for ( MethodDescriptor methodDescriptor : javaTypeDescriptor.getDeclaredMethods() ) { + // perform a series of opt-out checks + if ( !methodDescriptor.getName().equals( name ) ) { + continue; + } + + if ( !isPersistable( methodDescriptor ) ) { + continue; + } + + // no opt-outs above, we found it... + return methodDescriptor; + } + + throw new HibernateException( + "Unable to locate persistent property method [" + name + "] - class " + + javaTypeDescriptor.getName().toString() + ); + } + + @SuppressWarnings("RedundantIfStatement") + protected boolean isPersistable(MethodDescriptor methodDescriptor) { + if ( !methodDescriptor.getArgumentTypes().isEmpty() ) { + return false; + } + + if ( methodDescriptor.getReturnType() == null + || methodDescriptor.getReturnType().getErasedType() == VoidDescriptor.INSTANCE ) { + return false; + } + + if ( !methodDescriptor.getName().startsWith( "get" ) + && !methodDescriptor.getName().startsWith( "is" ) ) { + return false; + } + + if ( Modifier.isStatic( methodDescriptor.getModifiers() ) ) { + return false; + } + + if ( ModifierUtils.isBridge( methodDescriptor ) ) { + return false; + } + + if ( ModifierUtils.isSynthetic( methodDescriptor ) ) { + return false; + } + + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java new file mode 100644 index 000000000000..60162eb14c96 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AdditionalJaxbRootProducer.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.List; + +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.xml.spi.BindResult; + +import org.jboss.jandex.IndexView; + +/** + * Contract for integrations that wish to provide additional mappings (in the form of + * {@link org.hibernate.xml.spi.BindResult}. This hook is performed after all other + * mappings, annotations, etc have completed processing. + * + * @author Steve Ebersole + */ +public interface AdditionalJaxbRootProducer { + /** + * Produce and return the list of additional mappings to be processed. + * + * @param metadataCollector The metadata (for access to binding information). + * @param context The context. + * + * @return List of additional mappings + * + * @see AdditionalJaxbRootProducerContext + */ + public List produceRoots( + InFlightMetadataCollector metadataCollector, + AdditionalJaxbRootProducerContext context); + + public interface AdditionalJaxbRootProducerContext { + + /** + * Gets the Jandex annotation index. + * + * @return the Jandex annotation index + */ + public IndexView getJandexIndex(); + + /** + * Gets the service registry. + * + * @return The service registry. + */ + public StandardServiceRegistry getServiceRegistry(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AttributePath.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AttributePath.java new file mode 100644 index 000000000000..b3538d436809 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AttributePath.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +/** + * An attribute path is, generally speaking, the path of attribute names back + * to a "root" (which is either an entity or a persistent collection). The + * name of this root typically is not included in the path. + * + * @author Steve Ebersole + */ +public class AttributePath extends AbstractAttributeKey { + public static final char DELIMITER = '.'; + + public AttributePath() { + super(); + } + + @Override + protected char getDelimiter() { + return DELIMITER; + } + + @Override + public AttributePath append(String property) { + return new AttributePath( this, property ); + } + + @Override + public AttributePath getParent() { + return (AttributePath) super.getParent(); + } + + public AttributePath(AttributePath parent, String property) { + super( parent, property ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AttributeRole.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AttributeRole.java new file mode 100644 index 000000000000..e0c9e39b6edf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/AttributeRole.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +/** + * An attribute role is, generally speaking, the path of attribute names back + * to a "root" (which is either an entity or a persistent collection). The + * name of this root typically is included in the path. + * + * @author Steve Ebersole + */ +public class AttributeRole extends AbstractAttributeKey { + public static final char DELIMITER = '#'; + + public AttributeRole(String base) { + super( base ); + } + + @Override + protected char getDelimiter() { + return DELIMITER; + } + + @Override + public AttributeRole append(String property) { + return new AttributeRole( this, property ); + } + + @Override + public AttributeRole getParent() { + return (AttributeRole) super.getParent(); + } + + private AttributeRole(AttributeRole parent, String property) { + super( parent, property ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/BaseDelegatingBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/BaseDelegatingBindingContext.java new file mode 100644 index 000000000000..6e439058b241 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/BaseDelegatingBindingContext.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.internal.annotations.JandexAccess; +import org.hibernate.metamodel.source.spi.MappingDefaults; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.service.ServiceRegistry; + +import org.jboss.jandex.DotName; + +/** + * @author Steve Ebersole + */ +public abstract class BaseDelegatingBindingContext implements BindingContext { + private final BindingContext parent; + + public BaseDelegatingBindingContext(BindingContext parent) { + this.parent = parent; + } + + protected BindingContext parent() { + return parent; + } + + @Override + public MetadataBuildingOptions getBuildingOptions() { + return parent.getBuildingOptions(); + } + + @Override + public JandexAccess getJandexAccess() { + return parent.getJandexAccess(); + } + + @Override + public JavaTypeDescriptorRepository getJavaTypeDescriptorRepository() { + return parent.getJavaTypeDescriptorRepository(); + } + + @Override + public ClassLoaderAccess getClassLoaderAccess() { + return parent.getClassLoaderAccess(); + } + + @Override + public MappingDefaults getMappingDefaults() { + return parent.getMappingDefaults(); + } + + @Override + public InFlightMetadataCollector getMetadataCollector() { + return parent.getMetadataCollector(); + } + + @Override + public MetaAttributeContext getGlobalMetaAttributeContext() { + return parent.getGlobalMetaAttributeContext(); + } + + @Override + public String qualifyClassName(String name) { + return parent.qualifyClassName( name ); + } + + @Override + public ServiceRegistry getServiceRegistry() { + return parent.getServiceRegistry(); + } + + @Override + public boolean quoteIdentifiersInContext() { + return parent.quoteIdentifiersInContext(); + } + + @Override + public Type makeDomainType(String className) { + return parent.makeDomainType( className ); + } + + @Override + public JavaTypeDescriptor typeDescriptor(String name) { + return parent.typeDescriptor( name ); + } + + @Override + public Type makeDomainType(DotName typeName) { + return parent.makeDomainType( typeName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/BindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/BindingContext.java new file mode 100644 index 000000000000..8039e25bd568 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/BindingContext.java @@ -0,0 +1,119 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.internal.annotations.JandexAccess; +import org.hibernate.metamodel.source.spi.MappingDefaults; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.domain.JavaClassReference; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.service.ServiceRegistry; + +import org.jboss.jandex.DotName; + +/** + * Describes the context in which binding (the process of build Metadata out of + * MetadataSources) occurs. + *

      + * BindingContext are generally hierarchical getting more specific as we "go + * down". E.g. global -> PU -> document -> mapping + * + * @author Steve Ebersole + */ +public interface BindingContext { + /** + * Access to the options specified by the {@link org.hibernate.metamodel.MetadataBuilder} + * + * @return The options + */ + public MetadataBuildingOptions getBuildingOptions(); + + public JandexAccess getJandexAccess(); + + /** + * Access to the "reflite" type repository + * + * @return The reflite type repo + */ + public JavaTypeDescriptorRepository getJavaTypeDescriptorRepository(); + + /** + * Access to mapping defaults in effect for this context + * + * @return The mapping defaults. + */ + public MappingDefaults getMappingDefaults(); + + /** + * Access to the collector of metadata as we build it. + * + * @return The metadata collector. + */ + public InFlightMetadataCollector getMetadataCollector(); + + /** + * Shortcut for {@link #getBuildingOptions()} -> {@link org.hibernate.metamodel.spi.MetadataBuildingOptions#getServiceRegistry()} + * + * @return The ServiceRegistry + */ + public ServiceRegistry getServiceRegistry(); + + /** + * Provides access to ClassLoader services when needed during binding + * + * @return The ClassLoaderAccess + */ + public ClassLoaderAccess getClassLoaderAccess(); + + public MetaAttributeContext getGlobalMetaAttributeContext(); + + /** + * Qualify a class name per the rules for this context + * + * @param name The class name + * + * @return The qualified name + */ + public String qualifyClassName(String name); + + public boolean quoteIdentifiersInContext(); + + public JavaTypeDescriptor typeDescriptor(String name); + + // todo : go away + + /** + * todo : maybe a `Type makeDomainType(JavaTypeDescriptor)` method instead? + * + * @deprecated use the JavaTypeDescriptorRepository instead, available from {@link #getJavaTypeDescriptorRepository} + */ + @Deprecated + public Type makeDomainType(String className); + + public Type makeDomainType(DotName typeName); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ClassLoaderAccess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ClassLoaderAccess.java new file mode 100644 index 000000000000..f9cebf0e5c5b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/ClassLoaderAccess.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +/** + * During the process of building this metamodel, accessing the ClassLoader + * is very discouraged. However, sometimes it is needed. This contract helps + * mitigate accessing the ClassLoader in these cases. + * + * @author Steve Ebersole + */ +public interface ClassLoaderAccess { + /** + * Obtain a Class reference by name + * + * @param name The name of the Class to get a reference to. + * + * @return The Class. + */ + public Class classForName(String name); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/InFlightMetadataCollector.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/InFlightMetadataCollector.java new file mode 100644 index 000000000000..f56d9b90c824 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/InFlightMetadataCollector.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.cfg.ObjectNameNormalizer; +import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; +import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.engine.spi.Mapping; +import org.hibernate.engine.spi.NamedQueryDefinition; +import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.NamedStoredProcedureQueryDefinition; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.FetchProfile; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.TypeDefinition; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.procedure.ProcedureCallMemento; +import org.hibernate.type.TypeResolver; + +/** + * @author Steve Ebersole + */ +public interface InFlightMetadataCollector extends Mapping, Metadata { + + Database getDatabase(); + + TypeResolver getTypeResolver(); + + ObjectNameNormalizer getObjectNameNormalizer(); + + void addImport(String entityName, String entityName1); + + void addEntity(EntityBinding entityBinding); + + void addSecondaryTable(SecondaryTable secondaryTable); + + PluralAttributeBinding getCollection(String role); + + void addCollection(PluralAttributeBinding collectionBinding); + + void addFetchProfile(FetchProfile profile); + + void addTypeDefinition(TypeDefinition typeDefinition); + + void addFilterDefinition(FilterDefinition filterDefinition); + + void addIdGenerator(IdentifierGeneratorDefinition generator); + + void registerIdentifierGenerator(String name, String clazz); + + void addNamedNativeQuery(NamedSQLQueryDefinition def); + + void addNamedEntityGraph(NamedEntityGraphDefinition def); + + void addNamedQuery(NamedQueryDefinition def); + + void addNamedStoredProcedureQueryDefinition(NamedStoredProcedureQueryDefinition definition); + + void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition); + + @Deprecated + void setGloballyQuotedIdentifiers(boolean b); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/LenientPersistentAttributeMemberResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/LenientPersistentAttributeMemberResolver.java new file mode 100644 index 000000000000..cf3dd91b86a5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/LenientPersistentAttributeMemberResolver.java @@ -0,0 +1,191 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import javax.persistence.AccessType; + +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; +import org.jboss.logging.Logger; + +/** + * PersistentAttributeMemberResolver implementation that is more lenient in some cases + * than the JPA specification with the idea of being more user friendly. + * + * @author Steve Ebersole + */ +public class LenientPersistentAttributeMemberResolver extends AbstractPersistentAttributeMemberResolver { + private static final Logger LOG = Logger.getLogger( LenientPersistentAttributeMemberResolver.class ); + + /** + * Singleton access + */ + public static final LenientPersistentAttributeMemberResolver INSTANCE = new LenientPersistentAttributeMemberResolver(); + + @Override + protected List resolveAttributesMembers( + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext) { + final LinkedHashMap attributeMemberMap = new LinkedHashMap(); + + collectAnnotatedMembers( + attributeMemberMap, + transientFieldNames, + transientMethodNames, + managedTypeDescriptor + ); + + collectNonAnnotatedMembers( + attributeMemberMap, + transientFieldNames, + transientMethodNames, + managedTypeDescriptor + ); + + return new ArrayList( attributeMemberMap.values() ); + } + + private void collectAnnotatedMembers( + LinkedHashMap attributeMemberMap, + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor) { + for ( List annotationInstances : + managedTypeDescriptor.getJandexClassInfo().annotations().values() ) { + + for ( AnnotationInstance annotationInstance : annotationInstances ) { + final String annotationTypeName = annotationInstance.name().toString(); + if ( !annotationTypeName.startsWith( "javax.persistence." ) + && !annotationTypeName.startsWith( "org.hibernate.annotations." ) ) { + continue; + } + + final AnnotationTarget target = annotationInstance.target(); + if ( FieldInfo.class.isInstance( target ) ) { + final FieldInfo field = (FieldInfo) target; + + if ( transientFieldNames.contains( field.name() ) ) { + continue; + } + + final MemberDescriptor existing = attributeMemberMap.get( field.name() ); + if ( existing != null ) { + if ( !FieldDescriptor.class.isInstance( existing ) ) { + LOG.warnf( + "Found annotations split between field [%s] and method [%s]", + field.name(), + existing.getName() + ); + } + continue; + } + + attributeMemberMap.put( + field.name(), + findFieldDescriptor( managedTypeDescriptor, field.name() ) + ); + } + else if ( MethodInfo.class.isInstance( target ) ) { + final MethodInfo method = (MethodInfo) target; + if ( transientMethodNames.contains( method.name() ) ) { + continue; + } + + final String attributeName = ReflectHelper.getPropertyNameFromGetterMethod( method.name() ); + final MemberDescriptor existing = attributeMemberMap.get( attributeName ); + + if ( existing != null ) { + if ( !MethodDescriptor.class.isInstance( existing ) ) { + LOG.warnf( + "Found annotations split between field [%s] and method [%s]", + existing.getName(), + method.name() + ); + } + continue; + } + + attributeMemberMap.put( + attributeName, + findMethodDescriptor( managedTypeDescriptor, method.name() ) + ); + } + } + } + } + + private void collectNonAnnotatedMembers( + LinkedHashMap attributeMemberMap, + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor) { + for ( MethodDescriptor method : managedTypeDescriptor.getDeclaredMethods() ) { + if ( !isPersistable( method ) ) { + continue; + } + + if ( transientMethodNames.contains( method.getName() ) ) { + continue; + } + + final String attributeName = ReflectHelper.getPropertyNameFromGetterMethod( method.getName() ); + if ( attributeMemberMap.containsKey( attributeName ) ) { + continue; + } + + attributeMemberMap.put( attributeName, method ); + } + + for ( FieldDescriptor field : managedTypeDescriptor.getDeclaredFields() ) { + if ( !isPersistable( field ) ) { + continue; + } + + if ( transientFieldNames.contains( field.getName() ) ) { + continue; + } + + if ( attributeMemberMap.containsKey( field.getName() ) ) { + continue; + } + + attributeMemberMap.put( field.getName(), field ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/LocalBindingContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/LocalBindingContext.java new file mode 100644 index 000000000000..77fec9287023 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/LocalBindingContext.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.xml.spi.Origin; + +/** + * Specialization of the BindingContext contract specific to a given origin. + * + * @author Steve Ebersole + */ +public interface LocalBindingContext extends BindingContext { + /** + * Obtain the origin for this context + * + * @return The origin + */ + public Origin getOrigin(); + + /** + * Make a MappingException using the local origin + * + * @param message The exception message + * + * @return The MappingException + */ + public MappingException makeMappingException(String message); + + /** + * Make a MappingException using the local origin + * + * @param message The exception message + * @param cause The underlying cause + * + * @return The MappingException + */ + public MappingException makeMappingException(String message, Exception cause); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataBuildingOptions.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataBuildingOptions.java new file mode 100644 index 000000000000..c9e4763ee5f7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataBuildingOptions.java @@ -0,0 +1,171 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.List; +import javax.persistence.SharedCacheMode; + +import org.hibernate.MultiTenancyStrategy; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.metamodel.MetadataSourceProcessingOrder; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.type.BasicType; + +import org.jboss.jandex.IndexView; + +import org.xml.sax.EntityResolver; + +/** + * Describes the options used while building the Metadata object (during + * {@link org.hibernate.metamodel.MetadataBuilder#build()} processing). + * + * @author Steve Ebersole + */ +public interface MetadataBuildingOptions { + /** + * Access to the service registry. + * + * @return The service registry + */ + StandardServiceRegistry getServiceRegistry(); + + /** + * Access to the database defaults. + * + * @return The database defaults + */ + Database.Defaults getDatabaseDefaults(); + + /** + * Access the list of BasicType registrations. These are the BasicTypes explicitly + * registered via calls to:

        + *
      • {@link org.hibernate.metamodel.MetadataBuilder#with(org.hibernate.type.BasicType)}
      • + *
      • {@link org.hibernate.metamodel.MetadataBuilder#with(org.hibernate.usertype.UserType, java.lang.String[])}
      • + *
      • {@link org.hibernate.metamodel.MetadataBuilder#with(org.hibernate.usertype.CompositeUserType, java.lang.String[])}
      • + *
      + * + * @return The BasicType registrations + */ + List getBasicTypeRegistrations(); + + /** + * Access to the Jandex index passed by call to + * {@link org.hibernate.metamodel.MetadataBuilder#with(org.jboss.jandex.IndexView)}, if any. + * + * @return The Jandex index + */ + IndexView getJandexView(); + + /** + * Access the temporary ClassLoader passed to us as defined by + * {@link javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader()}, if any. + * + * @return The tempo ClassLoader + */ + ClassLoader getTempClassLoader(); + + /** + * Access to the NamingStrategy which should be used. + * + * @return The NamingStrategy + */ + NamingStrategy getNamingStrategy(); + + /** + * Access to the SharedCacheMode for determining whether we should perform second level + * caching or not. + * + * @return The SharedCacheMode + */ + SharedCacheMode getSharedCacheMode(); + + /** + * Access to the default second level cache AccessType to use if not specified. + * + * @return The default AccessType + */ + AccessType getDefaultCacheAccessType(); + + /** + * Access to whether we should be using the new identifier generator scheme. + * {@code true} indicates to use the new schema, {@code false} indicates to use the + * legacy scheme. + * + * @return Whether to use the new identifier generator scheme + */ + boolean isUseNewIdentifierGenerators(); + + /** + * Access to the MultiTenancyStrategy for this environment. + * + * @return The MultiTenancyStrategy + */ + MultiTenancyStrategy getMultiTenancyStrategy(); + + /** + * Access to all explicit cache region mappings. + * + * @return Explicit cache region mappings. + */ + List getCacheRegionDefinitions(); + + /** + * Whether explicit discriminator declarations should be ignored for joined + * subclass style inheritance. + * + * @return {@code true} indicates they should be ignored; {@code false} + * indicates they should not be ignored. + * + * @see org.hibernate.metamodel.MetadataBuilder#withExplicitDiscriminatorsForJoinedSubclassSupport + * @see org.hibernate.cfg.AvailableSettings#IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS + */ + boolean ignoreExplicitDiscriminatorsForJoinedInheritance(); + + /** + * Whether we should do discrimination implicitly joined subclass style inheritance when no + * discriminator info is provided. + * + * @return {@code true} indicates we should do discrimination; {@code false} we should not. + * + * @see org.hibernate.metamodel.MetadataBuilder#withImplicitDiscriminatorsForJoinedSubclassSupport + * @see org.hibernate.cfg.AvailableSettings#IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS + */ + boolean createImplicitDiscriminatorsForJoinedInheritance(); + + /** + * Obtain the selected strategy for resolving members identifying persistent attributes + * + * @return The select resolver strategy + */ + PersistentAttributeMemberResolver getPersistentAttributeMemberResolver(); + + // todo : these 2 will go away... + + MetadataSourceProcessingOrder getMetadataSourceProcessingOrder(); + + EntityResolver getEntityResolver(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java new file mode 100644 index 000000000000..35d0f2c66ed4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataContributor.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.jboss.jandex.IndexView; + +/** + * Contract for contributing MetadataSources. This hook occurs just after all processing of + * {@link org.hibernate.metamodel.MetadataSources} has completed (and just before {@link AdditionalJaxbRootProducer}). + * + * @author Steve Ebersole + */ +public interface MetadataContributor { + /** + * Perform the contributions. + * + * @param metadataCollector The metadata collector, representing the in-flight metadata being built + * @param jandexIndex The Jandex index + */ + public void contribute(InFlightMetadataCollector metadataCollector, IndexView jandexIndex); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java new file mode 100644 index 000000000000..7541a248a09f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataImplementor.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import org.hibernate.engine.spi.Mapping; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.type.TypeResolver; + +/** + * @author Steve Ebersole + */ +public interface MetadataImplementor extends Metadata, Mapping { + Database getDatabase(); + + ServiceRegistry getServiceRegistry(); + + TypeResolver getTypeResolver(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourceProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourceProcessor.java new file mode 100644 index 000000000000..64349c3619f6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourceProcessor.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.Collection; + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.FilterDefinitionSource; +import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource; +import org.hibernate.metamodel.source.spi.TypeDescriptorSource; + +/** + * Handles the processing of metadata sources in a dependency-ordered manner. + * + * @author Steve Ebersole + */ +public interface MetadataSourceProcessor { + /** + * Retrieve the sources pertaining to type descriptors. + * + * @return The type descriptor sources. + */ + Iterable extractTypeDefinitionSources(); + + /** + * Retrieve the sources pertaining to filter defs. + * + * @return The filter def sources. + */ + Iterable extractFilterDefinitionSources(); + + /** + * Retrieve the sources of "global" identifier generator specifications. + * + * @return The identifier generator sources. + */ + Iterable extractGlobalIdentifierGeneratorSources(); + + /** + * Retrieve the entity hierarchies. + * + * @return The entity hierarchies + */ + Collection extractEntityHierarchies(); + + /** + * Process the parts of the metadata that depend on mapping (entities, et al) information having been + * processed and available. + */ + void processMappingDependentMetadata(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java new file mode 100644 index 000000000000..e022dda12c62 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MetadataSourcesContributor.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + + +import org.hibernate.metamodel.MetadataSources; + +import org.jboss.jandex.IndexView; + +/** + * Contract for contributing sources to MetadataSources. + * + * @author Steve Ebersole + */ +public interface MetadataSourcesContributor { + /** + * Perform the process of contributing to MetadataSources. + * + * @param metadataSources + * @param jandexIndex The Jandex index + */ + public void contribute(MetadataSources metadataSources, IndexView jandexIndex); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/NaturalIdMutability.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/NaturalIdMutability.java new file mode 100644 index 000000000000..d6a86d5ca649 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/NaturalIdMutability.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +/** + * A ternary boolean enum for describing the mutability aspects of an + * attribute as a natural id. + * + * @author Steve Ebersole + */ +public enum NaturalIdMutability { + /** + * The attribute is part of a mutable natural id + */ + MUTABLE, + /** + * The attribute is part of a immutable natural id + */ + IMMUTABLE, + /** + * The attribute is not part of any kind of natural id. + */ + NOT_NATURAL_ID +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PersistentAttributeMemberResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PersistentAttributeMemberResolver.java new file mode 100644 index 000000000000..3be3e9a0e6ec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PersistentAttributeMemberResolver.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.List; +import javax.persistence.AccessType; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; + +/** + * Contract responsible for resolving the members that identify the persistent + * attributes for a given class descriptor representing a managed type. + * + * These members (field or method) would be where we look for mapping annotations + * for the attribute. + * + * Additionally, whether the member is a field or method would tell us the default + * runtime access strategy + * + * @author Steve Ebersole + */ +public interface PersistentAttributeMemberResolver { + /** + * Given the ManagedType Java type descriptor and the implicit AccessType + * to use, resolve the members that indicate persistent attributes. + * + * @param managedTypeDescriptor The ManagedType Java type descriptor + * @param classLevelAccessType The AccessType determined for the class default + * @param localBindingContext The local binding context + * + * @return The list of "backing members" + */ + public List resolveAttributesMembers( + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeElementNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeElementNature.java new file mode 100644 index 000000000000..786a67f04ed6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeElementNature.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +/** + * Describes the nature of plural attribute elements in terms of relational implications. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public enum PluralAttributeElementNature { + /** + * The collection elements are basic, simple values. + */ + BASIC( false, false ), + /** + * The collection elements are compositions. + */ + AGGREGATE( false, true ), + /** + * The collection elements represent entity's in a one-to-many association. + */ + ONE_TO_MANY, + /** + * The collection elements represent entity's in a many-to-many association. + */ + MANY_TO_MANY, + /** + * The collection elements represent entity's in a multi-valued ANY mapping. + */ + MANY_TO_ANY; + + private final boolean isAssociation; + private final boolean isCascadeable; + + PluralAttributeElementNature() { + this( true, true ); + } + + PluralAttributeElementNature(boolean association, boolean cascadeable) { + this.isAssociation = association; + this.isCascadeable = cascadeable; + } + + public boolean isAssociation() { + return isAssociation; + } + + public boolean isCascadeable() { + return isCascadeable; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeIndexNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeIndexNature.java new file mode 100644 index 000000000000..3206beabe123 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeIndexNature.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +/** + * Describes the nature of plural attribute indexes in terms of relational implications. + * + * @author Steve Ebersole + */ +public enum PluralAttributeIndexNature { + /** + * A sequential array/list index + */ + SEQUENTIAL, + /** + * The collection indexes are basic, simple values. + */ + BASIC, + /** + * The map key is an aggregated composite + */ + AGGREGATE, + /** + * The map key is an association identified by a column(s) on the collection table. + */ + MANY_TO_MANY, + /** + * The map key is represented by a Hibernate ANY mapping + */ + MANY_TO_ANY +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeNature.java new file mode 100644 index 000000000000..af659e8ce11b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/PluralAttributeNature.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Describes the nature of the collection itself as declared by the metadata. + * + * @author Steve Ebersole + */ +public enum PluralAttributeNature { + BAG( Collection.class, false ), + ID_BAG( Collection.class, false ), + SET( Set.class, false ), + LIST( List.class, true ), + ARRAY( Object[].class, true ), + MAP( Map.class, true ); + + private final boolean indexed; + private final Class reportedJavaType; + + PluralAttributeNature(Class reportedJavaType, boolean indexed) { + this.reportedJavaType = reportedJavaType; + this.indexed = indexed; + } + + public Class reportedJavaType() { + return reportedJavaType; + } + + public boolean isIndexed() { + return indexed; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/SingularAttributeNature.java similarity index 82% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/SingularAttributeNature.java index b62083860584..909fd58e65d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/SingularAttributeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/SingularAttributeNature.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.binder; +package org.hibernate.metamodel.spi; /** * Describes the understood natures of a singular attribute. @@ -30,7 +30,10 @@ */ public enum SingularAttributeNature { BASIC, - COMPONENT, + // TODO: COMPOSITE should be changed to AGGREGATE + // when non-aggregated composite IDs are no longer + // modelled as an AttributeBinding + COMPOSITE, MANY_TO_ONE, ONE_TO_ONE, ANY diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/StandardPersistentAttributeMemberResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/StandardPersistentAttributeMemberResolver.java new file mode 100644 index 000000000000..a22e7575aecb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/StandardPersistentAttributeMemberResolver.java @@ -0,0 +1,286 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import javax.persistence.AccessType; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.metamodel.reflite.spi.FieldDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.MemberDescriptor; +import org.hibernate.metamodel.reflite.spi.MethodDescriptor; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; + +/** + * Implementation of the PersistentAttributeMemberResolver contract that sticks + * pretty close to the specifics set forth in the JPA specification. Specifically + * AccessType does influence where we look for annotations. + * + * @author Steve Ebersole + */ +public class StandardPersistentAttributeMemberResolver extends AbstractPersistentAttributeMemberResolver { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( StandardPersistentAttributeMemberResolver.class ); + + /** + * Singleton access + */ + public static final StandardPersistentAttributeMemberResolver INSTANCE = new StandardPersistentAttributeMemberResolver(); + + @Override + protected List resolveAttributesMembers( + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext) { + final LinkedHashMap results = new LinkedHashMap(); + + collectMembersWithExplicitAccessAnnotation( + results, + transientFieldNames, + transientMethodNames, + managedTypeDescriptor, + classLevelAccessType, + localBindingContext + ); + + collectMembersUsingClassDefinedAccess( + results, + transientFieldNames, + transientMethodNames, + managedTypeDescriptor, + classLevelAccessType, + localBindingContext + ); + + return new ArrayList( results.values() ); + } + + private void collectMembersWithExplicitAccessAnnotation( + LinkedHashMap attributeMemberMap, + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext) { + final List accessAnnotations = managedTypeDescriptor.getJandexClassInfo() + .annotations() + .get( JPADotNames.ACCESS ); + if ( accessAnnotations == null ) { + return; + } + + // iterate over all @Access annotations defined on the current class + for ( AnnotationInstance accessAnnotation : accessAnnotations ) { + // we are only interested at annotations defined on fields and methods + AnnotationTarget annotationTarget = accessAnnotation.target(); + if ( !annotationTarget.getClass().equals( MethodInfo.class ) + && !annotationTarget.getClass().equals( FieldInfo.class ) ) { + continue; + } + + final AccessType attributeAccessType = localBindingContext.getJandexAccess() + .getTypedValueExtractor( AccessType.class ) + .extract( accessAnnotation, "value" ); + checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly( + annotationTarget, + attributeAccessType, + classLevelAccessType, + managedTypeDescriptor, + localBindingContext + ); + + if ( annotationTarget instanceof MethodInfo ) { + final MethodInfo methodInfo = ( (MethodInfo) annotationTarget ); + if ( transientMethodNames.contains( methodInfo.name() ) ) { + continue; + } + + final String attributeName = ReflectHelper.getPropertyNameFromGetterMethod( methodInfo.name() ); + if ( attributeName == null ) { + throw localBindingContext.makeMappingException( + "@Access annotation encountered on method [" + methodInfo.name() + + "] that did not following JavaBeans naming convention for getter" + ); + } + + if ( attributeMemberMap.containsKey( attributeName ) ) { + continue; + } + + attributeMemberMap.put( + attributeName, + findMethodDescriptor( managedTypeDescriptor, methodInfo.name() ) + ); + } + else { + final FieldInfo fieldInfo = (FieldInfo) annotationTarget; + final String attributeName = fieldInfo.name(); + if ( transientFieldNames.contains( attributeName ) ) { + continue; + } + + if ( attributeMemberMap.containsKey( attributeName ) ) { + continue; + } + + attributeMemberMap.put( + attributeName, + findFieldDescriptor( managedTypeDescriptor, attributeName ) + ); + } + } + + } + + private void checkExplicitJpaAttributeAccessAnnotationPlacedCorrectly( + AnnotationTarget annotationTarget, + AccessType attributeAccessType, + AccessType classLevelAccessType, + JavaTypeDescriptor managedTypeDescriptor, + LocalBindingContext localBindingContext) { + + if ( AccessType.FIELD.equals( classLevelAccessType ) ) { + // The class-level AccessType is FIELD.... + + if ( FieldInfo.class.isInstance( annotationTarget ) ) { + // we have an @Access annotation defined on a field.. + // + // Technically this is ok as long as the attribute-level AccessType defines + // FIELD. This falls under the 2.3.2 section footnote stating: + // "It is permitted (but redundant) to place Access(FIELD) on a + // persistent field whose class has field access type..." + if ( AccessType.PROPERTY.equals( attributeAccessType ) ) { + throw localBindingContext.makeMappingException( + String.format( + Locale.ENGLISH, + "Illegal attempt to specify Access(PROPERTY) on field [%s] in class [%s]", + ( (FieldInfo) annotationTarget ).name(), + ( (FieldInfo) annotationTarget ).declaringClass().name() + ) + ); + } + } + else { + // we have an @Access annotation defined on a method... + // (getter checks are done in the caller) + if ( AccessType.FIELD.equals( attributeAccessType ) ) { + throw localBindingContext.makeMappingException( + LOG.accessTypeOverrideShouldBeProperty( managedTypeDescriptor.getName().toString() ) + ); + } + } + } + else if ( AccessType.PROPERTY.equals( classLevelAccessType ) ) { + // The class-level AccessType is PROPERTY.... + + if ( MethodInfo.class.isInstance( annotationTarget ) ) { + // we have an @Access annotation defined on a method.. + // (again, getter checks are done in the caller) + // + // Technically this is ok as long as the attribute-level AccessType defines + // PROPERTY. This falls under the 2.3.2 section footnote stating: + // "It is permitted (but redundant) to place ... Access(PROPERTY) + // on a persistent property whose class has property access type" + if ( AccessType.FIELD.equals( attributeAccessType ) ) { + throw localBindingContext.makeMappingException( + String.format( + Locale.ENGLISH, + "Illegal attempt to specify Access(FIELD) on method [%s] in class [%s]", + ( (MethodInfo) annotationTarget ).name(), + ( (MethodInfo) annotationTarget ).declaringClass().name() + ) + ); + } + } + else { + // we have an @Access annotation defined on a field... + if ( AccessType.PROPERTY.equals( attributeAccessType ) ) { + throw localBindingContext.makeMappingException( + LOG.accessTypeOverrideShouldBeField( managedTypeDescriptor.getName().toString() ) + ); + } + } + } + } + + private void collectMembersUsingClassDefinedAccess( + LinkedHashMap attributeMemberMap, + Set transientFieldNames, + Set transientMethodNames, + JavaTypeDescriptor managedTypeDescriptor, + AccessType classLevelAccessType, + LocalBindingContext localBindingContext) { + if ( AccessType.FIELD.equals( classLevelAccessType ) ) { + for ( FieldDescriptor field : managedTypeDescriptor.getDeclaredFields() ) { + if ( !isPersistable( field ) ) { + continue; + } + + final String attributeName = field.getName(); + + if ( transientFieldNames.contains( attributeName ) ) { + continue; + } + + if ( attributeMemberMap.containsKey( attributeName ) ) { + continue; + } + + attributeMemberMap.put( attributeName, field ); + } + } + else { + for ( MethodDescriptor method : managedTypeDescriptor.getDeclaredMethods() ) { + if ( !isPersistable( method ) ) { + continue; + } + + if ( transientMethodNames.contains( method.getName() ) ) { + continue; + } + + final String attributeName = ReflectHelper.getPropertyNameFromGetterMethod( method.getName() ); + + if ( attributeMemberMap.containsKey( attributeName ) ) { + continue; + } + + attributeMemberMap.put( attributeName, method ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java index 4a04173faa3c..004caef5e6fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/TypeContributor.java @@ -29,9 +29,6 @@ * Contract for contributing types. * * @author Steve Ebersole - * - * NOTE: Cherry-pick of HHH-7998 from metamodel. For merging simplicity, just - * keep it in the o.h.metamodel.spi package. */ public interface TypeContributor { /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java new file mode 100644 index 000000000000..553c207f04ed --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java @@ -0,0 +1,155 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.domain.Attribute; + +/** + * Basic support for {@link AttributeBinding} implementors + * + * @author Steve Ebersole + */ +public abstract class AbstractAttributeBinding implements AttributeBinding { + private final AttributeBindingContainer container; + private final Attribute attribute; + + private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + private final Set entityReferencingAttributeBindings = new HashSet(); + + private final String propertyAccessorName; + private final boolean includedInOptimisticLocking; + + private boolean isAlternateUniqueKey; + + private final AttributeRole attributeRole; + private final AttributePath attributePath; + + private final MetaAttributeContext metaAttributeContext; + + protected AbstractAttributeBinding( + AttributeBindingContainer container, + Attribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + this.container = container; + this.attribute = attribute; + this.propertyAccessorName = propertyAccessorName; + this.includedInOptimisticLocking = includedInOptimisticLocking; + this.metaAttributeContext = metaAttributeContext; + + this.attributeRole = attributeRole; + this.attributePath = attributePath; + } + + @Override + public AttributeBindingContainer getContainer() { + return container; + } + + @Override + public Attribute getAttribute() { + return attribute; + } + + @Override + public AttributePath getAttributePath() { + return attributePath; + } + + @Override + public AttributeRole getAttributeRole() { + return attributeRole; + } + + @Override + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } + + @Override + public boolean isBackRef() { + return false; + } + + @Override + public boolean isBasicPropertyAccessor() { + return propertyAccessorName == null || "property".equals( propertyAccessorName ); + } + + @Override + public String getPropertyAccessorName() { + return propertyAccessorName; + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return includedInOptimisticLocking; + } + + @Override + public MetaAttributeContext getMetaAttributeContext() { + return metaAttributeContext; + } + + @Override + public boolean isAlternateUniqueKey() { + // todo : is this the same as "part of natural id"? + return isAlternateUniqueKey; + } + + public void setAlternateUniqueKey(boolean alternateUniqueKey) { + this.isAlternateUniqueKey = alternateUniqueKey; + } + + public void addEntityReferencingAttributeBinding(SingularAssociationAttributeBinding referencingAttributeBinding) { + entityReferencingAttributeBindings.add( referencingAttributeBinding ); + } + + public Set getEntityReferencingAttributeBindings() { + return Collections.unmodifiableSet( entityReferencingAttributeBindings ); + } + + public void validate() { + if ( !entityReferencingAttributeBindings.isEmpty() ) { + // TODO; validate that this AttributeBinding can be a target of an entity reference + // (e.g., this attribute is the primary key or there is a unique-key) + // can a unique attribute be used as a target? if so, does it need to be non-null? + } + } + + @Override + public String toString() { + return "AbstractAttributeBinding{attribute=" + attribute.getName() + ", path=" + attributePath + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java new file mode 100644 index 000000000000..3848e15458f1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java @@ -0,0 +1,364 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; +import java.util.Map; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * @author Gail Badner + */ +public abstract class AbstractAttributeBindingContainer implements AttributeBindingContainer { + + protected abstract Map attributeBindingMapInternal(); + + @Override + public AttributeBinding locateAttributeBinding(String name) { + return attributeBindingMapInternal().get( name ); + } + + @Override + public SingularAttributeBinding locateAttributeBinding(TableSpecification table, List values) { + for ( AttributeBinding attributeBinding : attributeBindingMapInternal().values() ) { + if ( !attributeBinding.getAttribute().isSingular() ) { + continue; + } + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + if ( hasEqualValues( table, values, singularAttributeBinding.getRelationalValueBindings() ) ) { + return singularAttributeBinding; + } + } + return null; + } + + private static boolean hasEqualValues( + TableSpecification table, + List values, + List relationalValueBindings) { + if ( values.size() != relationalValueBindings.size() ) { + return false; + } + for ( int i = 0 ; i < values.size() ; i++ ) { + final RelationalValueBinding relationalValueBinding = relationalValueBindings.get( i ); + if ( !table.equals( relationalValueBinding.getTable() ) || + !values.get( i ).equals( relationalValueBinding.getValue() ) ) { + return false; + } + } + return true; + } + + @Override + public int attributeBindingSpan() { + return attributeBindingMapInternal().size(); + } + + @Override + public Iterable attributeBindings() { + return attributeBindingMapInternal().values(); + } + + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + for ( AttributeBinding subAttributeBinding : attributeBindings() ) { + if ( AbstractSingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { + ( (AbstractSingularAttributeBinding) subAttributeBinding ).collectRelationalValueBindings( relationalValueBindingContainer ); + } + } + } + + @Override + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + PropertyGeneration generation) { + final BasicAttributeBinding binding = new BasicAttributeBinding( + this, + attribute, + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + generation + ); + registerAttributeBinding( binding ); + return binding; + } + + protected void registerAttributeBinding(AttributeBinding attributeBinding) { + // todo : hook this into the EntityBinding notion of "entity referencing attribute bindings" + attributeBindingMapInternal().put( attributeBinding.getAttribute().getName(), attributeBinding ); + } + + @Override + public EmbeddedAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + Class tuplizerClass, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + final EmbeddedAttributeBinding binding = EmbeddedAttributeBinding.createEmbeddedAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + parentReferenceAttribute, + tuplizerClass + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + final OneToOneAttributeBinding binding = new OneToOneAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + referencedEntityBinding, + referencedAttributeBinding, + isConstrained + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isIgnoreNotFound, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isIgnoreNotFound, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + referencedEntityBinding, + referencedAttributeBinding + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); + final BagBinding binding = new BagBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base) { + Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.LIST ); + final ListBinding binding = new ListBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath, + base + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base) { + Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.ARRAY ); + final ArrayBinding binding = new ArrayBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath, + base + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature elementNature, + PluralAttributeIndexNature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.MAP ); + final MapBinding binding = new MapBinding( + this, + attribute, + elementNature, + indexNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + registerAttributeBinding( binding ); + return binding; + } + + @Override + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); + final SetBinding binding = new SetBinding( + this, + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + registerAttributeBinding( binding ); + return binding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractEmbeddableBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractEmbeddableBinding.java new file mode 100644 index 000000000000..18f752b13efe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractEmbeddableBinding.java @@ -0,0 +1,374 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * A container for attribute bindings that make up composite grouping + * + * @author Gail Badner + * @author Steve Ebersole + */ +public abstract class AbstractEmbeddableBinding + extends AbstractAttributeBindingContainer + implements EmbeddableBinding { + private final EntityBinding entityBinding; + private final AttributeContainer attributeContainer; + private final TableSpecification primaryTable; + private final AttributeRole roleBase; + private final AttributePath pathBase; + private final MetaAttributeContext metaAttributeContext; + private final SingularAttribute parentReference; + private final Class tuplizerClass; + + protected AbstractEmbeddableBinding( + EntityBinding entityBinding, + AttributeContainer attributeContainer, + TableSpecification primaryTable, + AttributeRole roleBase, + AttributePath pathBase, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference, + Class tuplizerClass) { + this.entityBinding = entityBinding; + this.attributeContainer = attributeContainer; + this.primaryTable = primaryTable; + this.roleBase = roleBase; + this.pathBase = pathBase; + this.metaAttributeContext = metaAttributeContext; + this.parentReference = parentReference; + this.tuplizerClass = tuplizerClass; + } + + public SingularAttribute getParentReference() { + return parentReference; + } + + @Override + public AttributePath getPathBase() { + return pathBase; + } + + @Override + public AttributeRole getRoleBase() { + return roleBase; + } + + @Override + public AttributeContainer getAttributeContainer() { + return attributeContainer; + } + + @Override + public EntityBinding seekEntityBinding() { + return entityBinding; + } + + @Override + public MetaAttributeContext getMetaAttributeContext() { + return metaAttributeContext; + } + + @Override + public TableSpecification getPrimaryTable() { + return primaryTable; + } + + @Override + public Class getCustomTuplizerClass() { + return tuplizerClass; + } + + protected abstract boolean isModifiable(); + + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + final RelationalValueBindingContainer bindingContainer = new RelationalValueBindingContainer(); + collectRelationalValueBindings( bindingContainer ); + return bindingContainer; + } + + @Override + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + PropertyGeneration generation) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeBasicAttributeBinding( + attribute, + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + generation + ); + } + + @Override + public EmbeddedAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + Class tuplizerClass, String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeAggregatedCompositeAttributeBinding( + attribute, + parentReferenceAttribute, + tuplizerClass, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath + ); + } + + @Override + public OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeOneToOneAttributeBinding( + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + referencedEntityBinding, + referencedAttributeBinding, + isConstrained + ); + } + + @Override + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isIgnoreNotFound, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeManyToOneAttributeBinding( + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isIgnoreNotFound, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + referencedEntityBinding, + referencedAttributeBinding + ); + } + + @Override + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeBagAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + } + + @Override + public ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeListAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath, + base + ); + } + + @Override + public ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeArrayAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath, + base + ); + } + + @Override + public MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature elementNature, + PluralAttributeIndexNature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeMapAttributeBinding( + attribute, + elementNature, + indexNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + } + + @Override + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + if ( !isModifiable() ) { + throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); + } + return super.makeSetAttributeBinding( + attribute, + nature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java new file mode 100644 index 000000000000..a0f7a312e31b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeAssociationElementBinding.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.engine.spi.CascadeStyle; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeAssociationElementBinding + extends AbstractPluralAttributeElementBinding + implements PluralAttributeAssociationElementBinding { + + private CascadeStyle cascadeStyle; + + AbstractPluralAttributeAssociationElementBinding(AbstractPluralAttributeBinding pluralAttributeBinding) { + super( pluralAttributeBinding ); + } + + @Override + public CascadeStyle getCascadeStyle() { + return cascadeStyle; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + this.cascadeStyle = cascadeStyle; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java new file mode 100644 index 000000000000..7de28b0bc8b2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java @@ -0,0 +1,318 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.FetchMode; +import org.hibernate.TruthValue; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.persister.collection.CollectionPersister; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBinding implements PluralAttributeBinding { + private final PluralAttributeKeyBinding pluralAttributeKeyBinding; + private final AbstractPluralAttributeElementBinding pluralAttributeElementBinding; + + private FetchTiming fetchTiming; + private FetchStyle fetchStyle; + + private int batchSize = -1; + + private Caching caching = new Caching( TruthValue.UNKNOWN ); + + private boolean mutable = true; + + private Class explicitPersisterClass; + + private String where; + private String orderBy; + private boolean sorted; + private Comparator< ? > comparator; + + private String customLoaderName; + private CustomSQL customSqlInsert; + private CustomSQL customSqlUpdate; + private CustomSQL customSqlDelete; + private CustomSQL customSqlDeleteAll; + + private String referencedPropertyName; + + private List filterConfigurations = new ArrayList(); + + // private final java.util.Set synchronizedTables = new HashSet(); + + protected AbstractPluralAttributeBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + this.pluralAttributeKeyBinding = new PluralAttributeKeyBinding( this, referencedAttributeBinding ); + this.pluralAttributeElementBinding = interpretNature( pluralAttributeElementNature ); + this.referencedPropertyName = referencedAttributeBinding.getAttribute().getName(); + } + + private AbstractPluralAttributeElementBinding interpretNature(PluralAttributeElementNature nature) { + switch ( nature ) { + case BASIC: { + return new PluralAttributeElementBindingBasic( this ); + } + case AGGREGATE: { + return new PluralAttributeElementBindingEmbedded( this ); + } + case ONE_TO_MANY: { + return new PluralAttributeElementBindingOneToMany( this ); + } + case MANY_TO_MANY: { + return new PluralAttributeElementBindingManyToMany( this ); + } + case MANY_TO_ANY: { + return new PluralAttributeElementBindingManyToAny( this ); + } + default: { + throw new AssertionFailure( "Unknown collection element nature : " + nature ); + } + } + } + + @Override + public PluralAttribute getAttribute() { + return (PluralAttribute) super.getAttribute(); + } + + @Override + public boolean isAssociation() { + return pluralAttributeElementBinding.getNature().isAssociation(); + } + + @Override + public boolean isCascadeable() { + return pluralAttributeElementBinding.getNature().isCascadeable(); + } + + @Override + public PluralAttributeKeyBinding getPluralAttributeKeyBinding() { + return pluralAttributeKeyBinding; + } + + @Override + public AbstractPluralAttributeElementBinding getPluralAttributeElementBinding() { + return pluralAttributeElementBinding; + } + + @Override + public FetchTiming getFetchTiming() { + return fetchTiming; + } + + @Override + public void setFetchTiming(FetchTiming fetchTiming) { + this.fetchTiming = fetchTiming; + } + + @Override + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + @Override + public void setFetchStyle(FetchStyle fetchStyle) { + this.fetchStyle = fetchStyle; + } + + @Override + public String getCustomLoaderName() { + return customLoaderName; + } + + public void setCustomLoaderName(String customLoaderName) { + this.customLoaderName = customLoaderName; + } + + @Override + public CustomSQL getCustomSqlInsert() { + return customSqlInsert; + } + + public void setCustomSqlInsert(CustomSQL customSqlInsert) { + this.customSqlInsert = customSqlInsert; + } + + @Override + public CustomSQL getCustomSqlUpdate() { + return customSqlUpdate; + } + + public void setCustomSqlUpdate(CustomSQL customSqlUpdate) { + this.customSqlUpdate = customSqlUpdate; + } + + @Override + public CustomSQL getCustomSqlDelete() { + return customSqlDelete; + } + + public void setCustomSqlDelete(CustomSQL customSqlDelete) { + this.customSqlDelete = customSqlDelete; + } + + @Override + public CustomSQL getCustomSqlDeleteAll() { + return customSqlDeleteAll; + } + + public void setCustomSqlDeleteAll(CustomSQL customSqlDeleteAll) { + this.customSqlDeleteAll = customSqlDeleteAll; + } + + @Override + public Class getExplicitPersisterClass() { + return explicitPersisterClass; + } + + public void setExplicitPersisterClass(Class explicitPersisterClass) { + this.explicitPersisterClass = explicitPersisterClass; + } + + public Caching getCaching() { + return caching; + } + + public void setCaching(Caching caching) { + assert caching != null; + this.caching = caching; + } + + @Override + public String getOrderBy() { + return orderBy; + } + + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + @Override + public String getWhere() { + return where; + } + + public void setWhere(String where) { + this.where = where; + } + + @Override + public boolean isMutable() { + return mutable; + } + + public void setMutable(boolean mutable) { + this.mutable = mutable; + } + @Override + public boolean hasIndex() { + return IndexedPluralAttributeBinding.class.isInstance( this ); + } + + @Override + public int getBatchSize() { + return batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + @Override + public String getReferencedPropertyName() { + return referencedPropertyName; + } + + @Override + public boolean isSorted() { + return sorted; + } + + public void setSorted(boolean sorted) { + this.sorted = sorted; + } + + @Override + public Comparator< ? > getComparator() { + return comparator; + } + + public void setComparator( Comparator< ? > comparator ) { + this.comparator = comparator; + } + + @Override + public void addFilterConfiguration(FilterConfiguration filterConfiguration) { + filterConfigurations.add( filterConfiguration ); + } + + @Override + public List getFilterConfigurations() { + return filterConfigurations; + } + + @Override + public FetchMode getFetchMode() { + return getFetchStyle() == FetchStyle.JOIN ? FetchMode.JOIN : FetchMode.SELECT; + } + + @Override + public boolean isLazy() { + return fetchTiming != FetchTiming.IMMEDIATE; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java new file mode 100644 index 000000000000..3f2ddf5fcd66 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeElementBinding.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * Basic contract describing the commonality between the various types of collection element mappings. + * + * @author Steve Ebersole + */ +public abstract class AbstractPluralAttributeElementBinding implements PluralAttributeElementBinding { + private final AbstractPluralAttributeBinding pluralAttributeBinding; + private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + + AbstractPluralAttributeElementBinding(AbstractPluralAttributeBinding pluralAttributeBinding) { + this.pluralAttributeBinding = pluralAttributeBinding; + } + + @Override + public AbstractPluralAttributeBinding getPluralAttributeBinding() { + return pluralAttributeBinding; + } + + @Override + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java new file mode 100644 index 000000000000..99dc9e35870f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeIndexBinding.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.domain.IndexedPluralAttribute; +import org.hibernate.metamodel.spi.domain.Type; + +/** + * @author Gail Badner + */ +public abstract class AbstractPluralAttributeIndexBinding implements PluralAttributeIndexBinding { + + private final IndexedPluralAttributeBinding pluralAttributeBinding; + private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + + public AbstractPluralAttributeIndexBinding( + IndexedPluralAttributeBinding pluralAttributeBinding) { + this.pluralAttributeBinding = pluralAttributeBinding; + } + + @Override + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } + + @Override + public IndexedPluralAttributeBinding getIndexedPluralAttributeBinding() { + return pluralAttributeBinding; + } + + @Override + public Type getPluralAttributeIndexType() { + return ( (IndexedPluralAttribute) getIndexedPluralAttributeBinding().getAttribute() ).getIndexType(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java new file mode 100644 index 000000000000..b3d2341257c1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAssociationAttributeBinding.java @@ -0,0 +1,195 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.FetchMode; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Gail Badner + */ +public abstract class AbstractSingularAssociationAttributeBinding extends AbstractSingularAttributeBinding + implements SingularAssociationAttributeBinding { + private final EntityBinding referencedEntityBinding; + private final SingularAttributeBinding referencedAttributeBinding; + private JoinRelationalValueBindingContainer relationalValueBindingContainer; + private CascadeStyle cascadeStyle; + private FetchTiming fetchTiming; + private FetchStyle fetchStyle; + private boolean isUnWrapProxy; + private final boolean isIgnoreNotFound; + + public AbstractSingularAssociationAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + boolean isIgnoreNotFound, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + isLazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath + ); + if ( referencedEntityBinding == null ) { + throw new IllegalArgumentException( "referencedEntityBinding must be non-null." ); + } + if ( referencedAttributeBinding == null ) { + throw new IllegalArgumentException( "referencedAttributeBinding must be non-null." ); + } + this.referencedEntityBinding = referencedEntityBinding; + this.referencedAttributeBinding = referencedAttributeBinding; + this.isIgnoreNotFound = isIgnoreNotFound; + } + + @Override + public boolean isIgnoreNotFound() { + return isIgnoreNotFound; + } + + @Override + public boolean isAssociation() { + return true; + } + + @Override + public final String getReferencedEntityName() { + return referencedEntityBinding.getEntityName(); + } + + @Override + public CascadeStyle getCascadeStyle() { + return cascadeStyle; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + this.cascadeStyle = cascadeStyle; + } + + @Override + public FetchTiming getFetchTiming() { + return fetchTiming; + } + + @Override + public void setFetchTiming(FetchTiming fetchTiming) { + this.fetchTiming = fetchTiming; + } + + @Override + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + @Override + public void setFetchStyle(FetchStyle fetchStyle) { + if ( fetchStyle == FetchStyle.SUBSELECT ) { + throw new AssertionFailure( "Subselect fetching not yet supported for singular associations" ); + } + this.fetchStyle = fetchStyle; + } + + @Override + public FetchMode getFetchMode() { + switch ( fetchStyle ){ + case JOIN: + return FetchMode.JOIN; + case SELECT: + return FetchMode.SELECT; + case BATCH: + // we need the subsequent select... + return FetchMode.SELECT; + default: + throw new AssertionFailure( "Unexpected fetch style : " + fetchStyle.name() ); + } + } + + @Override + public final EntityBinding getReferencedEntityBinding() { + return referencedEntityBinding; + } + + @Override + public SingularAttributeBinding getReferencedAttributeBinding() { + return referencedAttributeBinding; + } + + public void setJoinRelationalValueBindings( + List relationalValueBindings, + ForeignKey foreignKey) { + this.relationalValueBindingContainer = + new JoinRelationalValueBindingContainer( relationalValueBindings, foreignKey ); + } + + @Override + public TableSpecification getTable() { + return relationalValueBindingContainer.getTable(); + } + + @Override + public ForeignKey getForeignKey() { + return relationalValueBindingContainer.getForeignKey(); + } + + @Override + public List getValues() { + return getRelationalValueBindingContainer().values(); + } + + @Override + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + return relationalValueBindingContainer; + } + + @Override + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + relationalValueBindingContainer.addRelationalValueBindings( this.relationalValueBindingContainer ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java new file mode 100644 index 000000000000..f6775a355526 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractSingularAttributeBinding + extends AbstractAttributeBinding + implements SingularAttributeBinding { + + private final boolean isLazy; + private final NaturalIdMutability naturalIdMutability; + + protected AbstractSingularAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext , + attributeRole, + attributePath + ); + this.isLazy = isLazy; + this.naturalIdMutability = naturalIdMutability; + } + + protected abstract RelationalValueBindingContainer getRelationalValueBindingContainer(); + + @Override + public List getRelationalValueBindings() { + return getRelationalValueBindingContainer().relationalValueBindings(); + } + + @Override + public List getValues() { + return getRelationalValueBindingContainer().values(); + } + + @Override + public boolean hasDerivedValue() { + return getRelationalValueBindingContainer().hasDerivedValue(); + } + + @Override + public boolean isNullable() { + return !getRelationalValueBindingContainer().hasNonNullableRelationalValueBinding(); + } + + @Override + public boolean isOptional() { + final EntityBinding entityBinding = getContainer().seekEntityBinding(); + final TableSpecification entityPrimaryTable = entityBinding.getPrimaryTable(); + for (RelationalValueBinding relationalValueBinding : getRelationalValueBindings() ) { + final TableSpecification table = relationalValueBinding.getTable(); + if ( table.equals( entityPrimaryTable ) ) { + // primary table is not optional. + return false; + } + final SecondaryTable secondaryTable = entityBinding.getSecondaryTables().get( table.getLogicalName() ); + // a secondaryTable can be null if it is a non-joined, collection/association table + if ( secondaryTable == null || ! secondaryTable.isOptional() ) { + return false; + } + } + return true; + } + + @Override + public boolean isIncludedInInsert() { + return getRelationalValueBindingContainer().hasInsertableRelationalValueBinding(); + } + + @Override + public boolean isIncludedInUpdate() { + return getRelationalValueBindingContainer().hasUpdateableRelationalValueBinding(); + } + + @Override + public SingularAttribute getAttribute() { + return (SingularAttribute) super.getAttribute(); + } + + @Override + public boolean isCascadeable() { + return isAssociation(); + } + + @Override + public boolean isLazy() { + return isLazy; + } + + @Override + public NaturalIdMutability getNaturalIdMutability() { + return naturalIdMutability; + } + + public void setAlternateUniqueKey(boolean isAlternateUniqueKey) { + super.setAlternateUniqueKey( isAlternateUniqueKey ); + } + + protected abstract void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java new file mode 100644 index 000000000000..d570c231ff00 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ArrayBinding.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; + +/** + * @author Brett Meyer + */ +public class ArrayBinding extends AbstractPluralAttributeBinding implements IndexedPluralAttributeBinding { + + private final PluralAttributeIndexBinding pluralAttributeIndexBinding; + private final int base; + + public ArrayBinding(AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( + this + ); + this.base = base; + } + + public int base() { + return base; + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding#getPluralAttributeIndexBinding() + */ + @Override + public PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + return pluralAttributeIndexBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java similarity index 76% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java index 5d317cc01e06..fe5e03659bee 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java @@ -21,12 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; -import java.util.Set; - -import org.hibernate.metamodel.domain.Attribute; -import org.hibernate.metamodel.source.MetaAttributeContext; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.domain.Attribute; /** * The basic contract for binding a {@link #getAttribute() attribute} from the domain model to the relational model. @@ -51,8 +51,8 @@ public interface AttributeBinding { /** * Obtain the descriptor for the Hibernate {@link org.hibernate.type.Type} for this binding. *

      - * For information about the Java type, query the {@link Attribute} obtained from {@link #getAttribute()} - * instead. + * For information about the Java type, query the {@link org.hibernate.metamodel.spi.domain.Attribute} + * obtained from {@link #getAttribute()} instead. * * @return The type descriptor */ @@ -60,16 +60,16 @@ public interface AttributeBinding { public boolean isAssociation(); + public boolean isCascadeable(); + + public boolean isBackRef(); + public boolean isBasicPropertyAccessor(); public String getPropertyAccessorName(); - public void setPropertyAccessorName(String propertyAccessorName); - public boolean isIncludedInOptimisticLocking(); - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking); - /** * Obtain the meta attributes associated with this binding * @@ -81,9 +81,6 @@ public interface AttributeBinding { public boolean isLazy(); - public void addEntityReferencingAttributeBinding(SingularAssociationAttributeBinding attributeBinding); - - public Set getEntityReferencingAttributeBindings(); - - public void validate(); + public AttributePath getAttributePath(); + public AttributeRole getAttributeRole(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java new file mode 100644 index 000000000000..1080aaaf8225 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java @@ -0,0 +1,348 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General License + * for more details. + * + * You should have received a copy of the GNU Lesser General License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.tuple.Tuplizer; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * Common contract for {@link EntityBinding} and {@link EmbeddedAttributeBinding} in so far as they are both + * containers for {@link AttributeBinding} descriptors + * + * @author Steve Ebersole + */ +public interface AttributeBindingContainer { + public AttributePath getPathBase(); + public AttributeRole getRoleBase(); + + /** + * Obtain the underlying domain attribute container. + * + * @return The attribute container + */ + AttributeContainer getAttributeContainer(); + + /** + * Obtain all attribute bindings + * + * @return All attribute bindings + */ + Iterable attributeBindings(); + + /** + * Return the number of attribute bindings returned by + * {@link #attributeBindings()}. + * + * @return the number of attribute bindings returned by + * {@link #attributeBindings()}. + */ + int attributeBindingSpan(); + + /** + * Return the custom tuplizer class. + * @return + */ + Class getCustomTuplizerClass(); + + /** + * Locate a specific attribute binding, by its local name. + * + * @param name The name of the attribute, local to this container. + * + * @return The attribute binding or {@code null} if none could be found. + */ + AttributeBinding locateAttributeBinding(String name); + + /** + * Locate a specific attribute binding, by its values. + * + * @param table The table containing the values + * @param values The list of values + * + * @return The attribute binding or {@code null} if none could be found. + */ + SingularAttributeBinding locateAttributeBinding(TableSpecification table, List values); + + /** + * Seeks out the entity binding that is the root of this component path. + * + * @return The entity binding + */ + EntityBinding seekEntityBinding(); + + /** + * Obtain the meta-attribute context for this container. + * + * @return The meta-attribute context. + */ + MetaAttributeContext getMetaAttributeContext(); + + + /** + * Return the table specification for the relational values of attributes + * directly contained by this attribute binding container. + * + * @return the table specification. + */ + TableSpecification getPrimaryTable(); + + /** + * Factory method for basic attribute bindings. + * + * @param attribute The attribute for which to make a binding. + * @param relationalValueBindings + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * @param generation + * + * @return The attribute binding instance. + */ + BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + PropertyGeneration generation); + + /** + * Factory method for component attribute bindings. + * + * @param attribute The attribute for which to make a binding. + * @param parentReferenceAttribute + * @param tuplizerClass + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + EmbeddedAttributeBinding makeAggregatedCompositeAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + Class tuplizerClass, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath); + + /** + * Factory method for one-to-one attribute bindings. + * + * @param attribute The attribute for which to make a binding. + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * @param referencedEntityBinding + * @param referencedAttributeBinding + * @param isConstrained + * @return The attribute binding instance. + */ + OneToOneAttributeBinding makeOneToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained); + + + /** + * Factory method for many-to-one attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param lazy + * @param metaAttributeContext + * @param referencedEntityBinding + * @param referencedAttributeBinding + * + * @return The attribute binding instance. + */ + ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isIgnoreNotFound, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding); + + /** + * Factory method for bag attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath); + + /** + * Factory method for list attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * @param base + * + * @return The attribute binding instance. + */ + ListBinding makeListAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base); + + /** + * Factory method for array attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * @param base + * + * @return The attribute binding instance. + */ + ArrayBinding makeArrayAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base); + + /** + * Factory method for map attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param elementNature The nature of the collection elements. + * @param indexNature The nature of the collection indexes. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + MapBinding makeMapAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature elementNature, + PluralAttributeIndexNature indexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath); + + /** + * Factory method for set attribute bindings. + * + * + * @param attribute The attribute for which to make a binding. + * @param nature The nature of the collection elements. + * @param referencedAttributeBinding + * @param propertyAccessorName + * @param includedInOptimisticLocking + * @param metaAttributeContext + * + * @return The attribute binding instance. + */ + SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java new file mode 100644 index 000000000000..529a691f08e4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BackRefAttributeBinding.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; + +/** + * @author Gail Badner + */ +public class BackRefAttributeBinding extends BasicAttributeBinding { + + private final PluralAttributeBinding pluralAttributeBinding; + private final boolean isIndexBackRef; + + BackRefAttributeBinding( + EntityBinding entityBinding, + SingularAttribute attribute, + PluralAttributeBinding pluralAttributeBinding, + boolean isIndexBackRef) { + super( + entityBinding, + attribute, + createRelationalValueBindings( pluralAttributeBinding, isIndexBackRef ), + null, + false, + false, + NaturalIdMutability.NOT_NATURAL_ID, + null, + pluralAttributeBinding.getAttributeRole().append( "backRef" ), + pluralAttributeBinding.getAttributePath().append( "backRef" ), + PropertyGeneration.NEVER + ); + this.pluralAttributeBinding = pluralAttributeBinding; + this.isIndexBackRef = isIndexBackRef; + } + + private static List createRelationalValueBindings( + PluralAttributeBinding pluralAttributeBinding, + boolean isIndexBackRef) { + List relationalValueBindings; + if ( isIndexBackRef ) { + PluralAttributeIndexBinding indexBinding = + ( (IndexedPluralAttributeBinding) pluralAttributeBinding).getPluralAttributeIndexBinding(); + relationalValueBindings = indexBinding.getRelationalValueBindings(); + + } + else { + relationalValueBindings = new ArrayList( ); + for ( RelationalValueBinding keyRelationalValueBinding : pluralAttributeBinding.getPluralAttributeKeyBinding().getRelationalValueBindings() ) { + Column keyColumn = (Column) keyRelationalValueBinding.getValue(); + relationalValueBindings.add( new RelationalValueBinding( keyRelationalValueBinding.getTable(), keyColumn, true, false ) ); + } + } + return relationalValueBindings; + } + + public String getCollectionRole() { + return pluralAttributeBinding.getAttribute().getRole(); + } + + public String getEntityName() { + return pluralAttributeBinding.getContainer().seekEntityBinding().getEntityName(); + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + public boolean isBackRef() { + return true; + } + + public boolean isIndexBackRef() { + return isIndexBackRef; + } + + @Override + public boolean isIncludedInUpdate() { + //TODO: should be able to rely on super method, but that seems broken currently. + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java new file mode 100644 index 000000000000..54ca413a050e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class BagBinding extends AbstractPluralAttributeBinding { + protected BagBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java new file mode 100644 index 000000000000..58695cbe135a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; + +/** + * @author Steve Ebersole + */ +public class BasicAttributeBinding + extends AbstractSingularAttributeBinding + implements SingularNonAssociationAttributeBinding { + + private final RelationalValueBindingContainer relationalValueBindingContainer; + private final PropertyGeneration generation; + + BasicAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + PropertyGeneration generation) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath + ); + this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings ); + this.generation = generation; + } + + @Override + public boolean isAssociation() { + return false; + } + + public PropertyGeneration getGeneration() { + return generation; + } + + @Override + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + return relationalValueBindingContainer; + } + + @Override + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + relationalValueBindingContainer.addRelationalValueBindings( this.relationalValueBindingContainer ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java new file mode 100644 index 000000000000..00e3ddd9ba9c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeIndexBinding.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * + */ +public class BasicPluralAttributeIndexBinding extends AbstractPluralAttributeIndexBinding { + + private RelationalValueBindingContainer relationalValueBindingContainer; + + public BasicPluralAttributeIndexBinding( + IndexedPluralAttributeBinding pluralAttributeBinding) { + super( pluralAttributeBinding ); + } + + @Override + public List getRelationalValueBindings() { + return relationalValueBindingContainer.relationalValueBindings(); + } + + @Override + public List getValues() { + return relationalValueBindingContainer.values(); + } + + public void setRelationalValueBindings(List relationalValueBindings) { + if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) { + throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." ); + } + if ( this.relationalValueBindingContainer != null ) { + throw new AssertionFailure( "Relational value bindings have already initialized" ); + } + this.relationalValueBindingContainer = + new RelationalValueBindingContainer( relationalValueBindings ); + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.BASIC; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Caching.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Caching.java new file mode 100644 index 000000000000..68169fe2fca7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Caching.java @@ -0,0 +1,124 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.TruthValue; +import org.hibernate.boot.spi.CacheRegionDefinition; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.internal.util.StringHelper; + +/** + * Defines the caching settings for an entity. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class Caching { + // NOTE : TruthValue for now because I need to look at how JPA's SharedCacheMode concept is handled + private TruthValue requested = TruthValue.UNKNOWN; + private String region; + private AccessType accessType; + private boolean cacheLazyProperties; + + public Caching(TruthValue requested) { + this.requested = requested; + } + + public Caching(String region, AccessType accessType, boolean cacheLazyProperties) { + this( region, accessType, cacheLazyProperties, TruthValue.UNKNOWN ); + } + + public Caching(String region, AccessType accessType, boolean cacheLazyProperties, TruthValue requested) { + this.requested = requested; + this.region = region; + this.accessType = accessType; + this.cacheLazyProperties = cacheLazyProperties; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public AccessType getAccessType() { + return accessType; + } + + public void setAccessType(AccessType accessType) { + this.accessType = accessType; + } + + public boolean isCacheLazyProperties() { + return cacheLazyProperties; + } + + public void setCacheLazyProperties(boolean cacheLazyProperties) { + this.cacheLazyProperties = cacheLazyProperties; + } + + public TruthValue getRequested() { + return requested; + } + + public void setRequested(TruthValue requested) { + this.requested = requested; + } + + public void overlay(CacheRegionDefinition overrides) { + if ( overrides == null ) { + return; + } + + requested = TruthValue.TRUE; + accessType = AccessType.fromExternalName( overrides.getUsage() ); + if ( StringHelper.isEmpty( overrides.getRegion() ) ) { + region = overrides.getRegion(); + } + // ugh, primitive boolean + cacheLazyProperties = overrides.isCacheLazy(); + } + + public void overlay(Caching overrides) { + if ( overrides == null ) { + return; + } + + this.requested = overrides.requested; + this.accessType = overrides.accessType; + this.region = overrides.region; + this.cacheLazyProperties = overrides.cacheLazyProperties; + } + + @Override + public String toString() { + return "Caching{region='" + region + '\'' + + ", accessType=" + accessType + + ", cacheLazyProperties=" + cacheLazyProperties + + ", requested=" + requested + '}'; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CascadeType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CascadeType.java similarity index 99% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CascadeType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CascadeType.java index 14a4f2aa0ad6..226b8568f04a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CascadeType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CascadeType.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.HashMap; import java.util.Map; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Cascadeable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Cascadeable.java new file mode 100644 index 000000000000..a0c253a82665 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Cascadeable.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.engine.spi.CascadeStyle; + +/** + * @author Steve Ebersole + */ +public interface Cascadeable { + /** + * Obtain the cascade style to be applied to this association. + * + * @return The cascade style. + */ + public CascadeStyle getCascadeStyle(); + + public void setCascadeStyle(CascadeStyle cascadeStyle); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionLaziness.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CollectionLaziness.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionLaziness.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CollectionLaziness.java index 72240474c9b2..ef4c1973b545 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionLaziness.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CollectionLaziness.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java new file mode 100644 index 000000000000..adf3680405b3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositePluralAttributeIndexBinding.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.PluralAttributeElementNature#AGGREGATE} elements + * + * @author Gail Badner + */ +public class CompositePluralAttributeIndexBinding extends AbstractPluralAttributeIndexBinding { + + // TODO: Come up with a more descriptive name for compositeAttributeBindingContainer. + private AbstractEmbeddableBinding compositeAttributeBindingContainer; + + public CompositePluralAttributeIndexBinding(IndexedPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public PluralAttributeIndexNature getNature() { + return PluralAttributeIndexNature.AGGREGATE; + } + + public EmbeddableBinding createCompositeAttributeBindingContainer( + Aggregate aggregate, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference, + Class tuplizerClass) { + compositeAttributeBindingContainer = new AbstractEmbeddableBinding( + getIndexedPluralAttributeBinding().getContainer().seekEntityBinding(), + aggregate, + getIndexedPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(), + getIndexedPluralAttributeBinding().getAttributeRole().append( "key" ), + getIndexedPluralAttributeBinding().getAttributePath().append( "key" ), + metaAttributeContext, + parentReference, + tuplizerClass) { + final Map attributeBindingMap = new LinkedHashMap(); + + @Override + protected boolean isModifiable() { + return true; + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return true; + } + }; + return compositeAttributeBindingContainer; + } + + public EmbeddableBinding getCompositeAttributeBindingContainer() { + return compositeAttributeBindingContainer; + } + + @Override + public List getRelationalValueBindings() { + return compositeAttributeBindingContainer.getRelationalValueBindingContainer().relationalValueBindings(); + } + + @Override + public List getValues() { + return compositeAttributeBindingContainer.getRelationalValueBindingContainer().values(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CustomSQL.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CustomSQL.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/CustomSQL.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CustomSQL.java index 17cc3493647b..67da4cfcf25d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CustomSQL.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CustomSQL.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddableBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddableBinding.java new file mode 100644 index 000000000000..5aa7b15c8f68 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddableBinding.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * @author Gail Badner + */ +public interface EmbeddableBinding extends AttributeBindingContainer { + boolean isAggregated(); + SingularAttribute getParentReference(); + + @Override + Class getCustomTuplizerClass(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddableBindingContributor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddableBindingContributor.java new file mode 100644 index 000000000000..5cb512e5ebf4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddableBindingContributor.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * @author Steve Ebersole + */ +public interface EmbeddableBindingContributor { + EmbeddableBinding getEmbeddableBinding(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddedAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddedAttributeBinding.java new file mode 100644 index 000000000000..0dbe158c96a4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EmbeddedAttributeBinding.java @@ -0,0 +1,309 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * Models the binding information for embeddable/composite values. + * + * @author Gail Badner + * @author Steve Ebersole + */ +public class EmbeddedAttributeBinding + extends AbstractSingularAttributeBinding + implements SingularNonAssociationAttributeBinding, Cascadeable, EmbeddableBindingContributor { + + private final AbstractEmbeddableBinding embeddableBinding; + + private EmbeddedAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + AbstractEmbeddableBinding embeddableBinding) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath + ); + this.embeddableBinding = embeddableBinding; + + getHibernateTypeDescriptor().setJavaTypeDescriptor( embeddableBinding.getAttributeContainer().getDescriptor() ); + } + + public static EmbeddedAttributeBinding createEmbeddedAttributeBinding( + final AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + SingularAttribute parentReference, + Class tuplizerClass) { + final AbstractEmbeddableBinding embeddableBinding = new AbstractEmbeddableBinding( + container.seekEntityBinding(), + (AttributeContainer) attribute.getSingularAttributeType(), + container.getPrimaryTable(), + attributeRole, + attributePath, + metaAttributeContext, + parentReference, + tuplizerClass) { + private final Map attributeBindingMap = new LinkedHashMap(); + + @Override + protected boolean isModifiable() { + return true; + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return true; + } + }; + + if ( ! attribute.getSingularAttributeType().isAggregate() ) { + throw new IllegalArgumentException( + "Cannot create an aggregated EmbeddableBinding with a non-aggregate attribute type" + ); + } + return new EmbeddedAttributeBinding( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + embeddableBinding + ); + } + + // TODO: Get rid of this when non-aggregated composite IDs is no longer modelled as a EmbeddedAttributeBinding. + public static EmbeddedAttributeBinding createVirtualEmbeddedAttributeBinding( + final AttributeBindingContainer container, + SingularAttribute syntheticAttribute, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + final List subAttributeBindings) { + AbstractEmbeddableBinding embeddableBinding = new AbstractEmbeddableBinding( + container.seekEntityBinding(), + (AttributeContainer) syntheticAttribute.getSingularAttributeType(), + container.getPrimaryTable(), + attributeRole, + attributePath, + metaAttributeContext, + null, + null) { + private final Map attributeBindingMap = createUnmodifiableAttributeBindingMap( subAttributeBindings ); + + @Override + protected boolean isModifiable() { + return false; + } + + @Override + protected Map attributeBindingMapInternal() { + return this.attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return false; + } + }; + + if ( syntheticAttribute.getSingularAttributeType().isAggregate() ) { + throw new IllegalArgumentException( + "Cannot create a non-aggregated EmbeddableBinding with an aggregate attribute type" + ); + } + return new EmbeddedAttributeBinding( + container, + syntheticAttribute, + "embedded", // TODO: get rid of "magic" string. + false, + false, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + embeddableBinding + ); + } + + private static Map createUnmodifiableAttributeBindingMap( + List subAttributeBindings) { + Map map = new LinkedHashMap( subAttributeBindings.size() ); + for ( AttributeBinding subAttributeBinding : subAttributeBindings ) { + map.put( subAttributeBinding.getAttribute().getName(), subAttributeBinding ); + } + return Collections.unmodifiableMap( map ); + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + protected RelationalValueBindingContainer getRelationalValueBindingContainer() { + return embeddableBinding.getRelationalValueBindingContainer(); + } + + @Override + public boolean hasDerivedValue() { + // todo : not sure this is even relevant for components + return false; + } + + @Override + public boolean isCascadeable() { + for ( AttributeBinding attributeBinding : embeddableBinding.attributeBindings() ) { + if ( attributeBinding.isCascadeable() ) { + return true; + } + } + return false; + } + + @Override + public CascadeStyle getCascadeStyle() { + for ( AttributeBinding attributeBinding : embeddableBinding.attributeBindings() ) { + if ( attributeBinding.isCascadeable() ) { + final Cascadeable cascadeable; + if ( attributeBinding.getAttribute().isSingular() ) { + cascadeable = Cascadeable.class.cast( attributeBinding ); + } + else { + cascadeable = Cascadeable.class.cast( ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding() ); + } + CascadeStyle cascadeStyle = cascadeable.getCascadeStyle(); + if ( cascadeStyle != CascadeStyles.NONE ) { + return CascadeStyles.ALL; + } + } + } + return CascadeStyles.NONE; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + throw new IllegalAccessError( "Composite attribute is not supposed to have cascade" ); + } + + @Override + public boolean isNullable() { + // return false if there are any singular attributes are non-nullable + for ( AttributeBinding attributeBinding : embeddableBinding.attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ! ( (SingularAttributeBinding) attributeBinding ).isNullable() ) { + return false; + } + } + return true; + } + + @Override + public boolean isIncludedInInsert() { + // if the attribute is synthetic, this attribute binding (as a whole) is not insertable; + if ( getAttribute().isSynthetic() ) { + return false; + } + // otherwise, return true if there are any singular attributes that are included in the insert. + for ( AttributeBinding attributeBinding : embeddableBinding.attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ( (SingularAttributeBinding) attributeBinding ).isIncludedInInsert() ) { + return true; + } + } + return false; + } + + @Override + public boolean isIncludedInUpdate() { + // if the attribute is synthetic, this attribute binding (as a whole) is not updateable; + if ( getAttribute().isSynthetic() ) { + return false; + } + // otherwise, return true if there are any singular attributes that are updatable; + for ( AttributeBinding attributeBinding : embeddableBinding.attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ( (SingularAttributeBinding) attributeBinding ).isIncludedInUpdate() ) { + return true; + } + } + return false; + } + + @Override + protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + embeddableBinding.collectRelationalValueBindings( relationalValueBindingContainer ); + } + + @Override + public EmbeddableBinding getEmbeddableBinding() { + return embeddableBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java new file mode 100644 index 000000000000..ad98b4c40bd1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java @@ -0,0 +1,841 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.AssertionFailure; +import org.hibernate.MappingException; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.source.spi.JpaCallbackSource; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.tuple.entity.EntityTuplizer; + +/** + * Provides the link between the domain and the relational model for an entity. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + * @author Strong Liu + */ +public class EntityBinding extends AbstractAttributeBindingContainer implements Filterable { + private static final String NULL_DISCRIMINATOR_MATCH_VALUE = "null"; + private static final String NOT_NULL_DISCRIMINATOR_MATCH_VALUE = "not null"; + + private final EntityBinding superEntityBinding; + private final List subEntityBindings = new ArrayList(); + private final HierarchyDetails hierarchyDetails; + + private Entity entity; + private TableSpecification primaryTable; + private String primaryTableName; + private Map secondaryTables = new LinkedHashMap(); + + private JavaTypeDescriptor proxyInterfaceType; + + private String entityName; + private String jpaEntityName; + + private Class customEntityPersisterClass; + private Class customEntityTuplizerClass; + + private String discriminatorMatchValue; + + private List filterConfigurations = new ArrayList(); + + private MetaAttributeContext metaAttributeContext; + + private boolean lazy; + private String rowId; + + private boolean dynamicUpdate; + private boolean dynamicInsert; + + private int batchSize; + private boolean selectBeforeUpdate; + private boolean hasSubselectLoadableCollections; + + private Boolean isAbstract; + + private String customLoaderName; + private CustomSQL customInsert; + private CustomSQL customUpdate; + private CustomSQL customDelete; + + private String[] synchronizedTableNames = StringHelper.EMPTY_STRINGS; + private Map attributeBindingMap = new LinkedHashMap(); + + private List jpaCallbackClasses = new ArrayList(); + private final int subEntityBindingId; + private int nextSubEntityBindingId = 0; + //for joined sub entitybinding only + private boolean isCascadeDeleteEnabled = false; + + private AttributePath pathBase; + private AttributeRole roleBase; + + public EntityBinding(HierarchyDetails hierarchyDetails) { + this.hierarchyDetails = hierarchyDetails; + this.superEntityBinding = null; + this.subEntityBindingId = 0; + } + + public EntityBinding makeSubBinding() { + final EntityBinding sub = new EntityBinding( this ); + subEntityBindings.add( sub ); + return sub; + } + + /** + * Used to instantiate the EntityBinding for an entity that is a subclass (sub-entity) in an inheritance hierarchy + * + * @param superEntityBinding The entity binding of this binding's super + */ + public EntityBinding(EntityBinding superEntityBinding) { + this.superEntityBinding = superEntityBinding; + this.hierarchyDetails = superEntityBinding.getHierarchyDetails(); + this.subEntityBindingId = superEntityBinding.nextSubEntityBindingId(); + + // TODO: the ID attribute binding needs to be recreated for this EntityBinding + // otherwise, this != hierarchyDetails.getEntityIdentifier().getAttributeBinding().getContainer() + } + + private int nextSubEntityBindingId(){ + return isRoot()? ++nextSubEntityBindingId : superEntityBinding.nextSubEntityBindingId(); + } + + public HierarchyDetails getHierarchyDetails() { + return hierarchyDetails; + } + + public EntityBinding getSuperEntityBinding() { + return superEntityBinding; + } + + public int getSubEntityBindingId() { + return subEntityBindingId; + } + + public boolean isRoot() { + return superEntityBinding == null; + } + + public boolean isPolymorphic() { + return !isRoot() || + hierarchyDetails.getEntityDiscriminator() != null || + !subEntityBindings.isEmpty(); + } + + public boolean hasSubEntityBindings() { + return !subEntityBindings.isEmpty(); + } + + + + public Entity getEntity() { + return entity; + } + + public void setEntity(Entity entity) { + this.entity = entity; + + this.pathBase = new AttributePath(); + this.roleBase = new AttributeRole( entity.getName() ); + } + + @Override + public TableSpecification getPrimaryTable() { + return primaryTable; + } + + public void setPrimaryTable(TableSpecification primaryTable) { + this.primaryTable = primaryTable; + } + + public boolean hasTable(String tableName) { + return tableName.equals( getPrimaryTableName() ) || + secondaryTables.containsKey( Identifier.toIdentifier( tableName ) ); + } + + public TableSpecification locateTable(String tableName) { + if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) { + return primaryTable; + } + SecondaryTable secondaryTable = secondaryTables.get( Identifier.toIdentifier( tableName ) ); + if ( secondaryTable == null ) { + throw new AssertionFailure( + String.format( + "Unable to find table %s amongst tables %s", + tableName, + secondaryTables.keySet() + ) + ); + } + return secondaryTable.getSecondaryTableReference(); + } + + public AttributeBinding locateAttributeBinding(String name, boolean searchParent) { + AttributeBinding attributeBinding = locateAttributeBinding( name ); + if ( attributeBinding == null && searchParent && getSuperEntityBinding() != null ) { + return getSuperEntityBinding().locateAttributeBinding( name, searchParent ); + } + else { + return attributeBinding; + } + } + + public SingularAttributeBinding locateAttributeBinding( + TableSpecification table, + List values, + boolean searchParent) { + SingularAttributeBinding attributeBinding = null; + SingularAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( primaryTable.equals( table ) && idAttributeBinding.getValues().equals( values ) ) { + attributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + } + if ( attributeBinding == null ) { + attributeBinding = locateAttributeBinding( table, values ); + } + if ( attributeBinding == null && searchParent && getSuperEntityBinding() != null ) { + attributeBinding = getSuperEntityBinding().locateAttributeBinding( table, values, searchParent ); + } + return attributeBinding; + } + + public AttributeBinding locateAttributeBindingByPath(String path, boolean searchParent) { + if ( path == null ) { + throw new IllegalArgumentException( "path must be non-null." ); + } + final String pathDelimiter = "\\."; + String[] tokens = path.split( pathDelimiter ); + AttributeBinding attributeBinding = locateAttributeBinding( tokens[ 0 ], searchParent ); + for ( int i = 1 ; i < tokens.length && attributeBinding != null ; i++ ) { + final AttributeBindingContainer attributeBindingContainer; + if ( AttributeBindingContainer.class.isInstance( attributeBinding ) ) { + attributeBindingContainer = (AttributeBindingContainer) attributeBinding; + } + else if ( EmbeddedAttributeBinding.class.isInstance( attributeBinding ) ) { + attributeBindingContainer = ( (EmbeddedAttributeBinding) attributeBinding ).getEmbeddableBinding(); + } + else { + // TODO: improve this message!!! + throw new MappingException( "improve this!!!" ); + } + + attributeBinding = attributeBindingContainer.locateAttributeBinding( tokens[i] ); + } + return attributeBinding; + } + + public String getPrimaryTableName() { + return primaryTableName; + } + + public void setPrimaryTableName(String primaryTableName) { + this.primaryTableName = primaryTableName; + } + + public void addSecondaryTable(SecondaryTable secondaryTable) { + secondaryTables.put( secondaryTable.getSecondaryTableReference().getLogicalName(), secondaryTable ); + } + public Map getSecondaryTables() { + return Collections.unmodifiableMap( secondaryTables ); + } + + public boolean isDiscriminatorMatchValueNull() { + return NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); + } + + public boolean isDiscriminatorMatchValueNotNull() { + return NOT_NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue ); + } + + public String getDiscriminatorMatchValue() { + return discriminatorMatchValue; + } + + public void setDiscriminatorMatchValue(String discriminatorMatchValue) { + this.discriminatorMatchValue = discriminatorMatchValue; + } + + @Override + public void addFilterConfiguration(FilterConfiguration filterConfiguration) { + filterConfigurations.add( filterConfiguration ); + } + + @Override + public List getFilterConfigurations() { + if ( superEntityBinding != null ) { + List results = new ArrayList( filterConfigurations ); + results.addAll( superEntityBinding.getFilterConfigurations() ); + return results; + } + return filterConfigurations; + } + + @Override + public EntityBinding seekEntityBinding() { + return this; + } + + @Override + public AttributeRole getRoleBase() { + return roleBase; + } + + @Override + public AttributePath getPathBase() { + return pathBase; + } + + @Override + public AttributeContainer getAttributeContainer() { + return getEntity(); + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public MetaAttributeContext getMetaAttributeContext() { + return metaAttributeContext; + } + + public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { + this.metaAttributeContext = metaAttributeContext; + } + + public boolean isCascadeDeleteEnabled() { + return isCascadeDeleteEnabled; + } + + public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) { + isCascadeDeleteEnabled = cascadeDeleteEnabled; + } + + public boolean isLazy() { + return lazy; + } + + public void setLazy(boolean lazy) { + this.lazy = lazy; + } + + public JavaTypeDescriptor getProxyInterfaceType() { + return proxyInterfaceType; + } + + public void setProxyInterfaceType(JavaTypeDescriptor proxyInterfaceType) { + this.proxyInterfaceType = proxyInterfaceType; + } + + public String getRowId() { + return rowId; + } + + public void setRowId(String rowId) { + this.rowId = rowId; + } + + public boolean isDynamicUpdate() { + return dynamicUpdate; + } + + public void setDynamicUpdate(boolean dynamicUpdate) { + this.dynamicUpdate = dynamicUpdate; + } + + public boolean isDynamicInsert() { + return dynamicInsert; + } + + public void setDynamicInsert(boolean dynamicInsert) { + this.dynamicInsert = dynamicInsert; + } + + public int getBatchSize() { + return batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + public boolean isSelectBeforeUpdate() { + return selectBeforeUpdate; + } + + public void setSelectBeforeUpdate(boolean selectBeforeUpdate) { + this.selectBeforeUpdate = selectBeforeUpdate; + } + + public boolean hasSubselectLoadableCollections() { + return hasSubselectLoadableCollections; + } + + public void setSubselectLoadableCollections(boolean hasSubselectLoadableCollections) { + this.hasSubselectLoadableCollections = hasSubselectLoadableCollections; + } + + public Class getCustomEntityPersisterClass() { + if ( customEntityPersisterClass != null ) { + return customEntityPersisterClass; + } + else if ( superEntityBinding != null ) { + return superEntityBinding.getCustomEntityPersisterClass(); + } + return null; + } + + public void setCustomEntityPersisterClass(Class customEntityPersisterClass) { + this.customEntityPersisterClass = customEntityPersisterClass; + } + @Override + public Class getCustomTuplizerClass() { + if ( customEntityTuplizerClass != null ) { + return customEntityTuplizerClass; + } + else if ( superEntityBinding != null ) { + return superEntityBinding.getCustomTuplizerClass(); + } + return null; + } + + public void setCustomEntityTuplizerClass(Class customEntityTuplizerClass) { + this.customEntityTuplizerClass = customEntityTuplizerClass; + } + + public Boolean isAbstract() { + return isAbstract; + } + + public void setAbstract(Boolean isAbstract) { + this.isAbstract = isAbstract; + } + + public String[] getSynchronizedTableNames() { + return synchronizedTableNames; + } + + public void addSynchronizedTableNames(String [] synchronizedTableNames) { + this.synchronizedTableNames = ArrayHelper.join( this.synchronizedTableNames, synchronizedTableNames ); + } + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public String getJpaEntityName() { + return jpaEntityName; + } + + public void setJpaEntityName(String jpaEntityName) { + this.jpaEntityName = jpaEntityName; + } + + public String getCustomLoaderName() { + return customLoaderName; + } + + public void setCustomLoaderName(String customLoaderName) { + this.customLoaderName = customLoaderName; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public void setCustomInsert(CustomSQL customInsert) { + this.customInsert = customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public void setCustomUpdate(CustomSQL customUpdate) { + this.customUpdate = customUpdate; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public void setCustomDelete(CustomSQL customDelete) { + this.customDelete = customDelete; + } + + @Override + public String toString() { + return String.format( + "EntityBinding(%s)", + entity != null ? StringHelper.collapse( getEntityName() ) : "" + ); + } + + public EmbeddedAttributeBinding makeVirtualCompositeAttributeBinding( + SingularAttribute syntheticAttribute, + MetaAttributeContext metaAttributeContext, + List idAttributeBindings) { + if ( !syntheticAttribute.isSynthetic() ) { + throw new AssertionFailure( + "Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference" + ); + } + // TODO: make sure all attributes are singular + final EmbeddedAttributeBinding binding = EmbeddedAttributeBinding.createVirtualEmbeddedAttributeBinding( + this, + syntheticAttribute, + NaturalIdMutability.NOT_NATURAL_ID, + metaAttributeContext, + getRoleBase(), + getPathBase(), + idAttributeBindings + ); +// registerAttributeBinding( binding ); + return binding; + } + + public BackRefAttributeBinding makeBackRefAttributeBinding( + SingularAttribute syntheticAttribute, + PluralAttributeBinding pluralAttributeBinding, + boolean isIndexBackRef) { + if ( ! syntheticAttribute.isSynthetic() ) { + throw new AssertionFailure( + "Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference" + ); + } + final BackRefAttributeBinding binding = new BackRefAttributeBinding( + this, + syntheticAttribute, + pluralAttributeBinding, + isIndexBackRef + ); + + registerAttributeBinding( binding ); + return binding; + } + + + public void setJpaCallbackClasses(List jpaCallbackClasses) { + this.jpaCallbackClasses = jpaCallbackClasses; + } + + public List getJpaCallbackClasses() { + return Collections.unmodifiableList( jpaCallbackClasses ); + } + //-------------------------- + //meta methods for persister , to improve performance, these methods below should really be replaced as ValueHolder + //and only be called in persister -- after build MetadataImpl + + + public TableSpecification[] getTableClosure() { + if ( isRoot() ) { + return new TableSpecification[] { getPrimaryTable() }; + } + return ArrayHelper.join( superEntityBinding.getTableClosure(), getPrimaryTable() ); + } + + public EntityBinding[] getEntityBindingClosure() { + if ( isRoot() ) { + return new EntityBinding[] { this }; + } + return ArrayHelper.join( superEntityBinding.getEntityBindingClosure(), this ); + } + + public int getSecondaryTableClosureSpan() { + return isRoot() ? secondaryTables.size() : superEntityBinding.getSecondaryTableClosureSpan() + secondaryTables.size(); + } + + public SecondaryTable[] getSecondaryTableClosure() { + if ( isRoot() ) { + return secondaryTables.values().toArray( new SecondaryTable[secondaryTables.size()] ); + } + else { + return ArrayHelper.join( + superEntityBinding.getSecondaryTableClosure(), + secondaryTables.values().toArray( new SecondaryTable[secondaryTables.size()] ) + ); + } + } + + public String[] getSynchronizedTableNameClosure() { + if ( isRoot() ) { + return getSynchronizedTableNames(); + } + return ArrayHelper.join( superEntityBinding.getSynchronizedTableNameClosure(), getSynchronizedTableNames() ); + } + + + /** + * Gets the number of attribute bindings defined on this class, including the + * identifier attribute binding and attribute bindings defined + * as part of a join. + * + * @return The number of attribute bindings + */ + public int getAttributeBindingClosureSpan() { + // TODO: update account for join attribute bindings + return getAttributeBindingClosure().length; + } + + /** + * Gets the attribute bindings defined on this class, including the + * identifier attribute binding and attribute bindings defined + * as part of a join. + * + * @return The attribute bindings. + */ + public AttributeBinding[] getAttributeBindingClosure() { + // TODO: update size to account for joins + if ( isRoot() ) { + return attributeBindingMapInternal().values() + .toArray( new AttributeBinding[attributeBindingMapInternal().size()] ); + } + else { + return ArrayHelper.join( + superEntityBinding.getAttributeBindingClosure(), + attributeBindingMapInternal().values() + .toArray( new AttributeBinding[attributeBindingMapInternal().size()] ) + + ); + } + } + + public AttributeBinding[] getNonIdAttributeBindingClosure(){ + // TODO: update size to account for joins + if ( isRoot() ) { + return internalGetNonIdAttributeBindings(); + } + else { + return ArrayHelper.join( + superEntityBinding.getNonIdAttributeBindingClosure(), + internalGetNonIdAttributeBindings() + ); + } + } + + public List getNonIdAttributeBindings() { + final List list = new ArrayList(); + for ( final AttributeBinding ab : attributeBindings() ) { + boolean isId = getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( ab ); + if ( !isId ) { + list.add( ab ); + } + } + return list; + + } + + private AttributeBinding[] internalGetNonIdAttributeBindings() { + final List list = getNonIdAttributeBindings(); + return list.toArray( new AttributeBinding[list.size()] ); + } + + public List getDirectSubEntityBindings() { + return subEntityBindings; + } + + /** + * Returns sub-EntityBinding objects in a special 'order', most derived subclasses + * first. Specifically, the sub-entity bindings follow a depth-first, + * post-order traversal + * + * Note that the returned value excludes this entity binding. + * + * @return sub-entity bindings ordered by those entity bindings that are most derived. + */ + public EntityBinding[] getPostOrderSubEntityBindingClosure() { + EntityBinding[] results = new EntityBinding[0]; + if ( subEntityBindings.isEmpty() ) { + return results; + } + for ( EntityBinding subEntityBinding : subEntityBindings ) { + EntityBinding[] subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure(); + results = ArrayHelper.join( results, subSubEntityBindings ); + } + if ( !subEntityBindings.isEmpty() ) { + results = ArrayHelper.join( results, subEntityBindings.toArray( new EntityBinding[subEntityBindings.size()] ) ); + } + return results; + } + + /** + * Returns sub-EntityBinding ordered as a depth-first, + * pre-order traversal (a subclass precedes its own subclasses). + * + * Note that the returned value specifically excludes this entity binding. + * + * @return sub-entity bindings ordered as a depth-first, + * pre-order traversal + */ + public EntityBinding[] getPreOrderSubEntityBindingClosure() { + return getPreOrderSubEntityBindingClosure( false, new EntityBinding[0] ); + } + + private EntityBinding[] getPreOrderSubEntityBindingClosure(boolean includeThis, EntityBinding[] results) { + if ( includeThis ) { + results = ArrayHelper.join( results, this ); + } + for ( EntityBinding subEntityBinding : subEntityBindings ) { + results = subEntityBinding.getPreOrderSubEntityBindingClosure( + true, results + ); + } + return results; + } + + public TableSpecification[] getPreOrderSubTableClosure(){ + EntityBinding[] subEntityBindings = getPreOrderSubEntityBindingClosure(); + TableSpecification [] tables = new TableSpecification[subEntityBindings.length]; + for(int i=0;i sts = eb.getSecondaryTables().values(); + int size = sts.size(); + if ( size == 0 ) { + continue; + } + results = ArrayHelper.join( results, sts.toArray( new SecondaryTable[size] ) ); + } + return results; + } + + + public SecondaryTable[] getEntitiesSecondaryTableClosure() { + if ( ! subEntityBindings.isEmpty() ) { + return ArrayHelper.join( getSecondaryTableClosure(), getSubEntitySecondaryTables() ); + } + else { + return getSecondaryTableClosure(); + } + } + + public int getSubEntityBindingClosureSpan() { + int n = subEntityBindings.size(); + for ( final EntityBinding seb : subEntityBindings ) { + n += seb.getSubEntityBindingClosureSpan(); + } + return n; + } + + /** + * @return the attribute bindings for this EntityBinding and all of its + * sub-EntityBinding, starting from the root of the hierarchy; includes + * the identifier and attribute bindings defined as part of a join. + */ + public AttributeBinding[] getEntitiesAttributeBindingClosure() { + AttributeBinding[] results = getAttributeBindingClosure(); + + for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) { + // only add attribute bindings declared for the subEntityBinding + + results = ArrayHelper.join( + results, + subEntityBinding.attributeBindingMapInternal().values().toArray( new AttributeBinding[subEntityBinding.attributeBindingMapInternal().size()] ) + ); + // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here + } + return results; + } + public AttributeBinding[] getNonIdEntitiesAttributeBindingClosure() { + AttributeBinding[] results = getNonIdAttributeBindingClosure(); + + for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) { + // only add attribute bindings declared for the subEntityBinding + + results = ArrayHelper.join( + results, + subEntityBinding.internalGetNonIdAttributeBindings() + ); + // TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here + } + return results; + } + + public boolean isClassOrSuperclassSecondaryTable(SecondaryTable secondaryTable) { + return secondaryTables.containsKey( secondaryTable.getSecondaryTableReference().getLogicalName() ) || + ( superEntityBinding != null && superEntityBinding.isClassOrSuperclassSecondaryTable( secondaryTable ) ); + } + + private List keyRelationalValueBindings; + + public List getKeyRelationalValueBindings() { + if(keyRelationalValueBindings == null){ + keyRelationalValueBindings = getHierarchyDetails().getEntityIdentifier().getAttributeBinding().getRelationalValueBindings(); + } + return keyRelationalValueBindings; + } + + public void setKeyRelationalValueBindings(List keyRelationalValueBindings) { + this.keyRelationalValueBindings = keyRelationalValueBindings; + } + + public int getSecondaryTableNumber(SingularAttributeBinding attributeBinding) { + if ( attributeBinding.getRelationalValueBindings().isEmpty() ) { + return 0; + } + int result=1; + TableSpecification table = attributeBinding.getRelationalValueBindings().get( 0 ).getTable(); + for ( SecondaryTable secondaryTable : getEntitiesSecondaryTableClosure() ) { + if ( secondaryTable.getSecondaryTableReference() == table ) { + return result; + } + result++; + } + return 0; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java index 724d194d8fd6..f3d7dc45bb71 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityDiscriminator.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java @@ -21,9 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; -import org.hibernate.metamodel.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.Value; /** * Binding of the discriminator in a entity hierarchy @@ -34,23 +34,27 @@ public class EntityDiscriminator { private final HibernateTypeDescriptor explicitHibernateTypeDescriptor = new HibernateTypeDescriptor(); - private SimpleValue boundValue; + private Value relationalValue; + private boolean inserted; private boolean forced; - private boolean inserted = true; public EntityDiscriminator() { } - public SimpleValue getBoundValue() { - return boundValue; + public Value getRelationalValue() { + return relationalValue; } - public void setBoundValue(SimpleValue boundValue) { - this.boundValue = boundValue; + public void setRelationalValue(Value relationalValue) { + this.relationalValue = relationalValue; } - public HibernateTypeDescriptor getExplicitHibernateTypeDescriptor() { - return explicitHibernateTypeDescriptor; + public boolean isInserted() { + return inserted; + } + + public void setInserted(boolean inserted) { + this.inserted = inserted; } public boolean isForced() { @@ -61,22 +65,14 @@ public void setForced(boolean forced) { this.forced = forced; } - public boolean isInserted() { - return inserted; - } - - public void setInserted(boolean inserted) { - this.inserted = inserted; + public HibernateTypeDescriptor getExplicitHibernateTypeDescriptor() { + return explicitHibernateTypeDescriptor; } @Override public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "EntityDiscriminator" ); - sb.append( "{boundValue=" ).append( boundValue ); - sb.append( ", forced=" ).append( forced ); - sb.append( ", inserted=" ).append( inserted ); - sb.append( '}' ); - return sb.toString(); + return "EntityDiscriminator{relationalValue=" + relationalValue + + ", forced=" + forced + + ", inserted=" + inserted + '}'; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityHierarchy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityHierarchy.java new file mode 100644 index 000000000000..46dfca581226 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityHierarchy.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.EntityMode; +import org.hibernate.engine.OptimisticLockStyle; + +/** + * Represents an Entity inheritance hierarchy in the binding model. + * + * @author Steve Ebersole + */ +public interface EntityHierarchy { + public EntityBinding getRootEntityBinding(); + + public InheritanceType getInheritanceType(); + + public EntityMode getEntityMode(); + + public EntityIdentifier getEntityIdentifier(); + + public EntityDiscriminator getEntityDiscriminator(); + + public EntityVersion getEntityVersion(); + + public OptimisticLockStyle getOptimisticLockStyle(); + + public TenantDiscrimination getTenantDiscrimination(); + + public Caching getCaching(); + + public Caching getNaturalIdCaching(); + + public boolean isMutable(); + + public boolean isExplicitPolymorphism(); + + /** + * Obtain the specified extra where condition to be applied to this entity. + * + * @return The extra where condition + */ + public String getWhere(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java new file mode 100644 index 000000000000..b4c5a31e290f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java @@ -0,0 +1,593 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.hibernate.MappingException; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.id.CompositeNestedGeneratedValueGenerator; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.factory.IdentifierGeneratorFactory; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.property.Setter; + +import static org.hibernate.id.EntityIdentifierNature.AGGREGATED_COMPOSITE; +import static org.hibernate.id.EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; +import static org.hibernate.id.EntityIdentifierNature.SIMPLE; + +/** + * Hold information about the entity identifier. At a high-level, can be one of + * 2 types:

        + *
      • + * single-attribute identifier - this includes both simple identifiers + * and aggregated composite identifiers + *
      • + *
      • + * multi-attribute identifier - non-aggregated composite identifiers + *
      • + *
      + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * @author Gail Badner + */ +public class EntityIdentifier { + private final EntityBinding entityBinding; + private EntityIdentifierBinding entityIdentifierBinding; + private IdentifierGenerator identifierGenerator; + + private LookupClassBinding lookupClassBinding; + + /** + * Create an identifier + * + * @param entityBinding the entity binding for which this instance is the id + */ + public EntityIdentifier(EntityBinding entityBinding) { + this.entityBinding = entityBinding; + } + + public EntityBinding getEntityBinding() { + return entityBinding; + } + + public void prepareAsSimpleIdentifier( + SingularAttributeBinding attributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue, + Class lookupIdClass, + String lookupIdClassAccessType) { + ensureNotBound(); + this.entityIdentifierBinding = new SimpleAttributeIdentifierBindingImpl( + attributeBinding, + identifierGeneratorDefinition, + unsavedValue + ); + this.lookupClassBinding = new LookupClassBindingImpl( lookupIdClass, lookupIdClassAccessType ); + } + + public void prepareAsAggregatedCompositeIdentifier( + EmbeddedAttributeBinding attributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue, + Class lookupIdClass, + String lookupIdClassAccessType) { + ensureNotBound(); + this.entityIdentifierBinding = new AggregatedComponentIdentifierBindingImpl( + attributeBinding, + identifierGeneratorDefinition, + unsavedValue + ); + this.lookupClassBinding = new LookupClassBindingImpl( lookupIdClass, lookupIdClassAccessType ); + } + + public void prepareAsNonAggregatedCompositeIdentifier( + EmbeddedAttributeBinding embeddedAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue, + Class lookupIdClass, + String lookupIdClassAccessType) { + ensureNotBound(); + this.entityIdentifierBinding = new NonAggregatedCompositeIdentifierBindingImpl( + embeddedAttributeBinding, + identifierGeneratorDefinition, + unsavedValue, + lookupIdClass, + lookupIdClassAccessType + ); + this.lookupClassBinding = new LookupClassBindingImpl( lookupIdClass, lookupIdClassAccessType ); + } + + public EntityIdentifierBinding getEntityIdentifierBinding() { + return entityIdentifierBinding; + } + + public LookupClassBinding getLookupClassBinding() { + return lookupClassBinding; + } + + public EntityIdentifierNature getNature() { + ensureBound(); + return entityIdentifierBinding.getNature(); + } + + public SingularAttributeBinding getAttributeBinding() { + ensureBound(); + return entityIdentifierBinding.getAttributeBinding(); + } + + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + ensureBound(); + return entityIdentifierBinding.isIdentifierAttributeBinding( attributeBinding ); + } + + public boolean isCascadeDeleteEnabled() { + if ( getAttributeBinding() instanceof Cascadeable ) { + Cascadeable cascadeable = Cascadeable.class.cast( getAttributeBinding() ); + cascadeable.getCascadeStyle();//todo + } + return false; + } + + public String getUnsavedValue() { + ensureBound(); + return entityIdentifierBinding.getUnsavedValue(); + } + + public boolean isNonAggregatedComposite() { + ensureBound(); + return getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE; + } + + /** + * Get the Class of the {@link javax.persistence.IdClass} associated with the entity, if one. + * + * @deprecated Use {@link #getLookupClassBinding()} instead + */ + @Deprecated + public Class getIdClassClass() { + ensureBound(); + return getLookupClassBinding().getIdClassType(); + } + + /** + * @deprecated Use {@link #getLookupClassBinding()} instead + */ + @Deprecated + public String getIdClassPropertyAccessorName() { + ensureBound(); + return getLookupClassBinding().getAccessStrategy(); + } + + /** + * @deprecated Use {@link #getLookupClassBinding()} instead + */ + @Deprecated + public boolean isIdentifierMapper() { + ensureBound(); + return isNonAggregatedComposite() && getLookupClassBinding().getIdClassType() != null; + } + + // todo do we really need this createIdentifierGenerator and how do we make sure the getter is not called too early + // maybe some sort of visitor pattern here!? (HF) + public IdentifierGenerator createIdentifierGenerator(IdentifierGeneratorFactory factory, Properties properties) { + ensureBound(); + if ( identifierGenerator == null ) { + identifierGenerator = entityIdentifierBinding.createIdentifierGenerator( factory, properties ); + } + return identifierGenerator; + } + + public IdentifierGenerator getIdentifierGenerator() { + ensureBound(); + return identifierGenerator; + } + + protected void ensureBound() { + if ( ! isBound() ) { + throw new IllegalStateException( "Entity identifier was not yet bound" ); + } + } + + protected void ensureNotBound() { + if ( isBound() ) { + throw new IllegalStateException( "Entity identifier was already bound" ); + } + } + + protected boolean isBound() { + return entityIdentifierBinding != null; + } + + public int getColumnCount() { + ensureBound(); + return entityIdentifierBinding.getColumnCount(); + } + + /** + * For now simply models {@link javax.persistence.IdClass} information. Ultimately should + * handle {@link javax.persistence.MapsId} information as well. + */ + public static interface LookupClassBinding { + public boolean definedIdClass(); + public Class getIdClassType(); + public String getAccessStrategy(); + } + + private static class LookupClassBindingImpl implements LookupClassBinding { + private final Class idClassType; + private final String accessStrategy; + + private LookupClassBindingImpl(Class idClassType, String accessStrategy) { + this.idClassType = idClassType; + this.accessStrategy = idClassType == null ? null : accessStrategy; + } + + @Override + public boolean definedIdClass() { + return getIdClassType() != null; + } + + @Override + public Class getIdClassType() { + return idClassType; + } + + @Override + public String getAccessStrategy() { + return accessStrategy; + } + } + + private abstract class EntityIdentifierBinding { + private final EntityIdentifierNature nature; + private final SingularAttributeBinding identifierAttributeBinding; + private final IdentifierGeneratorDefinition identifierGeneratorDefinition; + private final String unsavedValue; + private final int columnCount; + + protected EntityIdentifierBinding( + EntityIdentifierNature nature, + SingularAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + this.nature = nature; + this.identifierAttributeBinding = identifierAttributeBinding; + this.identifierGeneratorDefinition = identifierGeneratorDefinition; + this.unsavedValue = unsavedValue; + + // Configure primary key in relational model + final List relationalValueBindings = identifierAttributeBinding.getRelationalValueBindings(); + this.columnCount = relationalValueBindings.size(); + for ( final RelationalValueBinding valueBinding : relationalValueBindings ) { + entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() ); + } + } + + public EntityIdentifierNature getNature() { + return nature; + } + + public SingularAttributeBinding getAttributeBinding() { + return identifierAttributeBinding; + } + + public String getUnsavedValue() { + return unsavedValue; + } + + protected IdentifierGeneratorDefinition getIdentifierGeneratorDefinition() { + return identifierGeneratorDefinition; + } + + public int getColumnCount() { + return columnCount; + } + + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + return getAttributeBinding().equals( attributeBinding ); + } + + public IdentifierGenerator createIdentifierGenerator( + IdentifierGeneratorFactory identifierGeneratorFactory, + Properties properties) { + final List relationalValueBindings = + getAttributeBinding().getRelationalValueBindings(); + + // TODO: If multiple @Column annotations exist within an id's + // @Columns, we need a more solid solution than simply grabbing + // the first one to get the TableSpecification. + + final RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + final TableSpecification table = relationalValueBinding.getTable(); + if ( !Column.class.isInstance( relationalValueBinding.getValue() ) ) { + throw new MappingException( + "Cannot create an IdentifierGenerator because the value is not a column: " + + relationalValueBinding.getValue().toLoggableString() + ); + } + + Properties params = new Properties(); + params.putAll( properties ); + + // use the schema/catalog specified by getValue().getTable() - but note that + // if the schema/catalog were specified as params, they will already be initialized and + //will override the values set here (they are in identifierGeneratorDefinition.getParameters().) + Schema schema = table.getSchema(); + if ( schema != null ) { + if ( schema.getName().getSchema() != null ) { + params.setProperty( PersistentIdentifierGenerator.SCHEMA, schema.getName().getSchema().getText() ); + } + if ( schema.getName().getCatalog() != null ) { + params.setProperty( PersistentIdentifierGenerator.CATALOG, schema.getName().getCatalog().getText() ); + } + } + + params.setProperty( IdentifierGenerator.ENTITY_NAME, entityBinding.getEntityName() ); + params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, entityBinding.getJpaEntityName() ); + + //init the table here instead of earlier, so that we can get a quoted table name + //TODO: would it be better to simply pass the qualified table name, instead of + // splitting it up into schema/catalog/table names + String tableName = table.getQualifiedName( identifierGeneratorFactory.getDialect() ); + params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); + + params.setProperty( + PersistentIdentifierGenerator.PK, + ( (Column) relationalValueBinding.getValue() ).getColumnName().getText( + identifierGeneratorFactory.getDialect() + ) + ); + if ( entityBinding.getHierarchyDetails().getInheritanceType() != InheritanceType.TABLE_PER_CLASS ) { + params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); + } else { + params.setProperty( + PersistentIdentifierGenerator.TABLES, + resolveTableNames( identifierGeneratorFactory.getDialect(), entityBinding ) + ); + } + params.putAll( getIdentifierGeneratorDefinition().getParameters() ); + return identifierGeneratorFactory.createIdentifierGenerator( + getIdentifierGeneratorDefinition().getStrategy(), + getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(), + params + ); + } + } + + private class SimpleAttributeIdentifierBindingImpl extends EntityIdentifierBinding { + SimpleAttributeIdentifierBindingImpl( + SingularAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + super( SIMPLE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue ); + } + + } + + private String resolveTableNames(Dialect dialect, EntityBinding entityBinding) { + EntityBinding[] ebs = entityBinding.getPostOrderSubEntityBindingClosure(); + StringBuilder tableNames = new StringBuilder(); + String tbName = resolveTableName( dialect, entityBinding ); + if( StringHelper.isNotEmpty( tbName )){ + tableNames.append( tbName ); + } + + for ( EntityBinding eb : ebs ) { + tbName = resolveTableName( dialect, eb ); + if(StringHelper.isNotEmpty( tbName )){ + tableNames.append( ", " ).append( tbName ); + } + } + return tableNames.toString(); + } + + private String resolveTableName(Dialect dialect, EntityBinding entityBinding) { + TableSpecification tableSpecification = entityBinding.getPrimaryTable(); + if ( tableSpecification instanceof Table ) { + Table tb = (Table) tableSpecification; + if ( tb.isPhysicalTable() ) { + return tb.getTableName().toText( dialect ); + } + } + return null; + } + + private class AggregatedComponentIdentifierBindingImpl extends EntityIdentifierBinding { + AggregatedComponentIdentifierBindingImpl( + EmbeddedAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue) { + super( AGGREGATED_COMPOSITE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue ); + if ( ! identifierAttributeBinding.getEmbeddableBinding().isAggregated() ) { + throw new IllegalArgumentException( + String.format( + "identifierAttributeBinding must be an aggregated EmbeddedAttributeBinding: %s", + identifierAttributeBinding.getAttribute().getName() + ) + ); + } + } + + public IdentifierGenerator createIdentifierGenerator( + IdentifierGeneratorFactory factory, + Properties properties) { + if ( entityBinding.getSuperEntityBinding() != null ) { + throw new AssertionError( "Creating an identifier generator for a component on a subclass." ); + } + final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier(); + + final boolean hasCustomGenerator = ! "assigned".equals( getIdentifierGeneratorDefinition().getStrategy() ); + if ( hasCustomGenerator ) { + return super.createIdentifierGenerator( + factory, properties + ); + } + // IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the + // various scenarios for which we need to account here + // we have the "@EmbeddedId" / case + CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator = + new CompositeNestedGeneratedValueGenerator.GenerationContextLocator() { + public Serializable locateGenerationContext( SessionImplementor session, Object incomingObject) { + return session.getEntityPersister( entityBinding.getEntityName(), incomingObject ) + .getIdentifier( incomingObject, session ); + } + }; + // TODO: set up IdentifierGenerator for non-assigned sub-attributes + return new CompositeNestedGeneratedValueGenerator( locator ); + } + } + + private static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan { + private final String propertyName; + private final IdentifierGenerator subGenerator; + private final Setter injector; + + public ValueGenerationPlan( + String propertyName, + IdentifierGenerator subGenerator, + Setter injector) { + this.propertyName = propertyName; + this.subGenerator = subGenerator; + this.injector = injector; + } + + /** + * {@inheritDoc} + */ + public void execute(SessionImplementor session, Object incomingObject, Object injectionContext) { + final Object generatedValue = subGenerator.generate( session, incomingObject ); + injector.set( injectionContext, generatedValue, session.getFactory() ); + } + + public void registerPersistentGenerators(Map generatorMap) { + if ( PersistentIdentifierGenerator.class.isInstance( subGenerator ) ) { + generatorMap.put( ( (PersistentIdentifierGenerator) subGenerator ).generatorKey(), subGenerator ); + } + } + } + + private class NonAggregatedCompositeIdentifierBindingImpl extends EntityIdentifierBinding { + private final Class externalAggregatingClass; + private final String externalAggregatingPropertyAccessorName; + + NonAggregatedCompositeIdentifierBindingImpl( + EmbeddedAttributeBinding identifierAttributeBinding, + IdentifierGeneratorDefinition identifierGeneratorDefinition, + String unsavedValue, + Class externalAggregatingClass, + String externalAggregatingPropertyAccessorName) { + super( NON_AGGREGATED_COMPOSITE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue ); + if ( identifierAttributeBinding.getEmbeddableBinding().isAggregated() ) { + throw new IllegalArgumentException( + String.format( + "identifierAttributeBinding must be a non-aggregated EmbeddedAttributeBinding: %s", + identifierAttributeBinding.getAttribute().getName() + ) + ); + } + this.externalAggregatingClass = externalAggregatingClass; + this.externalAggregatingPropertyAccessorName = externalAggregatingPropertyAccessorName; + if ( identifierAttributeBinding.getEmbeddableBinding().attributeBindingSpan() == 0 ) { + throw new MappingException( + "A composite ID has 0 attributes for " + entityBinding.getEntityName() + ); + } + for ( AttributeBinding attributeBinding : identifierAttributeBinding.getEmbeddableBinding().attributeBindings() ) { + if ( ! attributeBinding.getAttribute().isSingular() ) { + throw new MappingException( + String.format( + "The composite ID for [%s] contains an attribute [%s} that is plural.", + entityBinding.getEntityName(), + attributeBinding.getAttribute().getName() + ) + ); + } + } + } + + private EmbeddedAttributeBinding getNonAggregatedCompositeAttributeBinding() { + return (EmbeddedAttributeBinding) getAttributeBinding(); + } + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + if ( !isIdentifierMapper() && getNonAggregatedCompositeAttributeBinding().equals( attributeBinding ) ) { + return true; + + } + for ( AttributeBinding idAttributeBindings : getNonAggregatedCompositeAttributeBinding().getEmbeddableBinding().attributeBindings() ) { + if ( idAttributeBindings.equals( attributeBinding ) ) { + return true; + } + } + return false; + } + + public Class getIdClassClass() { + return externalAggregatingClass; + } + + public String getIdClassPropertyAccessorName() { + return externalAggregatingPropertyAccessorName; + } + + public IdentifierGenerator createIdentifierGenerator( + IdentifierGeneratorFactory factory, + Properties properties) { + if ( entityBinding.getSuperEntityBinding() != null ) { + throw new AssertionError( "Creating an identifier generator for a component on a subclass." ); + } + // IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the + // various scenarios for which we need to account here + //if ( idClassClass != null ) { + // we have the @IdClass / case + // attributeDeclarer = idClassClass; + //} + //else { + // we have the "straight up" embedded (again the hibernate term) component identifier + // attributeDeclarer = entityClass; + //} + CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator = + new CompositeNestedGeneratedValueGenerator.GenerationContextLocator() { + public Serializable locateGenerationContext( SessionImplementor session, Object incomingObject) { + return session.getEntityPersister( entityBinding.getEntityName(), incomingObject ) + .getIdentifier( incomingObject, session ); + } + }; + // TODO: set up IdentifierGenerator for non-assigned sub-attributes + return new CompositeNestedGeneratedValueGenerator( locator ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java new file mode 100644 index 000000000000..ccd484a3248b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * @author Steve Ebersole + */ +public class EntityVersion { + private final EntityBinding rootEntityBinding; + private BasicAttributeBinding versioningAttributeBinding; + private String unsavedValue; + + public EntityVersion(EntityBinding rootEntityBinding) { + this.rootEntityBinding = rootEntityBinding; + } + + + public BasicAttributeBinding getVersioningAttributeBinding() { + return versioningAttributeBinding; + } + + public void setVersioningAttributeBinding(BasicAttributeBinding versioningAttributeBinding) { + this.versioningAttributeBinding = versioningAttributeBinding; + } + + public String getUnsavedValue() { + return unsavedValue; + } + + public void setUnsavedValue(String unsavedValue) { + this.unsavedValue = unsavedValue; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/FetchProfile.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/FetchProfile.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/FetchProfile.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/FetchProfile.java index 31b6d5dbc5d8..56f144a70f3c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/FetchProfile.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/FetchProfile.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.util.Collections; import java.util.Set; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Fetchable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Fetchable.java new file mode 100644 index 000000000000..17cd753f8ba9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Fetchable.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.FetchMode; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; + +/** + * @author Steve Ebersole + */ +public interface Fetchable { + public FetchMode getFetchMode(); + + public FetchTiming getFetchTiming(); + + public void setFetchTiming(FetchTiming fetchTiming); + + public FetchStyle getFetchStyle(); + + public void setFetchStyle(FetchStyle fetchStyle); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Filterable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Filterable.java new file mode 100644 index 000000000000..9ef4f9c6e6f9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Filterable.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.internal.FilterConfiguration; + +/** + * @author Strong Liu + */ +public interface Filterable { + public void addFilterConfiguration(FilterConfiguration filterConfiguration); + + public List getFilterConfigurations(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Helper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Helper.java new file mode 100644 index 000000000000..594788d9f234 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/Helper.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; + +/** + * Helper utilities specific to the binding package. + * + * @author Steve Ebersole + */ +public class Helper { + public static void checkPluralAttributeNature(PluralAttribute attribute, PluralAttributeNature expected) { + if ( attribute.getPluralAttributeNature() != expected ) { + throw new AssertionFailure( + String.format( + "Mismatched collection natures; expecting %s, but found %s", + expected.name(), + attribute.getPluralAttributeNature().name() + ) + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HibernateTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HibernateTypeDescriptor.java new file mode 100644 index 000000000000..fb4ef5a38320 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HibernateTypeDescriptor.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.type.Type; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class HibernateTypeDescriptor { + private String explicitTypeName; + private Map typeParameters = new HashMap( ); + + private Type resolvedTypeMapping; + private JavaTypeDescriptor typeDescriptor; + + public String getExplicitTypeName() { + return explicitTypeName; + } + + public void setExplicitTypeName(String explicitTypeName) { + this.explicitTypeName = explicitTypeName; + } + + public JavaTypeDescriptor getJavaTypeDescriptor() { + return typeDescriptor; + } + + public void setJavaTypeDescriptor(JavaTypeDescriptor typeDescriptor) { + this.typeDescriptor = typeDescriptor; + } + + public boolean isToOne() { + return resolvedTypeMapping.isEntityType(); + } + + public Map getTypeParameters() { + return typeParameters; + } + + public Type getResolvedTypeMapping() { + return resolvedTypeMapping; + } + + public void setResolvedTypeMapping(Type resolvedTypeMapping) { + this.resolvedTypeMapping = resolvedTypeMapping; + } + + public void copyFrom(HibernateTypeDescriptor hibernateTypeDescriptor) { + setJavaTypeDescriptor( hibernateTypeDescriptor.getJavaTypeDescriptor() ); + setExplicitTypeName( hibernateTypeDescriptor.getExplicitTypeName() ); + getTypeParameters().putAll( hibernateTypeDescriptor.getTypeParameters() ); + setResolvedTypeMapping( hibernateTypeDescriptor.getResolvedTypeMapping() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java new file mode 100644 index 000000000000..96605c59badb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java @@ -0,0 +1,235 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.EntityMode; +import org.hibernate.engine.OptimisticLockStyle; + +/** + * @author Steve Ebersole + */ +public class HierarchyDetails implements EntityHierarchy { + private final EntityBinding rootEntityBinding; + private final InheritanceType inheritanceType; + private final EntityIdentifier entityIdentifier; + private final EntityDiscriminator entityDiscriminator; + private final EntityVersion entityVersion; + + private final TenantDiscrimination tenantDiscrimination; + + private final EntityMode entityMode; + private final OptimisticLockStyle optimisticLockStyle; + + private final Caching caching; + private final Caching naturalIdCaching; + + private final boolean explicitPolymorphism; + private final boolean mutable; + private final String where; + + public HierarchyDetails( + EntityMode entityMode, + InheritanceType inheritanceType, + boolean isDiscriminated, + boolean isVersioned, + boolean isTenancyDiscriminated, + OptimisticLockStyle optimisticLockStyle, + Caching caching, + Caching naturalIdCaching, + boolean explicitPolymorphism, + boolean mutable, + String where) { + this.entityMode = entityMode; + this.inheritanceType = inheritanceType; + this.optimisticLockStyle = optimisticLockStyle; + this.caching = caching; + this.naturalIdCaching = naturalIdCaching; + this.explicitPolymorphism = explicitPolymorphism; + this.mutable = mutable; + this.where = where; + + this.rootEntityBinding = new EntityBinding( this ); + this.entityIdentifier = new EntityIdentifier( rootEntityBinding ); + + this.entityVersion = isVersioned ? new EntityVersion( rootEntityBinding ) : null; + this.entityDiscriminator = isDiscriminated ? new EntityDiscriminator() : null; + this.tenantDiscrimination = isTenancyDiscriminated ? new TenantDiscrimination() : null; + } + + @Override + public EntityBinding getRootEntityBinding() { + return rootEntityBinding; + } + + @Override + public InheritanceType getInheritanceType() { + return inheritanceType; + } + + @Override + public TenantDiscrimination getTenantDiscrimination() { + return tenantDiscrimination; + } + + @Override + public EntityMode getEntityMode() { + return entityMode; + } + + @Override + public EntityIdentifier getEntityIdentifier() { + return entityIdentifier; + } + + @Override + public EntityDiscriminator getEntityDiscriminator() { + return entityDiscriminator; + } + + @Override + public OptimisticLockStyle getOptimisticLockStyle() { + return optimisticLockStyle; + } + + + public boolean isVersioned() { + return getEntityVersion() != null; + } + + @Override + public EntityVersion getEntityVersion() { + return entityVersion; + } + + @Override + public Caching getCaching() { + return caching; + } + + @Override + public Caching getNaturalIdCaching() { + return naturalIdCaching; + } + + @Override + public boolean isMutable() { + return mutable; + } + + @Override + public boolean isExplicitPolymorphism() { + return explicitPolymorphism; + } + + @Override + public String getWhere() { + return where; + } + + public static class Builder { + private InheritanceType inheritanceType = InheritanceType.NO_INHERITANCE; + private EntityMode entityMode = EntityMode.POJO; + private OptimisticLockStyle optimisticLockStyle = OptimisticLockStyle.VERSION; + private Caching caching; + private Caching naturalIdCaching; + private boolean explicitPolymorphism; + private boolean mutable = true; + private String where; + + private boolean isDiscriminated; + private boolean isVersioned; + private boolean isTenancyDiscriminated; + + public Builder setInheritanceType(InheritanceType inheritanceType) { + this.inheritanceType = inheritanceType; + return this; + } + + public Builder setEntityMode(EntityMode entityMode) { + this.entityMode = entityMode; + return this; + } + + public Builder setOptimisticLockStyle(OptimisticLockStyle optimisticLockStyle) { + this.optimisticLockStyle = optimisticLockStyle; + return this; + } + + public Builder setCaching(Caching caching) { + this.caching = caching; + return this; + } + + public Builder setNaturalIdCaching(Caching naturalIdCaching) { + this.naturalIdCaching = naturalIdCaching; + return this; + } + + public Builder setExplicitPolymorphism(boolean explicitPolymorphism) { + this.explicitPolymorphism = explicitPolymorphism; + return this; + } + + public Builder setMutable(boolean mutable) { + this.mutable = mutable; + return this; + } + + public Builder setWhere(String where) { + this.where = where; + return this; + } + + public Builder setDiscriminated(boolean isDiscriminated) { + this.isDiscriminated = isDiscriminated; + return this; + } + + public Builder setVersioned(boolean isVersioned) { + this.isVersioned = isVersioned; + return this; + } + + public Builder setTenancyDiscriminated(boolean isTenancyDiscriminated) { + this.isTenancyDiscriminated = isTenancyDiscriminated; + return this; + } + + public HierarchyDetails createHierarchyDetails() { + return new HierarchyDetails( + entityMode, + inheritanceType, + isDiscriminated, + isVersioned, + isTenancyDiscriminated, + optimisticLockStyle, + caching, + naturalIdCaching, + explicitPolymorphism, + mutable, + where + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java new file mode 100644 index 000000000000..a071c40e5b35 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IdentifierGeneratorDefinition.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; + +import org.hibernate.internal.util.collections.CollectionHelper; + +/** + * Identifier generator definition, should be immutable. + * + * @author Emmanuel Bernard + * @author Strong Liu + */ +public class IdentifierGeneratorDefinition implements Serializable { + private final String name; + private final String strategy; + private final Map parameters; + + public IdentifierGeneratorDefinition( + final String name, + final String strategy, + final Map parameters) { + this.name = name; + this.strategy = strategy; + if ( CollectionHelper.isEmpty( parameters ) ) { + this.parameters = Collections.emptyMap(); + } + else { + this.parameters = Collections.unmodifiableMap( parameters ); + } + } + + /** + * @return identifier generator strategy + */ + public String getStrategy() { + return strategy; + } + + /** + * @return generator name + */ + public String getName() { + return name; + } + + /** + * @return generator configuration parameters + */ + public Map getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof IdentifierGeneratorDefinition ) ) { + return false; + } + + IdentifierGeneratorDefinition that = (IdentifierGeneratorDefinition) o; + + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( parameters != null ? !parameters.equals( that.parameters ) : that.parameters != null ) { + return false; + } + if ( strategy != null ? !strategy.equals( that.strategy ) : that.strategy != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( strategy != null ? strategy.hashCode() : 0 ); + result = 31 * result + ( parameters != null ? parameters.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "IdentifierGeneratorDefinition{" + + "name='" + name + '\'' + + ", strategy='" + strategy + '\'' + + ", parameters=" + parameters + + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java new file mode 100644 index 000000000000..ae9adcce286e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/IndexedPluralAttributeBinding.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * Specialization of plural attribute binding for indexed collections (maps and lists). + * + * @author Steve Ebersole + */ +public interface IndexedPluralAttributeBinding extends PluralAttributeBinding { + /** + * Retrieve the binding descriptor pertaining to the plural attribute's index value. + * + * @return The index binding descriptor + */ + public PluralAttributeIndexBinding getPluralAttributeIndexBinding(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/InheritanceType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/InheritanceType.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/InheritanceType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/InheritanceType.java index 9bcd4792cd76..3d55aff685b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/InheritanceType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/InheritanceType.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import org.hibernate.MappingException; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java new file mode 100644 index 000000000000..772d7c642501 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/JoinRelationalValueBindingContainer.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Gail Badner + */ +public class JoinRelationalValueBindingContainer extends RelationalValueBindingContainer { + private final TableSpecification table; + private final ForeignKey foreignKey; + + public JoinRelationalValueBindingContainer( + List relationalValueBindings, + ForeignKey foreignKey) { + super( relationalValueBindings ); + if ( relationalValueBindings.isEmpty() ) { + table = null; + } + else { + table = relationalValueBindings.get( 0 ).getTable(); + for ( int i = 1; i< relationalValueBindings.size(); i++ ) { + if ( !table.equals( relationalValueBindings.get( i ).getTable() ) ) { + throw new AssertionFailure( + String.format( + "Multiple tables found in a %s: %s, %s", + getClass().getName(), + table.getLogicalName(), + relationalValueBindings.get( i ).getTable() + ) + ); + } + } + } + if ( table != null && foreignKey != null && !table.equals( foreignKey.getSourceTable() ) ) { + throw new IllegalStateException( + String.format( + "Unexpected source table for foreign key: %s; expected %s.", + foreignKey.getSourceTable(), + table + ) + ); + } + this.foreignKey = foreignKey; + } + + public TableSpecification getTable() { + return table; + } + + public ForeignKey getForeignKey() { + return foreignKey; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java new file mode 100644 index 000000000000..77bf5a8a1612 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ListBinding.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; + +/** + * + */ +public class ListBinding extends AbstractPluralAttributeBinding implements IndexedPluralAttributeBinding { + + private final PluralAttributeIndexBinding pluralAttributeIndexBinding; + private final int base; + + public ListBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + int base) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( this ); + this.base = base; + } + + public int base() { + return base; + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding#getPluralAttributeIndexBinding() + */ + @Override + public PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + return pluralAttributeIndexBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java new file mode 100644 index 000000000000..fd70b1c78cdb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; + +/** + * TODO : javadoc + * + * @author Gail Badner + * @author Steve Ebersole + */ +public class ManyToOneAttributeBinding + extends AbstractSingularAssociationAttributeBinding { + + public ManyToOneAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + boolean isIgnoreNotFound, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + isIgnoreNotFound, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + referencedEntityBinding, + referencedAttributeBinding + ); + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java new file mode 100644 index 000000000000..02b98ae49cde --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MapBinding.java @@ -0,0 +1,100 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; + +/** + * + */ +public class MapBinding extends AbstractPluralAttributeBinding implements IndexedPluralAttributeBinding { + + private final PluralAttributeIndexBinding pluralAttributeIndexBinding; + + public MapBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + PluralAttributeIndexNature pluralAttributeIndexNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + pluralAttributeIndexBinding = createPluralAttributeIndexBinding( pluralAttributeIndexNature ); + } + + /** + * {@inheritDoc} + * + * @see org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding#getPluralAttributeIndexBinding() + */ + @Override + public PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + return pluralAttributeIndexBinding; + } + + private PluralAttributeIndexBinding createPluralAttributeIndexBinding(PluralAttributeIndexNature nature) { + switch ( nature ) { + case BASIC: { + return new BasicPluralAttributeIndexBinding( this ); + } + case AGGREGATE: { + return new CompositePluralAttributeIndexBinding( this ); + } + case MANY_TO_MANY: { + throw new NotYetImplementedException( + String.format( "%s index nature is not supported yet.", nature ) + ); + } + case MANY_TO_ANY: { + throw new NotYetImplementedException( + String.format( "%s index nature is not supported yet.", nature ) + ); + } + default: { + throw new AssertionFailure( "Unknown collection index nature : " + nature ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MetaAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MetaAttribute.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/binding/MetaAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MetaAttribute.java index 18babda0e31e..9930b16bd3e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MetaAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/MetaAttribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import java.io.Serializable; import java.util.ArrayList; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java new file mode 100644 index 000000000000..06a8894596f8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; + +/** + * TODO : javadoc + * + * @author Gail Badner + */ +public class OneToOneAttributeBinding + extends AbstractSingularAssociationAttributeBinding { + final boolean isConstrained; + + public OneToOneAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + NaturalIdMutability naturalIdMutability, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath, + EntityBinding referencedEntityBinding, + SingularAttributeBinding referencedAttributeBinding, + boolean isConstrained) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + false, + naturalIdMutability, + metaAttributeContext, + attributeRole, + attributePath, + referencedEntityBinding, + referencedAttributeBinding + ); + this.isConstrained = isConstrained; + } + + @Override + public boolean isNullable() { + return !isConstrained; + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java new file mode 100644 index 000000000000..dd58aa8f64c3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeAssociationElementBinding.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * Specialization of PluralAttributeElementBinding for elements which are association (entity) values. + * + * @author Steve Ebersole + */ +public interface PluralAttributeAssociationElementBinding + extends PluralAttributeElementBinding, Cascadeable { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java new file mode 100644 index 000000000000..68120b6789cf --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.Comparator; + +import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.persister.collection.CollectionPersister; + +/** + * Describes the binding of a plural attribute. + * + * @author Steve Ebersole + */ +public interface PluralAttributeBinding extends AttributeBinding, Fetchable, Filterable { + /** + * Retrieve the plural attribute being bound. + * + * @return The plural attribute descriptor + */ + @Override + public PluralAttribute getAttribute(); + + /** + * Retrieve the binding information pertaining to the collection (foreign) key. + * + * @return The key binding descriptor + */ + public PluralAttributeKeyBinding getPluralAttributeKeyBinding(); + + /** + * Retrieve the binding information pertaining to the collection elements. + * + * @return The element binding descriptor + */ + public PluralAttributeElementBinding getPluralAttributeElementBinding(); + + public boolean isMutable(); + + public Caching getCaching(); + + public Class getExplicitPersisterClass(); + + public String getCustomLoaderName(); + + public CustomSQL getCustomSqlInsert(); + + public CustomSQL getCustomSqlUpdate(); + + public CustomSQL getCustomSqlDelete(); + + public CustomSQL getCustomSqlDeleteAll(); + + String getWhere(); + + boolean isSorted(); + + boolean hasIndex(); + + Comparator getComparator(); + + int getBatchSize(); + + String getOrderBy(); + + String getReferencedPropertyName(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java new file mode 100644 index 000000000000..b32eda5fc931 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBinding.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + + +/** + * Common "descriptor" for describing the elements of a persistent collection. + * + * @author Steve Ebersole + */ +public interface PluralAttributeElementBinding { + /** + * Retrieves the plural attribute binding descriptor whose element binding is described here. + * + * @return The plural attribute binding descriptor. + */ + PluralAttributeBinding getPluralAttributeBinding(); + + /** + * Retrieves an enumeration describing the mapping nature of the collection's elements. + * + * @return The nature enum. + */ + PluralAttributeElementNature getNature(); + + /** + * Retrieve the Hibernate type descriptor describing the mapping-typing of the elements. + * + * @return The element type descriptor. + */ + HibernateTypeDescriptor getHibernateTypeDescriptor(); + + // not a fan of this, but for now... + + RelationalValueBindingContainer getRelationalValueContainer(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingBasic.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingBasic.java new file mode 100644 index 000000000000..f8cf003cb9d2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingBasic.java @@ -0,0 +1,78 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.PluralAttributeElementNature#BASIC} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementBindingBasic extends AbstractPluralAttributeElementBinding { + private RelationalValueBindingContainer relationalValueBindingContainer; + + public PluralAttributeElementBindingBasic(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.BASIC; + } + + @Override + public RelationalValueBindingContainer getRelationalValueContainer() { + return relationalValueBindingContainer; + } + + public void setRelationalValueBindings(List relationalValueBindings) { + this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindings ); + } + + + public List getValues() { + return getRelationalValueContainer().values(); + } + + public List getRelationalValueBindings() { + return getRelationalValueContainer().relationalValueBindings(); + } + + public boolean isNullable() { + return getRelationalValueContainer().hasNullableRelationalValueBinding(); + } + + public boolean hasDerivedValue() { + return getRelationalValueContainer().hasDerivedValue(); + } + + public boolean hasNonNullableValue() { + return getRelationalValueContainer().hasNonNullableRelationalValueBinding(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingEmbedded.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingEmbedded.java new file mode 100644 index 000000000000..0e8a6f045a19 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingEmbedded.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.tuple.component.ComponentTuplizer; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.PluralAttributeElementNature#AGGREGATE} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementBindingEmbedded + extends AbstractPluralAttributeElementBinding + implements Cascadeable, EmbeddableBindingContributor { + + private AbstractEmbeddableBinding embeddableBinding; + private CascadeStyle cascadeStyle; + + public PluralAttributeElementBindingEmbedded(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.AGGREGATE; + } + + @Override + public RelationalValueBindingContainer getRelationalValueContainer() { + return embeddableBinding.getRelationalValueBindingContainer(); + } + + @Override + public CascadeStyle getCascadeStyle() { + return cascadeStyle; + } + + @Override + public void setCascadeStyle(CascadeStyle cascadeStyle) { + this.cascadeStyle = cascadeStyle; + } + + @Override + public EmbeddableBinding getEmbeddableBinding() { + return embeddableBinding; + + } + + public EmbeddableBinding createBindingContainer( + Aggregate aggregate, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference, + Class tuplizerClass) { + if ( embeddableBinding != null ) { + throw new IllegalStateException( "EmbeddableBinding was already set" ); + } + + final boolean isMap = getPluralAttributeBinding().getAttribute().getPluralAttributeNature() + == PluralAttributeNature.MAP; + final String virtualAttributeName = isMap ? "value" : "element"; + + embeddableBinding = new AbstractEmbeddableBinding( + getPluralAttributeBinding().getContainer().seekEntityBinding(), + aggregate, + getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(), + getPluralAttributeBinding().getAttributeRole().append( virtualAttributeName ), + getPluralAttributeBinding().getAttributePath().append( virtualAttributeName ), + metaAttributeContext, + parentReference, + tuplizerClass) { + final Map attributeBindingMap = new LinkedHashMap(); + + @Override + protected boolean isModifiable() { + return true; + } + + @Override + protected Map attributeBindingMapInternal() { + return attributeBindingMap; + } + + @Override + public boolean isAggregated() { + return true; + } + }; + + return embeddableBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingManyToAny.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingManyToAny.java new file mode 100644 index 000000000000..cc6e133f844c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingManyToAny.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.PluralAttributeElementNature#MANY_TO_ANY} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementBindingManyToAny extends AbstractPluralAttributeAssociationElementBinding { + PluralAttributeElementBindingManyToAny(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public RelationalValueBindingContainer getRelationalValueContainer() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.MANY_TO_ANY; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingManyToMany.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingManyToMany.java new file mode 100644 index 000000000000..0ec48baa0421 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingManyToMany.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.FetchMode; +import org.hibernate.internal.FilterConfiguration; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.relational.ForeignKey; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.PluralAttributeElementNature#MANY_TO_MANY} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementBindingManyToMany extends AbstractPluralAttributeAssociationElementBinding implements Filterable{ + private List filterConfigurations = new ArrayList(); + private String manyToManyWhere; + private String manyToManyOrderBy; + private FetchMode fetchMode; + private JoinRelationalValueBindingContainer relationalValueBindingContainer; + + PluralAttributeElementBindingManyToMany(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public RelationalValueBindingContainer getRelationalValueContainer() { + return relationalValueBindingContainer; + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.MANY_TO_MANY; + } + + public void setJoinRelationalValueBindings( + List relationalValueBindings, + ForeignKey foreignKey) { + this.relationalValueBindingContainer = new JoinRelationalValueBindingContainer( + relationalValueBindings, + foreignKey + ); + } + + public ForeignKey getForeignKey() { + return relationalValueBindingContainer.getForeignKey(); + } + + public String getManyToManyWhere() { + return manyToManyWhere; + } + + public void setManyToManyWhere(String manyToManyWhere) { + this.manyToManyWhere = manyToManyWhere; + } + + public String getManyToManyOrderBy() { + return manyToManyOrderBy; + } + + public void setManyToManyOrderBy(String manyToManyOrderBy) { + this.manyToManyOrderBy = manyToManyOrderBy; + } + + public void setFetchMode(FetchMode fetchMode) { + this.fetchMode = fetchMode; + } + + @Override + public void addFilterConfiguration(FilterConfiguration filterConfiguration) { + filterConfigurations.add( filterConfiguration ); + } + + @Override + public List getFilterConfigurations() { + return filterConfigurations; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingOneToMany.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingOneToMany.java new file mode 100644 index 000000000000..7dbb80b90a36 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeElementBindingOneToMany.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.PluralAttributeElementNature; + +/** + * Describes plural attributes of {@link org.hibernate.metamodel.spi.PluralAttributeElementNature#ONE_TO_MANY} elements + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeElementBindingOneToMany extends AbstractPluralAttributeAssociationElementBinding { + private RelationalValueBindingContainer relationalValueBindingContainer; + + PluralAttributeElementBindingOneToMany(AbstractPluralAttributeBinding binding) { + super( binding ); + } + + @Override + public RelationalValueBindingContainer getRelationalValueContainer() { + return relationalValueBindingContainer; + } + + @Override + public PluralAttributeElementNature getNature() { + return PluralAttributeElementNature.ONE_TO_MANY; + } + + public void setElementEntityIdentifier(List relationalValueBindingList) { + this.relationalValueBindingContainer = new RelationalValueBindingContainer( relationalValueBindingList ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java new file mode 100644 index 000000000000..e7b03fbeb1b2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeIndexBinding.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.domain.Type; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +public interface PluralAttributeIndexBinding { + IndexedPluralAttributeBinding getIndexedPluralAttributeBinding(); + + PluralAttributeIndexNature getNature(); + + /** + * Retrieve the relational aspect of the index binding. Essentially describes the + * column(s)/derived value(s) to which the binding maps the indexes. + * + * @return The relational values. + */ + public List getRelationalValueBindings(); + + List getValues(); + + HibernateTypeDescriptor getHibernateTypeDescriptor(); + + Type getPluralAttributeIndexType(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java new file mode 100644 index 000000000000..230534669235 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java @@ -0,0 +1,151 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Describes the binding information pertaining to the plural attribute foreign key. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class PluralAttributeKeyBinding { + private final AbstractPluralAttributeBinding pluralAttributeBinding; + private final SingularAttributeBinding referencedAttributeBinding; + private JoinRelationalValueBindingContainer relationalValueBindingContainer; + private boolean inverse; + + // this knowledge can be implicitly resolved based on the typing information on the referenced owner attribute + private HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); + + +// todo : this would be nice to have but we do not always know it, especially in HBM case. +// private BasicAttributeBinding otherSide; + + + public PluralAttributeKeyBinding( + AbstractPluralAttributeBinding pluralAttributeBinding, + SingularAttributeBinding referencedAttributeBinding) { + this.pluralAttributeBinding = pluralAttributeBinding; + this.referencedAttributeBinding = referencedAttributeBinding; + } + + /** + * Identifies the plural attribute binding whose foreign key this class is describing. + * + * @return The plural attribute whose foreign key is being described + */ + public AbstractPluralAttributeBinding getPluralAttributeBinding() { + return pluralAttributeBinding; + } + + public SingularAttributeBinding getReferencedAttributeBinding() { + return referencedAttributeBinding; + } + + public TableSpecification getCollectionTable() { + return relationalValueBindingContainer.getTable(); + } + + /** + * Is the plural attribute considered inverse? + *

      + * NOTE: The "inverse-ness" of a plural attribute logically applies to it key. + * + * @return {@code true} indicates the plural attribute is inverse; {@code false} indicates is not. + */ + public boolean isInverse() { + return inverse; + } + + public void setInverse(boolean inverse) { + this.inverse = inverse; + } + + public HibernateTypeDescriptor getHibernateTypeDescriptor() { + return hibernateTypeDescriptor; + } + + public void setHibernateTypeDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) { + this.hibernateTypeDescriptor = hibernateTypeDescriptor; + } + + public List getRelationalValueBindings() { + return relationalValueBindingContainer.relationalValueBindings(); + } + + public List getValues() { + return relationalValueBindingContainer.values(); + } + public ForeignKey getForeignKey() { + return relationalValueBindingContainer.getForeignKey(); + } + public void setJoinRelationalValueBindings( + List relationalValueBindings, + ForeignKey foreignKey) { + if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) { + throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." ); + } + if ( this.relationalValueBindingContainer != null ) { + throw new AssertionFailure( "Relational value bindings have already initialized" ); + } + this.relationalValueBindingContainer = new JoinRelationalValueBindingContainer( + relationalValueBindings, + foreignKey + ); + if ( this.relationalValueBindingContainer.hasDerivedValue() ) { + throw new NotYetImplementedException( + "Derived values are not supported when creating a foreign key that targets columns." + ); + } + } + + public boolean isCascadeDeleteEnabled() { + return relationalValueBindingContainer.getForeignKey().getDeleteRule() == ForeignKey.ReferentialAction.CASCADE; + } + + public boolean isNullable() { + // cannot be nullable if the foreign key source columns are included in the primary key + // TODO: move this into RelationalValueBindingContainer. + if ( getCollectionTable().getPrimaryKey().getColumns().containsAll( relationalValueBindingContainer.columns() ) ) { + return false; + } + return relationalValueBindingContainer.hasNullableRelationalValueBinding(); + } + + public boolean isInsertable() { + return relationalValueBindingContainer.hasInsertableRelationalValueBinding(); + } + + public boolean isUpdatable() { + return relationalValueBindingContainer.hasUpdateableRelationalValueBinding(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java new file mode 100644 index 000000000000..95ae8145acec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Represents the binding information of a column/formula. + * + * Different from a {@link Value} because, while the {@link Value} exists only once in the relational model, + * that {@link Value} may be bound to multiple attributes. A {@link RelationalValueBinding} then tracks the + * information that is specific to each attribute's binding to that {@link Value}. + * + * @author Steve Ebersole + */ +public class RelationalValueBinding { + private final TableSpecification table; + private final Value value; + private final boolean includeInInsert; + private final boolean includeInUpdate; + private final boolean isDerived; + + public RelationalValueBinding(final TableSpecification table, final DerivedValue value) { + this.table = table; + this.value = value; + this.includeInInsert = false; + this.includeInUpdate = false; + this.isDerived = true; + } + + public RelationalValueBinding(final TableSpecification table, final Column value, final boolean includeInInsert, final boolean includeInUpdate) { + this.table = table; + this.value = value; + this.includeInInsert = includeInInsert; + this.includeInUpdate = includeInUpdate; + this.isDerived = false; + } + + public TableSpecification getTable() { + return table; + } + + /** + * Retrieve the relational value bound here. + * + * @return The relational value. + */ + public Value getValue() { + return value; + } + + /** + * Is the value bound here derived? Same as checking {@link #getValue()} as a {@link DerivedValue} + * + * @return {@code true} indicates the bound value is derived. + */ + public boolean isDerived() { + return isDerived; + } + + /** + * Is the value bound here nullable? + * + * @return {@code true} indicates the bound value is derived or a column not marked as non-null. + */ + public boolean isNullable() { + return isDerived() || ( (Column) value ).isNullable(); + } + + /** + * Is the value to be inserted as part of its binding here? + * + * @return {@code true} indicates the value should be included; {@code false} indicates it should not + */ + public boolean isIncludeInInsert() { + return includeInInsert; + } + + /** + * Is the value to be updated as part of its binding here? + * + * @return {@code true} indicates the value should be included; {@code false} indicates it should not + */ + public boolean isIncludeInUpdate() { + return includeInUpdate; + } + + @Override + public String toString() { + return "RelationalValueBinding{table=" + table.toLoggableString() + + ", value=" + value.toLoggableString() + + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java new file mode 100644 index 000000000000..907fc6770c91 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBindingContainer.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Gail Badner + */ +public class RelationalValueBindingContainer { + private final List relationalValueBindings; + private final boolean isListModifiable; + + public RelationalValueBindingContainer(List relationalValueBindings) { + this.relationalValueBindings = Collections.unmodifiableList( relationalValueBindings ); + this.isListModifiable = false; + } + + public RelationalValueBindingContainer() { + this.relationalValueBindings = new ArrayList(); + this.isListModifiable = true; + } + + public List relationalValueBindings() { + return isListModifiable ? + Collections.unmodifiableList( relationalValueBindings ) : + relationalValueBindings; + } + + public List values() { + final List values = new ArrayList( relationalValueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + values.add( relationalValueBinding.getValue() ); + } + return values; + } + + public List columns() { + final List columns = new ArrayList( relationalValueBindings.size() ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( !relationalValueBinding.isDerived() ) { + columns.add( (Column) relationalValueBinding.getValue() ); + } + } + return columns; + } + + void addRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) { + if ( !isListModifiable ) { + throw new IllegalStateException( "Cannot add relationalValueBindings because this object is unmodifiable." ); + } + relationalValueBindings.addAll( relationalValueBindingContainer.relationalValueBindings ); + } + + public boolean hasDerivedValue() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if (relationalValueBinding.isDerived() ) { + return true; + } + } + return false; + } + + public boolean hasNullableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.isNullable() ) { + return true; + } + } + return false; + } + + public boolean hasNonNullableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( !relationalValueBinding.isNullable() ) { + return true; + } + } + return false; + } + + public boolean hasInsertableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.isIncludeInInsert() ) { + return true; + } + } + return false; + } + + public boolean hasUpdateableRelationalValueBinding() { + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + if ( relationalValueBinding.isIncludeInUpdate() ) { + return true; + } + } + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java new file mode 100644 index 000000000000..deeaeeb209e7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SecondaryTable.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.engine.FetchStyle; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Steve Ebersole + */ +public class SecondaryTable { + private final TableSpecification secondaryTableReference; + private final ForeignKey foreignKeyReference; + private FetchStyle fetchStyle = FetchStyle.JOIN; + private boolean isInverse = false; + private boolean isOptional = true; + private boolean isCascadeDeleteEnabled; + private CustomSQL customInsert; + private CustomSQL customUpdate; + private CustomSQL customDelete; + + public SecondaryTable(TableSpecification secondaryTableReference, ForeignKey foreignKeyReference) { + this.secondaryTableReference = secondaryTableReference; + this.foreignKeyReference = foreignKeyReference; + } + + public TableSpecification getSecondaryTableReference() { + return secondaryTableReference; + } + + public ForeignKey getForeignKeyReference() { + return foreignKeyReference; + } + + public FetchStyle getFetchStyle() { + return fetchStyle; + } + + public void setFetchStyle(FetchStyle fetchStyle) { + this.fetchStyle = fetchStyle; + } + + public boolean isInverse() { + return isInverse; + } + + public void setInverse(boolean isInverse) { + this.isInverse = isInverse; + } + + public boolean isOptional() { + return isOptional; + } + + public void setOptional(boolean isOptional) { + this.isOptional = isOptional; + } + + public boolean isCascadeDeleteEnabled() { + return isCascadeDeleteEnabled; + } + + public void setCascadeDeleteEnabled(boolean isCascadeDeleteEnabled) { + this.isCascadeDeleteEnabled = isCascadeDeleteEnabled; + } + public boolean isLazy() { + // TODO: need to check attribute bindings using this table + return false; + } + + public CustomSQL getCustomDelete() { + return customDelete; + } + + public void setCustomDelete(CustomSQL customDelete) { + this.customDelete = customDelete; + } + + public CustomSQL getCustomInsert() { + return customInsert; + } + + public void setCustomInsert(CustomSQL customInsert) { + this.customInsert = customInsert; + } + + public CustomSQL getCustomUpdate() { + return customUpdate; + } + + public void setCustomUpdate(CustomSQL customUpdate) { + this.customUpdate = customUpdate; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java new file mode 100644 index 000000000000..9d76571926f8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.source.spi.MetaAttributeContext; +import org.hibernate.metamodel.spi.AttributePath; +import org.hibernate.metamodel.spi.AttributeRole; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.domain.PluralAttribute; + +/** + * @author Steve Ebersole + */ +public class SetBinding extends AbstractPluralAttributeBinding { + + public SetBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + SingularAttributeBinding referencedAttributeBinding, + String propertyAccessorName, + boolean includedInOptimisticLocking, + MetaAttributeContext metaAttributeContext, + AttributeRole attributeRole, + AttributePath attributePath) { + super( + container, + attribute, + pluralAttributeElementNature, + referencedAttributeBinding, + propertyAccessorName, + includedInOptimisticLocking, + metaAttributeContext, + attributeRole, + attributePath + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAssociationAttributeBinding.java new file mode 100644 index 000000000000..c83cbc05adf4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAssociationAttributeBinding.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * Contract describing the attribute binding for singular associations ({@code many-to-one}, {@code one-to-one}). + * + * @author Gail Badner + * @author Steve Ebersole + */ +@SuppressWarnings( {"JavaDoc", "UnusedDeclaration"}) +public interface SingularAssociationAttributeBinding extends SingularAttributeBinding, Cascadeable, Fetchable { + /** + * Obtain the name of the referenced entity. + * + * @return The referenced entity name + */ + public String getReferencedEntityName(); + + public EntityBinding getReferencedEntityBinding(); + + public SingularAttributeBinding getReferencedAttributeBinding(); + + public boolean isIgnoreNotFound(); + + public TableSpecification getTable(); + + public ForeignKey getForeignKey(); +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java new file mode 100644 index 000000000000..a3910bb91b91 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java @@ -0,0 +1,93 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.List; + +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Value; + +/** + * Specialized binding contract for singular (non-collection) attributes + * + * @author Steve Ebersole + */ +public interface SingularAttributeBinding extends AttributeBinding { + + @Override + public SingularAttribute getAttribute(); + + public List getRelationalValueBindings(); + + public List getValues(); + /** + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} are derived values + * (formula mappings). + * + * @return {@code true} indicates that the binding contains a derived value; {@code false} indicates it does not. + */ + public boolean hasDerivedValue(); + + /** + * Convenience method to determine if all {@link RelationalValueBinding simple value bindings} allow nulls. + * + * @return {@code true} indicates that all values allow {@code null}; {@code false} indicates one or more do not. + */ + public boolean isNullable(); + + /** + * Convenience method to determine if all tables (primary and secondary) involved with this attribute + * binding are optional. + * + * @return true, if all tables involved with this attribute are optional; false, otherwise. + */ + public boolean isOptional(); + + /** + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} are inserted. + * + * @return {@code true} indicates that at least one value is inserted; {@code false} indicates none are inserted. + */ + public boolean isIncludedInInsert(); + + /** + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} can be updated. + * + * @return {@code true} indicates that at least one value can be updated; {@code false} indicates none can + * be updated. + */ + public boolean isIncludedInUpdate(); + + /** + * Convenience method to determine if this attribute is an natural id and if it is, then returns its mutability. + * + * @return The {@link org.hibernate.metamodel.spi.NaturalIdMutability} linked with this attribute, + * {@code NaturalIdMutability#NOT_NATURAL_ID} indicates this is NOT a natural id attribute. + */ + public NaturalIdMutability getNaturalIdMutability(); + + public void setAlternateUniqueKey(boolean alternateUniqueKey); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularNonAssociationAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularNonAssociationAttributeBinding.java new file mode 100644 index 000000000000..f8c29d086b4a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularNonAssociationAttributeBinding.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +/** + * @author Steve Ebersole + */ +public interface SingularNonAssociationAttributeBinding extends SingularAttributeBinding { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java new file mode 100644 index 000000000000..2c9f8cf1b880 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TenantDiscrimination.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.relational.Value; + +/** + * @author Steve Ebersole + */ +public class TenantDiscrimination { + private Value discriminatorValue; + private boolean isShared = false; + private boolean useParameterBinding = true; + + public Value getDiscriminatorValue() { + return discriminatorValue; + } + + public void setDiscriminatorValue(Value discriminatorValue) { + this.discriminatorValue = discriminatorValue; + } + + public boolean isShared() { + return isShared; + } + + public void setShared(boolean shared) { + isShared = shared; + } + + public boolean isUseParameterBinding() { + return useParameterBinding; + } + + public void setUseParameterBinding(boolean useParameterBinding) { + this.useParameterBinding = useParameterBinding; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java new file mode 100644 index 000000000000..6a509b674dfa --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/TypeDefinition.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; + +/** + * Describes custom type definitions supplied by the user as part of the metadata. + * + * @author John Verhaeg + */ +public class TypeDefinition implements Serializable { + private final String name; + private final Class typeImplementorClass; + private final String[] registrationKeys; + private final Map parameters; + + public TypeDefinition( + String name, + Class typeImplementorClass, + String[] registrationKeys, + Map parameters) { + this.name = name; + this.typeImplementorClass = typeImplementorClass; + this.registrationKeys= registrationKeys; + this.parameters = parameters == null ? Collections.emptyMap() : Collections.unmodifiableMap( + parameters + ); + } + + public String getName() { + return name; + } + + public Class getTypeImplementorClass() { + return typeImplementorClass; + } + + public String[] getRegistrationKeys() { + return registrationKeys; + } + + public Map getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof TypeDefinition ) ) { + return false; + } + + TypeDefinition that = (TypeDefinition) o; + + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + if ( parameters != null ? !parameters.equals( that.parameters ) : that.parameters != null ) { + return false; + } + if ( !Arrays.equals( registrationKeys, that.registrationKeys ) ) { + return false; + } + if ( typeImplementorClass != null ? !typeImplementorClass.equals( that.typeImplementorClass ) : that.typeImplementorClass != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( typeImplementorClass != null ? typeImplementorClass.hashCode() : 0 ); + result = 31 * result + ( registrationKeys != null ? Arrays.hashCode( registrationKeys ) : 0 ); + result = 31 * result + ( parameters != null ? parameters.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "TypeDefinition{" + + "name='" + name + '\'' + + ", typeImplementorClass=" + typeImplementorClass + + ", registrationKeys=" + Arrays.toString( registrationKeys ) + + ", parameters=" + parameters + + '}'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java new file mode 100644 index 000000000000..7a088a082ba9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java @@ -0,0 +1,318 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * Convenient base class for {@link AttributeContainer}. Because in our model all + * {@link AttributeContainer AttributeContainers} are also {@link Hierarchical} we also implement that here + * as well. + * + * @author Steve Ebersole + */ +public abstract class AbstractAttributeContainer implements AttributeContainer, Hierarchical { + private final JavaTypeDescriptor typeDescriptor; + private final Hierarchical superType; + + private LinkedHashSet attributeSet = new LinkedHashSet(); + private HashMap attributeMap = new HashMap(); + + public AbstractAttributeContainer(JavaTypeDescriptor typeDescriptor, Hierarchical superType) { + this.typeDescriptor = typeDescriptor; + this.superType = superType; + } + + @Override + public String getName() { + return typeDescriptor.getName().toString(); + } + + @Override + public String getRoleBaseName() { + return getName(); + } + + @Override + public JavaTypeDescriptor getDescriptor() { + return typeDescriptor; + } + + @Override + public Hierarchical getSuperType() { + return superType; + } + + @Override + public Set attributes() { + return Collections.unmodifiableSet( attributeSet ); + } + + @Override + public Attribute locateAttribute(String name) { + return attributeMap.get( name ); + } + + @Override + public SingularAttribute locateSingularAttribute(String name) { + return (SingularAttribute) locateAttribute( name ); + } + + @Override + public SingularAttribute locateCompositeAttribute(String name) { + return (SingularAttributeImpl) locateAttribute( name ); + } + + @Override + public PluralAttribute locatePluralAttribute(String name) { + return (PluralAttribute) locateAttribute( name ); + } + + @Override + public PluralAttribute locateBag(String name) { + return locatePluralAttribute( name ); + } + + @Override + public PluralAttribute locateSet(String name) { + return locatePluralAttribute( name ); + } + + @Override + public IndexedPluralAttribute locateList(String name) { + return (IndexedPluralAttribute) locatePluralAttribute( name ); + } + + @Override + public IndexedPluralAttribute locateMap(String name) { + return (IndexedPluralAttribute) locatePluralAttribute( name ); + } + + @Override + public String toString() { + return "AbstractAttributeContainer" + "{name='" + getName() + "', superType=" + superType + '}'; + } + + + @Override + public SingularAttribute createSyntheticSingularAttribute(String name) { + SingularAttribute attribute = new SingularAttributeImpl( this, name, true ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical type) { + SingularAttributeImpl attribute = new SingularAttributeImpl( this, name, true ); + attribute.resolveType( type ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createSingularAttribute(String name) { + SingularAttribute attribute = new SingularAttributeImpl( this, name, false ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createCompositeAttribute(String name, Aggregate composite) { + SingularAttributeImpl attribute = new SingularAttributeImpl( this, name, false ); + attribute.resolveType( composite ); + addAttribute( attribute ); + return attribute; + } + + @Override + public PluralAttribute createBag(String name) { + return createPluralAttribute( name, PluralAttributeNature.BAG ); + } + + protected PluralAttribute createPluralAttribute(String name, PluralAttributeNature pluralAttributeNature) { + PluralAttribute attribute = pluralAttributeNature.isIndexed() + ? new IndexedPluralAttributeImpl( this, name, pluralAttributeNature ) + : new PluralAttributeImpl( this, name, pluralAttributeNature ); + addAttribute( attribute ); + return attribute; + } + + @Override + public PluralAttribute createSet(String name) { + return createPluralAttribute( name, PluralAttributeNature.SET ); + } + + @Override + public IndexedPluralAttribute createList(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.LIST ); + } + + @Override + public IndexedPluralAttribute createArray(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.ARRAY ); + } + + @Override + public IndexedPluralAttribute createMap(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.MAP ); + } + + protected void addAttribute(Attribute attribute) { + if ( attributeMap.put( attribute.getName(), attribute ) != null ) { + throw new IllegalArgumentException( "Attribute with name [" + attribute.getName() + "] already registered" ); + } + attributeSet.add( attribute ); + } + + // todo : inner classes for now.. + + public static class SingularAttributeImpl implements SingularAttribute { + private final AttributeContainer attributeContainer; + private final String name; + private final boolean synthetic; + private Type type; + + public SingularAttributeImpl(AttributeContainer attributeContainer, String name, boolean synthetic) { + this.attributeContainer = attributeContainer; + this.name = name; + this.synthetic = synthetic; + } + + public boolean isTypeResolved() { + return type != null; + } + + public void resolveType(Type type) { + if ( type == null ) { + throw new IllegalArgumentException( "Attempt to resolve with null type" ); + } + this.type = type; + } + + @Override + public Type getSingularAttributeType() { + return type; + } + + @Override + public String getName() { + return name; + } + + @Override + public AttributeContainer getAttributeContainer() { + return attributeContainer; + } + + @Override + public boolean isSingular() { + return true; + } + + @Override + public boolean isSynthetic() { + return synthetic; + } + } + + public static class PluralAttributeImpl implements PluralAttribute { + private final AttributeContainer attributeContainer; + private final PluralAttributeNature pluralAttributeNature; + private final String name; + + private Type elementType; + + public PluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, PluralAttributeNature pluralAttributeNature) { + this.attributeContainer = attributeContainer; + this.name = name; + this.pluralAttributeNature = pluralAttributeNature; + } + + @Override + public AttributeContainer getAttributeContainer() { + return attributeContainer; + } + + @Override + public boolean isSingular() { + return false; + } + + @Override + public boolean isSynthetic() { + // don't think there are ever any synthetic plural attributes created... + return false; + } + + @Override + public PluralAttributeNature getPluralAttributeNature() { + return pluralAttributeNature; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getRole() { + return StringHelper.qualify( attributeContainer.getRoleBaseName(), name ); + } + + @Override + public Type getElementType() { + return elementType; + } + + @Override + public void setElementType(Type elementType) { + this.elementType = elementType; + } + } + + public static class IndexedPluralAttributeImpl extends PluralAttributeImpl implements IndexedPluralAttribute { + private Type indexType; + + public IndexedPluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, PluralAttributeNature pluralAttributeNature) { + super( attributeContainer, name, pluralAttributeNature ); + } + + @Override + public Type getIndexType() { + return indexType; + } + + @Override + public void setIndexType(Type indexType) { + this.indexType = indexType; + } + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Aggregate.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Aggregate.java new file mode 100644 index 000000000000..a866e9a66261 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Aggregate.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Models the notion of an aggregated composite (what JPA calls an Embeddable). + *

      + * NOTE : Composites are not currently really hierarchical. But that is a feature I want to add. + * + * @author Steve Ebersole + */ +public class Aggregate extends AbstractAttributeContainer { + public Aggregate(JavaTypeDescriptor typeDescriptor, Hierarchical superType) { + super( typeDescriptor, superType ); + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + public boolean isAggregate() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Attribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java similarity index 75% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Attribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java index c58bd8778f66..5c3930b84567 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Attribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * Describes an attribute. @@ -37,7 +37,7 @@ public interface Attribute { public String getName(); /** - * Retrieve the declaring container for this attribute (entity/component). + * Retrieve the declaring container for this attribute (entity or aggregated composite). * * @return The attribute container. */ @@ -52,4 +52,13 @@ public interface Attribute { * @return True if attribute is singular; false if plural. */ public boolean isSingular(); + + /** + * Synthetic attributes do not really exist in the users domain classes. Hibernate sometimes generates these + * synthetic attributes for various reasons. Some parts of the code base use the phrase "virtual" as well. + * + * @return {@code true} indicates this attribute is synthetic; {@code false} indicates it is non-synthetic + * (an actual attribute). + */ + public boolean isSynthetic(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/AttributeContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java index 6024c758e432..b512852e50e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/AttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java @@ -21,13 +21,13 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; import java.util.Set; /** * Basic contract for any container holding attributes. This allows polymorphic handling of both - * components and entities in terms of the attributes they hold. + * aggregated composites and entities in terms of the attributes they hold. * * @author Steve Ebersole */ @@ -42,6 +42,13 @@ public interface AttributeContainer extends Type { */ public String getRoleBaseName(); + /** + * Retrieve the attributes contained in this container. + * + * @return The contained attributes + */ + public Set attributes(); + /** * Retrieve an attribute by name. * @@ -50,33 +57,22 @@ public interface AttributeContainer extends Type { * @return The attribute matching the given name, or null. */ public Attribute locateAttribute(String name); - - /** - * Retrieve the attributes contained in this container. - * - * @return The contained attributes - */ - public Set attributes(); - public SingularAttribute locateSingularAttribute(String name); - public SingularAttribute createSingularAttribute(String name); - public SingularAttribute createVirtualSingularAttribute(String name); - - public SingularAttribute locateComponentAttribute(String name); - public SingularAttribute createComponentAttribute(String name, Component component); - + public SingularAttribute locateCompositeAttribute(String name); public PluralAttribute locatePluralAttribute(String name); - public PluralAttribute locateBag(String name); - public PluralAttribute createBag(String name); - public PluralAttribute locateSet(String name); - public PluralAttribute createSet(String name); - public IndexedPluralAttribute locateList(String name); - public IndexedPluralAttribute createList(String name); - public IndexedPluralAttribute locateMap(String name); + + public SingularAttribute createSingularAttribute(String name); + public SingularAttribute createCompositeAttribute(String name, Aggregate composite); + public PluralAttribute createBag(String name); + public PluralAttribute createSet(String name); + public IndexedPluralAttribute createList(String name); public IndexedPluralAttribute createMap(String name); + public IndexedPluralAttribute createArray(String name); + public SingularAttribute createSyntheticSingularAttribute(String name); + public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical container); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/BasicType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/BasicType.java new file mode 100644 index 000000000000..5cbdbf460860 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/BasicType.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Models a basic type. + * + * @author Steve Ebersole + */ +public class BasicType implements Type { + private final String name; + private final JavaTypeDescriptor typeDescriptor; + + public BasicType(String name, JavaTypeDescriptor typeDescriptor) { + this.name = name; + this.typeDescriptor = typeDescriptor; + } + + public BasicType(JavaTypeDescriptor typeDescriptor) { + this( typeDescriptor.getName().toString(), typeDescriptor ); + } + + @Override + public String getName() { + return name; + } + + @Override + public JavaTypeDescriptor getDescriptor() { + return typeDescriptor; + } + + @Override + public boolean isAssociation() { + return false; + } + + @Override + public boolean isAggregate() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Entity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Entity.java new file mode 100644 index 000000000000..982affc480da --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Entity.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in nthe hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Models the notion of an entity + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public class Entity extends AbstractAttributeContainer implements IdentifiableType { + /** + * Constructor for the entity + * + * @param typeDescriptor The reflite {@link org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor} describing this entity's class + * @param superType The super type for this entity. If there is not super type {@code null} needs to be passed. + */ + public Entity(JavaTypeDescriptor typeDescriptor, Hierarchical superType) { + super( typeDescriptor, superType ); + } + + /** + * {@inheritDoc} + *

      + * Specifically here we are returning the name of the java type. This is + * not (usually) the same as the entity-name. + */ + @Override + public String getName() { + return super.getName(); + } + + @Override + public boolean isAssociation() { + return true; + } + + @Override + public boolean isAggregate() { + return false; + } + + @Override + public String getRoleBaseName() { + return getName(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Hierarchical.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Hierarchical.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/Hierarchical.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Hierarchical.java index fd587b0a1f88..29eb0ba00085 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/Hierarchical.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Hierarchical.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * Additional contract for things that can occur in an inheritance hierarchy (specifically ones we would diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IdentifiableType.java new file mode 100644 index 000000000000..aae5b3a16505 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IdentifiableType.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +/** + * Borrowing the JPA term again, this represents an Entity or MappedSuperclass + * + * @author Steve Ebersole + */ +public interface IdentifiableType extends Hierarchical { +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/IndexedPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IndexedPluralAttribute.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/IndexedPluralAttribute.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IndexedPluralAttribute.java index 5a15664925d4..aea4f1f85933 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/IndexedPluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/IndexedPluralAttribute.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * TODO : javadoc diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/JavaClassReference.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/JavaClassReference.java new file mode 100644 index 000000000000..8f011723a6ad --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/JavaClassReference.java @@ -0,0 +1,99 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.util.ValueHolder; + +/** + * Models the naming of a Java type where we may not have access to that type's {@link Class} reference. Generally + * speaking this is the case in various hibernate-tools and reverse-engineering use cases. + * + * @author Steve Ebersole + */ +public class JavaClassReference { + + // ClassLoaderService.classForName( className ) does not work for primitives, so add mapping + // from primitive class names -> class. + private static final Map> primitiveClassesByName = new HashMap>(); + static { + primitiveClassesByName.put("int", Integer.TYPE ); + primitiveClassesByName.put( "long", Long.TYPE ); + primitiveClassesByName.put( "double", Double.TYPE ); + primitiveClassesByName.put( "float", Float.TYPE ); + primitiveClassesByName.put( "bool", Boolean.TYPE ); + primitiveClassesByName.put( "char", Character.TYPE ); + primitiveClassesByName.put( "byte", Byte.TYPE ); + primitiveClassesByName.put( "void", Void.TYPE ); + primitiveClassesByName.put( "short", Short.TYPE ); + } + private final String name; + private final ValueHolder> classHolder; + + public JavaClassReference(final String name, final ClassLoaderService classLoaderService) { + if ( name == null || classLoaderService == null ) { + throw new IllegalArgumentException( "name and classLoaderService must be non-null." ); + } + this.name = name; + + final Class primitiveClass = primitiveClassesByName.get( name ); + if ( primitiveClass != null ) { + this.classHolder = new ValueHolder>( primitiveClass ); + } + else { + this.classHolder = new ValueHolder>( + new ValueHolder.DeferredInitializer>() { + @Override + public Class initialize() { + return classLoaderService.classForName( name ); + } + } + ); + } + } + + public JavaClassReference(Class theClass) { + if ( theClass == null ) { + throw new IllegalArgumentException( "theClass must be non-null." ); + } + this.name = theClass.getName(); + this.classHolder = new ValueHolder>( theClass ); + } + + public String getName() { + return name; + } + + public Class getResolvedClass() { + return classHolder.getValue(); + } + + @Override + public String toString() { + return super.toString() + "[name=" + name + "]"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/MappedSuperclass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/MappedSuperclass.java new file mode 100644 index 000000000000..b3b84d880556 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/MappedSuperclass.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Models the concept of a (intermediate) superclass + * + * @author Steve Ebersole + */ +public class MappedSuperclass extends AbstractAttributeContainer implements IdentifiableType { + /** + * Constructor for the entity + * + * @param typeDescriptor The descriptor of this entity's {@link Class} + * @param superType The super type for this entity. If there is not super type {@code null} needs to be passed. + */ + public MappedSuperclass(JavaTypeDescriptor typeDescriptor, Hierarchical superType) { + super( typeDescriptor, superType ); + } + + @Override + public boolean isAssociation() { + return true; + } + + @Override + public boolean isAggregate() { + return false; + } + + @Override + public String getRoleBaseName() { + return getName(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java new file mode 100644 index 000000000000..6082fcf3ebb8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/PluralAttribute.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import org.hibernate.metamodel.spi.PluralAttributeNature; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public interface PluralAttribute extends Attribute { + public String getRole(); + public PluralAttributeNature getPluralAttributeNature(); + public Type getElementType(); + public void setElementType(Type elementType); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/SingularAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/SingularAttribute.java new file mode 100644 index 000000000000..2ee54b86cb54 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/SingularAttribute.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +/** + * A single valued (non-collection) attribute + * + * @author Steve Ebersole + */ +public interface SingularAttribute extends Attribute { + /** + * Retrieve the attribute type descriptor. + * + * @return THe attribute type. + */ + public Type getSingularAttributeType(); + + public boolean isTypeResolved(); + + public void resolveType(Type type); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Type.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Type.java new file mode 100644 index 000000000000..ed85fe5328f3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Type.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.domain; + +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; + +/** + * Describes a "Java type" within a domain model. This concept builds on top of the + * lower level {@link org.hibernate.metamodel.reflite} typing model applying more + * O/RM semantics (like what is an entity, a composite, etc). + * + * @author Steve Ebersole + */ +public interface Type { + /** + * Obtain the name of the type. + * + * @return The name + */ + public String getName(); + + /** + * Is this attribute an aggregated composite (what JPA calls an Embeddable)? + * + * @return {@code true}, if this attribute is an aggregated composite; {@code false}, otherwise. + */ + public boolean isAggregate(); + + /** + * Access the {@link org.hibernate.metamodel.reflite} descriptor corresponding to this + * domain model type. + * + * @return The corresponding {@link org.hibernate.metamodel.reflite} JavaTypeDescriptor + */ + public JavaTypeDescriptor getDescriptor(); + + /** + * @deprecated This belongs on the attribute, not on its type. + */ + @Deprecated + public boolean isAssociation(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/TypeNature.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/TypeNature.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/TypeNature.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/TypeNature.java index 09350d2a806e..21ce86494e9b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/TypeNature.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/TypeNature.java @@ -21,16 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.domain; +package org.hibernate.metamodel.spi.domain; /** * Describes the type of a type :/ * + * todo: this is not currently used; is it needed? + * * @author Steve Ebersole */ public enum TypeNature { BASIC( "basic" ), - COMPONENT( "component" ), + AGGREGATE( "aggregate" ), ENTITY( "entity" ), SUPERCLASS( "superclass" ), NON_ENTITY( "non-entity" ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/domain/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/package.html similarity index 100% rename from hibernate-core/src/main/java/org/hibernate/metamodel/domain/package.html rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/package.html diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractAuxiliaryDatabaseObject.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractAuxiliaryDatabaseObject.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractAuxiliaryDatabaseObject.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractAuxiliaryDatabaseObject.java index 8b2b58c0a63a..7ea0f5421bcd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractAuxiliaryDatabaseObject.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractAuxiliaryDatabaseObject.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.HashSet; import java.util.Set; @@ -46,9 +46,15 @@ public abstract class AbstractAuxiliaryDatabaseObject implements AuxiliaryDataba private static final AtomicInteger counter = new AtomicInteger( 0 ); private final String exportIdentifier; private final Set dialectScopes; + private boolean beforeTablesOnCreation; protected AbstractAuxiliaryDatabaseObject(Set dialectScopes) { + this( dialectScopes, false ); + } + + protected AbstractAuxiliaryDatabaseObject(Set dialectScopes, boolean beforeTablesOnCreation) { this.dialectScopes = dialectScopes == null ? new HashSet() : dialectScopes; + this.beforeTablesOnCreation = beforeTablesOnCreation; this.exportIdentifier = new StringBuilder( EXPORT_IDENTIFIER_PREFIX ) .append( '.' ) @@ -73,4 +79,9 @@ public boolean appliesToDialect(Dialect dialect) { public String getExportIdentifier() { return exportIdentifier; } + + @Override + public boolean beforeTablesOnCreation() { + return beforeTablesOnCreation; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java new file mode 100644 index 000000000000..eac97f338eec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java @@ -0,0 +1,182 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.internal.util.StringHelper; + +/** + * Support for writing {@link Constraint} implementations + * + * @todo do we need to support defining these on particular schemas/catalogs? + * + * @author Steve Ebersole + * @author Gail Badner + * @author Brett Meyer + */ +public abstract class AbstractConstraint implements Constraint { + private TableSpecification table; + private Identifier name; + private final Map columnMap = new LinkedHashMap(); + private final Map columnOrderMap = new HashMap(); + + protected AbstractConstraint(TableSpecification table, Identifier name) { + this.table = table; + this.name = name; + } + + @Override + public TableSpecification getTable() { + return table; + } + + public void setTable( TableSpecification table ) { + this.table = table; + } + + /** + * Returns the constraint name, or null if the name has not been set. + * + * @return the constraint name, or null if the name has not been set + */ + public Identifier getName() { + return name; + } + + /** + * Sets a constraint name that is unique across + * all database objects. + * + * @param name - the unique constraint name; must be non-null. + * + * @throws IllegalArgumentException if name is null. + * @throws IllegalStateException if this constraint already has a non-null name. + */ + public void setName(Identifier name) { + if ( name == null ) { + throw new IllegalArgumentException( "name must be non-null." ); + } + if ( this.name != null ) { + throw new IllegalStateException( + String.format( + "This constraint already has a name (%s) and cannot be renamed to (%s).", + this.name, + name + ) + ); + } + this.name = name; + } + + public int columnListId() { + return table.columnListId( getColumns() ); + } + + public int columnListAlphabeticalId() { + List alphabeticalColumns = new ArrayList( columnMap.values() ); + Collections.sort( alphabeticalColumns, alphabeticalColumnComparator ); + return table.columnListId( Collections.unmodifiableList( alphabeticalColumns ) ); + } + + public List getColumns() { + return Collections.unmodifiableList( new ArrayList( columnMap.values() ) ); + } + + public String getColumnNames() { + StringBuilder sb = new StringBuilder(); + String sep = ""; + for (Column column : columnMap.values()) { + sb.append( column.getColumnName().getText() ); + sb.append( sep ); + sep = ", "; + } + return sb.toString(); + } + + public int getColumnSpan() { + return columnMap.size(); + } + + public boolean hasColumn(Column column) { + return columnMap.containsKey( column.getColumnName() ); + } + + public boolean hasColumn(String columnName) { + for ( Identifier key : columnMap.keySet() ) { + if ( key.getText().equals( columnName ) ) return true; + } + return false; + } + + protected Map internalColumnAccess() { + return columnMap; + } + + public void addColumn(Column column) { + internalAddColumn( column ); + } + + protected void internalAddColumn(Column column) { +// if ( column.getTable() != getTable() ) { +// throw new AssertionFailure( +// String.format( +// "Unable to add column to constraint; tables [%s, %s] did not match", +// column.getTable().toLoggableString(), +// getTable().toLoggableString() +// ) +// ); +// } + columnMap.put( column.getColumnName(), column ); + } + + public void addColumn(Column column, String order) { + addColumn( column ); + if ( StringHelper.isNotEmpty( order ) ) { + columnOrderMap.put( column, order ); + } + } + + public boolean hasOrdering(Column column) { + return columnOrderMap.containsKey( column ); + } + + public String getOrdering(Column column) { + return columnOrderMap.get( column ); + } + + private final static AlphabeticalColumnComparator alphabeticalColumnComparator = new AlphabeticalColumnComparator(); + private static class AlphabeticalColumnComparator implements Comparator { + @Override + public int compare(Column c1, Column c2) { + return c1.getColumnName().compareTo( c2.getColumnName() ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java new file mode 100644 index 000000000000..efe2625a0bda --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java @@ -0,0 +1,243 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * Convenience base class for implementing the {@link ValueContainer} contract centralizing commonality + * between modeling tables, views and inline views. + * + * @author Steve Ebersole + * @author Brett Meyer + */ +public abstract class AbstractTableSpecification implements TableSpecification { + + /** + * A column and derived value can have the same text; this value class helps + * to disambiguate. + */ + private class ValueKey { + private final Value.ValueType valueType; + private final Identifier identifier; + + private ValueKey(Value.ValueType valueType, Identifier identifier) { + this.valueType = valueType; + this.identifier = identifier; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + ValueKey valueKey = (ValueKey) o; + + if ( identifier != null ? !identifier.equals( valueKey.identifier ) : valueKey.identifier != null ) { + return false; + } + return valueType == valueKey.valueType; + + } + + @Override + public int hashCode() { + int result = valueType != null ? valueType.hashCode() : 0; + result = 31 * result + ( identifier != null ? identifier.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "ValueKey{valueType=" + valueType.name() + + ", identifier=" + identifier + + '}'; + } + } + private int tableNumber; + + private final List valueList = new ArrayList(); + private final LinkedHashMap valueMap = new LinkedHashMap(); + + private final PrimaryKey primaryKey = new PrimaryKey( this ); + private final List foreignKeys = new ArrayList(); + + @Override + public int getTableNumber() { + return tableNumber; + } + + public void setTableNumber( int tableNumber ) { + // This must be done outside of Table, rather than statically, to ensure + // deterministic alias names. See HHH-2448. + this.tableNumber = tableNumber; + } + + @Override + public List values() { + return Collections.unmodifiableList( valueList ); + } + + @Override + public Column locateOrCreateColumn(String name) { + Column column = locateColumn( name ); + if(column == null){ + column = createColumn( name ); + } + return column; + } + + @Override + public Column locateColumn(String name) { + final Identifier identifier = Identifier.toIdentifier( name ); + final ValueKey valueKey = new ValueKey( Value.ValueType.COLUMN, identifier ); + if ( valueMap.containsKey( valueKey ) ) { + Value value = valueMap.get( valueKey ); + return Column.class.isInstance( value ) ? Column.class.cast( value ) : null; + } + return null; + } + + @Override + public boolean hasValue(Value value) { + return valueMap.containsValue( value ); + } + + @Override + public Column createColumn(String name) { + return createColumn( Identifier.toIdentifier( name ) ); + } + + @Override + public Column createColumn(Identifier name) { + final Column column = new Column( valueList.size(), name ); + valueMap.put( new ValueKey( column.getValueType(), name ), column ); + valueList.add( column ); + return column; + } + + @Override + public DerivedValue locateOrCreateDerivedValue(String fragment) { + DerivedValue value = locateDerivedValue( fragment ); + return value != null ? value : createDerivedValue( fragment ); + } + + protected DerivedValue locateDerivedValue(String fragment) { + final Identifier identifier = Identifier.toIdentifier( fragment ); + final ValueKey valueKey = new ValueKey( Value.ValueType.DERIVED_VALUE, identifier ); + if ( valueMap.containsKey( valueKey ) ) { + Value value = valueMap.get( valueKey ); + if ( DerivedValue.class.isInstance( value ) ) { + return DerivedValue.class.cast( value ); + } + } + return null; + } + + protected DerivedValue createDerivedValue(String fragment) { + final Identifier identifier = Identifier.toIdentifier( fragment ); + final DerivedValue value = new DerivedValue( valueList.size(), fragment ); + valueMap.put( new ValueKey( value.getValueType(), identifier ), value ); + valueList.add( value ); + return value; + } + + @Override + public Iterable getForeignKeys() { + return foreignKeys; + } + + @Override + public ForeignKey createForeignKey(TableSpecification targetTable, String name, boolean createConstraint) { + Identifier identifier = Identifier.toIdentifier( name ); + return createForeignKey( targetTable, identifier, createConstraint ); + } + + @Override + public ForeignKey createForeignKey(TableSpecification targetTable, Identifier name, boolean createConstraint) { + ForeignKey fk = new ForeignKey( this, targetTable, name, createConstraint ); + foreignKeys.add( fk ); + return fk; + } + + @Override + public ForeignKey locateForeignKey(String name) { + return locateConstraint( foreignKeys, name ); + } + + protected T locateConstraint(Iterable constraints, String name) { + if ( name == null ) { + throw new IllegalArgumentException( "name must be non-null." ); + } + Identifier identifier = Identifier.toIdentifier( name ); + for ( T constraint : constraints ) { + if ( identifier.equals( constraint.getName() ) ) { + return constraint; + } + } + return null; + } + + @Override + public Iterable locateForeignKey(TableSpecification targetTable) { + List result = null; + for ( ForeignKey fk : foreignKeys ) { + if ( fk.getTargetTable().equals( targetTable ) ) { + if ( result == null ) { + result = new ArrayList(); + } + result.add( fk ); + } + } + return result; + } + + + @Override + public PrimaryKey getPrimaryKey() { + return primaryKey; + } + @Override + public int columnListId(Iterable columns) { + int result = getLogicalName().hashCode(); + for ( Column column : columns ) { + sameTableCheck( column ); + result = 31 * result + column.getColumnName().hashCode(); + } + return result; + } + + private void sameTableCheck(Column column) { + if ( ! hasValue( column ) ) { + throw new IllegalArgumentException( "All columns must be from this table." ); + } + } +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java new file mode 100644 index 000000000000..ff45a51173a7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.ValidationException; + +import org.jboss.logging.Logger; + +/** + * Basic support for {@link Value} implementations. + * + * @author Steve Ebersole + */ +public abstract class AbstractValue implements Value { + + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractValue.class.getName()); + + private final int position; + private JdbcDataType jdbcDataType; + + protected AbstractValue(int position) { + this.position = position; + } + + public int getPosition() { + return position; + } + + @Override + public JdbcDataType getJdbcDataType() { + return jdbcDataType; + } + + public void setJdbcDataType(JdbcDataType jdbcDataType) { + LOG.debugf( "setting jdbcDataType for column %s : %s", toLoggableString(), jdbcDataType ); + if ( this.jdbcDataType != null && ! this.jdbcDataType.equals( jdbcDataType ) ) { + LOG.debugf( "overriding previous jdbcDataType : %s", this.jdbcDataType ); + } + this.jdbcDataType = jdbcDataType; + } + + @Override + public void validateJdbcTypes(JdbcCodes typeCodes) { + // todo : better compatibility testing... + if ( jdbcDataType.getTypeCode() != typeCodes.nextJdbcCde() ) { + throw new ValidationException( "Mismatched types" ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java new file mode 100644 index 000000000000..fde238dba050 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AuxiliaryDatabaseObject.java @@ -0,0 +1,76 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.io.Serializable; + +import org.hibernate.dialect.Dialect; + +/** + * Auxiliary database objects (i.e., triggers, stored procedures, etc) defined + * in the mappings. Allows Hibernate to manage their lifecycle as part of + * creating/dropping the schema. + * + * @author Steve Ebersole + */ +public interface AuxiliaryDatabaseObject extends Exportable, Serializable { + /** + * Does this database object apply to the given dialect? + * + * @param dialect The dialect to check against. + * @return True if this database object does apply to the given dialect. + */ + public boolean appliesToDialect(Dialect dialect); + + /** + * Defines a simple precedence. Should creation of this auxiliary object happen before creation of + * tables? If {@code true}, the auxiliary object creation will happen after any explicit schema creations + * but before table/sequence creations; if {@code false}, the auxiliary object creation will happen after + * explicit schema creations and after table/sequence creations. + * + * This precedence is automatically inverted for dropping. + * + * @return {@code true} indicates this object should be created before tables; {@code false} indicates + * it should be created after. + */ + public boolean beforeTablesOnCreation(); + + /** + * Gets the SQL strings for creating the database object. + * + * @param dialect The dialect for which to generate the SQL creation strings + * + * @return the SQL strings for creating the database object. + */ + public String[] sqlCreateStrings(Dialect dialect); + + /** + * Gets the SQL strings for dropping the database object. + * + * @param dialect The dialect for which to generate the SQL drop strings + * + * @return the SQL strings for dropping the database object. + */ + public String[] sqlDropStrings(Dialect dialect); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/BasicAuxiliaryDatabaseObjectImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/BasicAuxiliaryDatabaseObjectImpl.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/BasicAuxiliaryDatabaseObjectImpl.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/BasicAuxiliaryDatabaseObjectImpl.java index 07389d08ca9f..834f87d97545 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/BasicAuxiliaryDatabaseObjectImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/BasicAuxiliaryDatabaseObjectImpl.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.Set; @@ -35,6 +35,7 @@ public class BasicAuxiliaryDatabaseObjectImpl extends AbstractAuxiliaryDatabaseObject { private static final String CATALOG_NAME_PLACEHOLDER = "${catalog}"; private static final String SCHEMA_NAME_PLACEHOLDER = "${schema}"; + private final Schema defaultSchema; private final String createString; private final String dropString; @@ -63,8 +64,8 @@ public String[] sqlDropStrings(Dialect dialect) { } private static String injectCatalogAndSchema(String ddlString, Schema schema) { - String rtn = StringHelper.replace( ddlString, CATALOG_NAME_PLACEHOLDER, schema.getName().getCatalog().getName() ); - rtn = StringHelper.replace( rtn, SCHEMA_NAME_PLACEHOLDER, schema.getName().getSchema().getName() ); + String rtn = StringHelper.replace( ddlString, CATALOG_NAME_PLACEHOLDER, schema.getName().getCatalog().getText() ); + rtn = StringHelper.replace( rtn, SCHEMA_NAME_PLACEHOLDER, schema.getName().getSchema().getText() ); return rtn; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/CheckConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/CheckConstraint.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/CheckConstraint.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/CheckConstraint.java index 52c0a5c129d5..885d3439f01e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/CheckConstraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/CheckConstraint.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; /** * TODO : javadoc diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java new file mode 100644 index 000000000000..f53ad232f9d7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java @@ -0,0 +1,244 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.function.SQLFunctionRegistry; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.sql.Template; + +/** + * Models a physical column + * + * @author Gavin King + * @author Steve Ebersole + */ +public class Column extends AbstractValue { + public static final int DEFAULT_LENGTH = 255; + public static final int DEFAULT_PRECISION = 19; + public static final int DEFAULT_SCALE = 2; + + private final Identifier columnName; + private boolean nullable = true; + + private String defaultValue; + private String checkCondition; + private String sqlType; + + private String readFragment; + private String writeFragment; + + private String comment; + + private Size size = new Size(); + + private boolean isIdentity = false; + + protected Column(int position, Identifier name) { + super( position ); + this.columnName = name; + } + + public Identifier getColumnName() { + return columnName; + } + + public boolean isNullable() { + return nullable; + } + + public void setNullable(boolean nullable) { + this.nullable = nullable; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getCheckCondition() { + return checkCondition; + } + + public void setCheckCondition(String checkCondition) { + this.checkCondition = checkCondition; + } + + public String getSqlType() { + return sqlType; + } + + public void setSqlType(String sqlType) { + this.sqlType = sqlType; + } + + // TODO: Solely used by schema tools. Re-think this, getSqlType, and getJdbcDataType. Clean-up and/or + // condense somehow? + public String getSqlTypeString(Dialect dialect) { + if ( sqlType != null ) { + return sqlType; + } + else { + return dialect.getTypeName( + getJdbcDataType().getTypeCode(), + size.getLength(), + size.getPrecision(), + size.getScale() + ); + } + } + + public String getReadFragment() { + return readFragment; + } + + public void setReadFragment(String readFragment) { + this.readFragment = readFragment; + } + + public String getWriteFragment() { + return writeFragment; + } + + public void setWriteFragment(String writeFragment) { + this.writeFragment = writeFragment; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getTemplate(Dialect dialect, SQLFunctionRegistry functionRegistry) { + return hasCustomRead() + ? Template.renderWhereStringTemplate( readFragment, dialect, functionRegistry ) + : Template.TEMPLATE + '.' + getColumnName().getText( dialect ); + } + + public boolean hasCustomRead() { + return StringHelper.isNotEmpty( readFragment ); + } + + public String getReadExpr(Dialect dialect) { + return hasCustomRead() ? readFragment : getColumnName().getText( dialect ); + } + + public String getWriteExpr() { + return StringHelper.isNotEmpty( writeFragment ) ? writeFragment : "?"; + } + + + public Size getSize() { + return size; + } + + public void setSize(Size size) { + this.size = size; + } + + /** + * Returns true if this column is an identity column. + * @return true, if this column is an identity column; false, otherwise. + */ + public boolean isIdentity() { + return isIdentity; + } + + /** + * Indicate if this column is an identity column. + * @param isIdentity - true, if this column is an identity column; false, otherwise. + */ + public void setIdentity(boolean isIdentity) { + this.isIdentity = isIdentity; + } + + @Override + public ValueType getValueType() { + return ValueType.COLUMN; + } + + @Override + public String toLoggableString() { + return getColumnName().getText(); + } + + @Override + public String getAlias(Dialect dialect, TableSpecification tableSpecification) { + if ( tableSpecification == null ) { + // see HHH-7547 -- protect against ambiguity + throw new IllegalArgumentException("To ensure uniqueness, tableSpecification must not be null"); + } + + final int lastLetter = StringHelper.lastIndexOfLetter( columnName.getText() ); + final String colPositionSuffix = String.valueOf( getPosition() ) + '_'; + final String tableNumberSuffix = String.valueOf( tableSpecification.getTableNumber() ) + "_"; + final String suffix = colPositionSuffix + tableNumberSuffix; + + String alias; + if ( lastLetter == -1 ) { + alias = "column" ; + } + else if ( columnName.getText().length() > lastLetter + 1 ) { + alias = columnName.getText().substring( 0, lastLetter + 1 ); + } + else { + alias = columnName.getText(); + } + + if ( alias.length() + suffix.length() > dialect.getMaxAliasLength() ) { + alias = alias.substring( 0, dialect.getMaxAliasLength() - suffix.length() ); + } + + return alias + suffix; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + Column column = (Column) o; + + if ( columnName != null ? !columnName.equals( column.columnName ) : column.columnName != null ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return columnName != null ? columnName.hashCode() : 0; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Constraint.java similarity index 85% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Constraint.java index 5587ebcbd6a8..46a176d04378 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Constraint.java @@ -21,7 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; + +import java.util.List; /** * Basic contract for the types of constraints we fully support as metadata constructs:

        @@ -45,12 +47,12 @@ public interface Constraint extends Exportable { * * @return the name. */ - public String getName(); + public Identifier getName(); /** - * Obtain the columns that are part of this constraint. + * Obtain a read-only view of the columns that are part of this constraint. * - * @return The constrained columns. + * @return A read-only view of the constrained columns. */ - public Iterable getColumns(); + public List getColumns(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java new file mode 100644 index 000000000000..82169c5632b3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Database.java @@ -0,0 +1,126 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; + +/** + * Represents a database and manages the named schema/catalog pairs defined within. + * + * @author Steve Ebersole + * @author Gail Badner + */ +public class Database { + public static interface Defaults { + String getDefaultSchemaName(); + String getDefaultCatalogName(); + boolean isGloballyQuotedIdentifiers(); + } + + private final Schema.Name implicitSchemaName; + private final JdbcEnvironment jdbcEnvironment; + + private final Map schemaMap = new HashMap(); + private final List auxiliaryDatabaseObjects = new ArrayList(); + private final List initCommands = new ArrayList(); + + public Database(Defaults options, JdbcEnvironment jdbcEnvironment) { + String schemaName = options.getDefaultSchemaName(); + String catalogName = options.getDefaultCatalogName(); + if ( options.isGloballyQuotedIdentifiers() ) { + schemaName = StringHelper.quote( schemaName ); + catalogName = StringHelper.quote( catalogName ); + } + this.implicitSchemaName = new Schema.Name( catalogName, schemaName ); + makeSchema( implicitSchemaName ); + this.jdbcEnvironment = jdbcEnvironment; + } + + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } + + public Iterable getSchemas() { + return schemaMap.values(); + } + + public Schema getDefaultSchema() { + return schemaMap.get( implicitSchemaName ); + } + + public Schema locateSchema(Schema.Name name) { + if ( name.getSchema() == null && name.getCatalog() == null ) { + return getDefaultSchema(); + } + Schema schema = schemaMap.get( name ); + if ( schema == null ) { + schema = makeSchema( name ); + } + return schema; + } + + public Schema getSchemaFor(ObjectName objectName) { + return getSchema( objectName.getCatalog(), objectName.getSchema() ); + } + + private Schema makeSchema(Schema.Name name) { + Schema schema; + schema = new Schema( name ); + schemaMap.put( name, schema ); + return schema; + } + + public Schema getSchema(Identifier catalog, Identifier schema) { + return locateSchema( new Schema.Name( catalog, schema ) ); + } + + public Schema getSchema(String catalog, String schema) { + return locateSchema( new Schema.Name( Identifier.toIdentifier( catalog ), Identifier.toIdentifier( schema ) ) ); + } + + public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) { + if ( auxiliaryDatabaseObject == null ) { + throw new IllegalArgumentException( "Auxiliary database object is null." ); + } + auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject ); + } + + public Iterable getAuxiliaryDatabaseObjects() { + return auxiliaryDatabaseObjects; + } + + public void addInitCommand(InitCommand initCommand) { + initCommands.add( initCommand ); + } + + public Iterable getInitCommands() { + return initCommands; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java new file mode 100644 index 000000000000..8f26aa9f0378 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java @@ -0,0 +1,128 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Strong Liu + */ +public class DenormalizedTable extends Table { + private final Table includedTable; + + public DenormalizedTable(Schema database, Identifier logicalName, Identifier physicalName, Table includedTable) { + super( database, logicalName, physicalName ); + this.includedTable = includedTable; + this.includedTable.setHasDenormalizedTables( true ); + } + + @Override + public List values() { + List values = new ArrayList( super.values().size() + includedTable.values().size() ); + values.addAll( super.values() ); + values.addAll( includedTable.values() ); + return Collections.unmodifiableList( values ); + } + + @Override + public Column locateColumn(String name) { + Column column = includedTable.locateColumn( name ); + if(column!=null){ + return column; + } + return super.locateColumn( name ); + } + + @Override + public boolean hasValue(Value value) { + return includedTable.hasValue( value ) || super.hasValue( value ); + } + + @Override + protected DerivedValue locateDerivedValue(String fragment) { + DerivedValue value = includedTable.locateDerivedValue( fragment ); + return value != null ? value : super.locateDerivedValue( fragment ); + } + //todo other constraints other than fk + //we have to copy all FKs defined in the parent table to this sub table, can this be doing only once? like using ValueHolder? + @Override + public Iterable getForeignKeys() { + copyFKsFromParentTable(); + return super.getForeignKeys(); + } + private Set alreadyCopiedNonNameParentFK = new HashSet( ); + private void copyFKsFromParentTable() { + Iterable fksInSuperTable = includedTable.getForeignKeys(); + final String fkNamePostfix = Integer.toHexString( getTableName().hashCode() ); + for ( ForeignKey fk : fksInSuperTable ) { + + Identifier name = fk.getName(); + if (name == null || name.getText() == null) { + if(!alreadyCopiedNonNameParentFK.contains( fk )){ + copyFK( fk, name ); + alreadyCopiedNonNameParentFK.add( fk ); + } + } + else { + Identifier fkName = name.applyPostfix( fkNamePostfix ); + ForeignKey copiedFK = super.locateForeignKey( fkName.toString() ); + if ( copiedFK == null ) { + copyFK( fk, fkName ); + } + } + } + } + + private void copyFK(ForeignKey fk, Identifier fkName) { + ForeignKey copiedFK = createForeignKey( fk.getTargetTable(), fkName, fk.createConstraint() ); + copiedFK.setDeleteRule( fk.getDeleteRule() ); + copiedFK.setUpdateRule( fk.getUpdateRule() ); + Iterable columnMappings = fk.getColumnMappings(); + for ( ForeignKey.ColumnMapping cm : columnMappings ) { + copiedFK.addColumnMapping( cm.getSourceColumn(), cm.getTargetColumn() ); + } + } + + @Override + public Iterable locateForeignKey(TableSpecification targetTable) { + Iterable fks = includedTable.locateForeignKey( targetTable ); + return fks != null ? fks : super.locateForeignKey( targetTable ); + } + + @Override + protected T locateConstraint(Iterable constraints, String name) { + T t = includedTable.locateConstraint( constraints, name ); + return t != null ? t : super.locateConstraint( constraints, name ); + } + + @Override + public PrimaryKey getPrimaryKey() { + return includedTable.getPrimaryKey(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java similarity index 78% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java index 2f39332ac79f..c743958fd814 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.dialect.Dialect; @@ -30,21 +30,31 @@ * * @author Steve Ebersole */ -public class DerivedValue extends AbstractSimpleValue { +public class DerivedValue extends AbstractValue { private final String expression; - public DerivedValue(TableSpecification table, int position, String expression) { - super( table, position ); + public DerivedValue(int position, String expression) { + super( position ); this.expression = expression; } @Override + public ValueType getValueType() { + return ValueType.DERIVED_VALUE; + } + + /** + * {@inheritDoc} + */ public String toLoggableString() { - return getTable().toLoggableString() + ".{derived-column}"; + return "{derived-column}"; } + /** + * {@inheritDoc} + */ @Override - public String getAlias(Dialect dialect) { + public String getAlias(Dialect dialect, TableSpecification tableSpecification) { return "formula" + Integer.toString( getPosition() ) + '_'; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Exportable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Exportable.java new file mode 100644 index 000000000000..6ed7d95bd6b3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Exportable.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +/** + * Contract for entities (in the ERD sense) which can be exported via {@code CREATE}, {@code ALTER}, etc + * + * @author Steve Ebersole + * + * @see org.hibernate.tool.schema.spi.Exporter + */ +public interface Exportable { + /** + * Get a unique identifier to make sure we are not exporting the same database structure multiple times. + * + * @return The exporting identifier. + */ + public String getExportIdentifier(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ExportableProducer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ExportableProducer.java new file mode 100644 index 000000000000..ff193c611594 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ExportableProducer.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +/** + * Identifies metamodel objects that can produce {@link Exportable} relational stuff. + * + * @author Steve Ebersole + */ +public interface ExportableProducer { + /** + * Register the contained exportable things to the {@link Database} + * + * @param database The database instance + */ + public void registerExportables(Database database); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java new file mode 100644 index 000000000000..0a59820017d9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ForeignKey.java @@ -0,0 +1,227 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.AssertionFailure; +import org.jboss.logging.Logger; + +/** + * Models the notion of a foreign key. + *

        + * Note that this need not mean a physical foreign key; we just mean a relationship between 2 table + * specifications. + * + * @author Gavin King + * @author Steve Ebersole + * @author Brett Meyer + */ +public class ForeignKey extends AbstractConstraint { + + private static final Logger LOG = Logger.getLogger( ForeignKey.class ); + + private static final String ON_DELETE = " on delete "; + private static final String ON_UPDATE = " on update "; + + private final TableSpecification targetTable; + private List targetColumns; + + private ReferentialAction deleteRule = ReferentialAction.NO_ACTION; + private ReferentialAction updateRule = ReferentialAction.NO_ACTION; + + private boolean createConstraint; + + protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, Identifier name, + boolean createConstraint) { + super( sourceTable, name ); + if ( targetTable == null ) { + throw new IllegalArgumentException( "targetTable must be non-null." ); + } + this.targetTable = targetTable; + this.createConstraint = createConstraint; + } + + protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable) { + this( sourceTable, targetTable, null, true ); + } + + public TableSpecification getSourceTable() { + return getTable(); + } + + public TableSpecification getTargetTable() { + return targetTable; + } + + public List getSourceColumns() { + return getColumns(); + } + + public List getTargetColumns() { + return targetColumns == null + ? getTargetTable().getPrimaryKey().getColumns() + : Collections.unmodifiableList( targetColumns ); + } + + public boolean hasTargetColumn(String name) { + for (Column column : targetColumns) { + if (column.getColumnName().getText().equals( name )) { + return true; + } + } + return false; + } + + public int getTargetColumnSpan() { + return targetColumns.size(); + } + + public int columnListId() { + return 31 * super.columnListId() + targetTable.columnListId( getTargetColumns() ); + } + + @Override + public void addColumn(Column column) { + addColumnMapping( column, null ); + } + + public void addColumnMapping(Column sourceColumn, Column targetColumn) { + if ( targetColumn == null ) { + if ( targetColumns != null ) { + LOG.debugf( + "Attempt to map column [%s] to no target column after explicit target column(s) named for FK [name=%s]", + sourceColumn.toLoggableString(), + getName() + ); + } + } + else { + checkTargetTable( targetColumn ); + if ( targetColumns == null ) { + if (!internalColumnAccess().isEmpty()) { + LOG.debugf( + "Value mapping mismatch as part of FK [table=%s, name=%s] while adding source column [%s]", + getTable().toLoggableString(), + getName(), + sourceColumn.toLoggableString() + ); + } + targetColumns = new ArrayList(); + } + targetColumns.add( targetColumn ); + } + internalAddColumn( sourceColumn ); + } + + private void checkTargetTable(Column targetColumn) { + if ( !getTargetTable().hasValue( targetColumn ) ) { + throw new AssertionFailure( + String.format( + "Unable to add column to constraint; target column [%s] is not in target table [%s]", + targetColumn.toLoggableString(), + getTargetTable().toLoggableString() + ) + ); + } + } + + public ReferentialAction getDeleteRule() { + return deleteRule; + } + + public void setDeleteRule(ReferentialAction deleteRule) { + this.deleteRule = deleteRule; + } + + public ReferentialAction getUpdateRule() { + return updateRule; + } + + public void setUpdateRule(ReferentialAction updateRule) { + this.updateRule = updateRule; + } + + public static enum ReferentialAction { + NO_ACTION( "no action" ), + CASCADE( "cascade" ), + SET_NULL( "set null" ), + SET_DEFAULT( "set default" ), + RESTRICT( "restrict" ); + + private final String actionString; + + private ReferentialAction(String actionString) { + this.actionString = actionString; + } + + public String getActionString() { + return actionString; + } + } + + public class ColumnMapping { + private final int position; + + public ColumnMapping(int position) { + this.position = position; + } + + public Column getSourceColumn() { + return getColumns().get( position ); + } + + public Column getTargetColumn() { + return getTargetColumns().get( position ); + } + } + + public boolean referencesPrimaryKey() { + return targetColumns == null + || targetColumns.equals( targetTable.getPrimaryKey().getColumns() ); + } + + public Iterable getColumnMappings() { + final List targetColumns = getTargetColumns(); + if ( getColumns().size() != targetColumns.size() ) { + // todo : this needs to be an error, though not sure the best type yet + } + final List columnMappingList = new ArrayList(); + for ( int i = 0; i < getColumns().size(); i++ ) { + columnMappingList.add( new ColumnMapping( i ) ); + } + return columnMappingList; + } + + @Override + public String getExportIdentifier() { + return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName().getText(); + } + + public boolean createConstraint() { + return createConstraint; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Identifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Identifier.java new file mode 100644 index 000000000000..0dbb052ccd59 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Identifier.java @@ -0,0 +1,211 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + + +import org.hibernate.dialect.Dialect; +import org.hibernate.internal.util.StringHelper; + +/** + * Models an identifier (name). + * + * @author Steve Ebersole + * @author Brett Meyer + */ +public class Identifier implements Comparable { + private String text; + private final boolean isQuoted; + + /** + * Means to generate an {@link Identifier} instance from its simple name + * + * @param text The text + * + * @return The identifier form of the name. + */ + public static Identifier toIdentifier(String text) { + if ( StringHelper.isEmpty( text ) ) { + return null; + } + final String trimmed = text.trim(); + if ( isQuoted( trimmed ) ) { + final String bareName = trimmed.substring( 1, trimmed.length() - 1 ); + return new Identifier( bareName, true ); + } + else { + return new Identifier( trimmed, false ); + } + } + + /** + * Means to generate an {@link Identifier} instance from its simple name + * + * @param text The name + * + * @return The identifier form of the name. + */ + public static Identifier toIdentifier(String text, boolean quote) { + if ( StringHelper.isEmpty( text ) ) { + return null; + } + final String trimmed = text.trim(); + if ( isQuoted( trimmed ) ) { + final String bareName = trimmed.substring( 1, trimmed.length() - 1 ); + return new Identifier( bareName, quote ); + } + else { + return new Identifier( trimmed, quote ); + } + } + + public static boolean isQuoted(String text) { + return text.startsWith( "`" ) && text.endsWith( "`" ); + } + + /** + * Constructs an identifier instance. + * + * private access. Use one of the static {@link #toIdentifier} forms instead to get a reference. + * + * @param text The identifier text. + * @param quoted Is this a quoted identifier? + */ + private Identifier(String text, boolean quoted) { + if ( StringHelper.isEmpty( text ) ) { + throw new IllegalIdentifierException( "Identifier text cannot be null" ); + } + if ( isQuoted( text ) ) { + throw new IllegalIdentifierException( "Identifier text should not contain quote markers (`)" ); + } + this.text = text; + this.isQuoted = quoted; + } + + public boolean isEmpty() { + return text.equals( "" ); + } + + /** + * Is this a quoted identifier> + * + * @return True if this is a quote identifier; false otherwise. + */ + public boolean isQuoted() { + return isQuoted; + } + + /** + * Get the identifier text + * + * @return The text + */ + public String getText() { + return text; + } + + /** + * @deprecated Use {@link #getText} instead + */ + @Deprecated + public String getName() { + return text; + } + + /** + * If this is a quoted identifier, then return the identifier name + * enclosed in dialect-specific open- and end-quotes; otherwise, + * simply return the identifier name. + * + * @param dialect The dialect whose dialect-specific quoting should be used. + * @return if quoted, identifier name enclosed in dialect-specific open- and end-quotes; otherwise, the + * identifier name. + */ + public String getText(Dialect dialect) { + return getText( dialect.openQuote(), dialect.closeQuote() ); + } + + /** + * If this is a quoted identifier, then return the identifier name + * enclosed in dialect-specific open- and end-quotes; otherwise, + * simply return the identifier name. + * + * @param openQuote The character to use as start quote + * @param closeQuote The character to use as end quote + * @return if quoted, identifier name enclosed in dialect-specific open- and end-quotes; otherwise, the + * identifier name. + */ + public String getText(char openQuote, char closeQuote) { + return isQuoted ? + String.valueOf( openQuote ) + text + closeQuote : + text; + } + + public String getQualifiedText(String prefix, Dialect dialect) { + String qualified = prefix + "." + text; + return isQuoted ? dialect.openQuote() + qualified + dialect.closeQuote() : qualified; + } + + public String getUnqualifiedText(Dialect dialect) { + int loc = text.lastIndexOf("."); + String unqualified = ( loc < 0 ) ? text : text.substring( loc + 1 ); + return isQuoted ? dialect.openQuote() + unqualified + dialect.closeQuote() : unqualified; + } + + public Identifier applyPostfix(String postfix) { + String newText = text + postfix; + return Identifier.toIdentifier( newText, isQuoted ); + } + + @Override + public String toString() { + return isQuoted + ? '`' + getText() + '`' + : getText(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + Identifier that = (Identifier) o; + + return isQuoted == that.isQuoted + && isQuoted ? text.equals( that.text ) : text.equalsIgnoreCase( that.text ); + } + + @Override + public int hashCode() { + return isQuoted ? text.hashCode() : text.toUpperCase().hashCode(); + } + + @Override + public int compareTo(Identifier o) { + return text.compareTo( o.getText() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/IllegalIdentifierException.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/IllegalIdentifierException.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/IllegalIdentifierException.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/IllegalIdentifierException.java index 80ccba8ecceb..e904ffd61d04 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/IllegalIdentifierException.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/IllegalIdentifierException.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import org.hibernate.HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/InLineView.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/InLineView.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java index 23651e8d8298..adc0aeee1399 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/InLineView.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InLineView.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.util.Collections; @@ -36,10 +36,10 @@ */ public class InLineView extends AbstractTableSpecification { private final Schema schema; - private final String logicalName; + private final Identifier logicalName; private final String select; - public InLineView(Schema schema, String logicalName, String select) { + public InLineView(Schema schema, Identifier logicalName, String select) { this.schema = schema; this.logicalName = logicalName; this.select = select; @@ -49,13 +49,18 @@ public Schema getSchema() { return schema; } + @Override + public Identifier getLogicalName() { + return logicalName; + } + public String getSelect() { return select; } @Override public String getLoggableValueQualifier() { - return logicalName; + return logicalName.getText(); } @Override @@ -64,7 +69,7 @@ public Iterable getIndexes() { } @Override - public Index getOrCreateIndex(String name) { + public void addIndex(Index index) { throw new UnsupportedOperationException( "Cannot create index on inline view" ); } @@ -74,10 +79,15 @@ public Iterable getUniqueKeys() { } @Override - public UniqueKey getOrCreateUniqueKey(String name) { + public void addUniqueKey(UniqueKey uk) { throw new UnsupportedOperationException( "Cannot create unique-key on inline view" ); } + @Override + public boolean hasUniqueKey(Column column) { + return false; + } + @Override public Iterable getCheckConstraints() { return Collections.emptyList(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java new file mode 100644 index 000000000000..8928d53d4ac5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + + +/** + * Models a SQL INDEX + * + * @author Gavin King + * @author Steve Ebersole + */ +public class Index extends AbstractConstraint { + + private final boolean unique; + + public Index(boolean unique) { + this( null, null, unique ); + } + + protected Index(Table table, Identifier name, boolean unique) { + super( table, name ); + this.unique = unique; + } + + @Override + public String getExportIdentifier() { + StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier() ); + sb.append( ".IDX" ); + sb.append( '_' ).append( getName().getText() ); + for ( Column column : getColumns() ) { + sb.append( '_' ).append( column.getColumnName().getText() ); + } + return sb.toString(); + } + + public boolean isUnique() { + return unique; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java new file mode 100644 index 000000000000..320c2675f735 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/InitCommand.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +/** + * A general SQL command. + * + * @author Steve Ebersole + */ +public class InitCommand { + private final String[] initCommands; + + public InitCommand(String... initCommands) { + this.initCommands = initCommands; + } + + public String[] getInitCommands() { + return initCommands; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java new file mode 100644 index 000000000000..7421fe9f8263 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +/** + * Models a JDBC {@link java.sql.Types DATATYPE}. Mainly breaks down into 3 pieces of information:

          + *
        • + * {@link #getTypeCode() type code} - The JDBC type code; generally matches a code from {@link java.sql.Types} + * though not necessarily. + *
        • + *
        • + * {@link #getTypeName() type name} - The database type name for the given type code. + *
        • + *
        • + * {@link #getJavaType()} java type} - The java type recommended for representing this JDBC type (if known) + *
        • + *
        + * + * @todo Would love to link this in with {@link org.hibernate.engine.jdbc.internal.TypeInfo} + * + * @author Steve Ebersole + */ +public class JdbcDataType { + private final int typeCode; + private final String typeName; + private final Class javaType; + private final int hashCode; + + public JdbcDataType(int typeCode, String typeName, Class javaType) { + this.typeCode = typeCode; + this.typeName = typeName; + this.javaType = javaType; + + int result = typeCode; + if ( typeName != null ) { + result = 31 * result + typeName.hashCode(); + } + if ( javaType != null ) { + result = 31 * result + javaType.hashCode(); + } + this.hashCode = result; + } + + public int getTypeCode() { + return typeCode; + } + + public String getTypeName() { + return typeName; + } + + public Class getJavaType() { + return javaType; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + JdbcDataType jdbcDataType = (JdbcDataType) o; + + return typeCode == jdbcDataType.typeCode + && javaType.equals( jdbcDataType.javaType ) + && typeName.equals( jdbcDataType.typeName ); + + } + + @Override + public String toString() { + return super.toString() + "[code=" + typeCode + ", name=" + typeName + ", javaClass=" + javaType.getName() + "]"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Loggable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Loggable.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Loggable.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Loggable.java index b49008d24430..8f61c8fb08bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Loggable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Loggable.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; /** * Marker for things which can be logged. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ObjectName.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ObjectName.java new file mode 100644 index 000000000000..8b9feb759351 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ObjectName.java @@ -0,0 +1,226 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.internal.util.StringHelper; + +/** + * Models the qualified name of a database object. + *

        + * Some things to keep in mind wrt catalog/schema: + * 1) {@link java.sql.DatabaseMetaData#isCatalogAtStart} + * 2) {@link java.sql.DatabaseMetaData#getCatalogSeparator()} + * + * @author Steve Ebersole + */ +public class ObjectName { + private final Identifier catalog; + private final Identifier schema; + private final Identifier name; + + private final String identifier; + private final int hashCode; + + /** + * Tries to create an {@code ObjectName} from a name. This form explicitly looks for the form + * {@code catalog.schema.name}. If you need db specific parsing use + * {@link org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport#parseName} instead + * + * @param text simple or qualified name of the database object. + */ + public static ObjectName parse(String text) { + if ( text == null ) { + throw new IllegalIdentifierException( "Object name must be specified" ); + } + + String schemaName = null; + String catalogName = null; + String localObjectName; + + boolean wasQuoted = false; + if ( text.startsWith( "`" ) && text.endsWith( "`" ) ) { + wasQuoted = true; + text = StringHelper.unquote( text ); + } + + final String[] tokens = text.split( "." ); + if ( tokens.length == 0 || tokens.length == 1 ) { + // we have just a local name... + localObjectName = text; + } + else if ( tokens.length == 2 ) { + schemaName = tokens[0]; + localObjectName = tokens[1]; + } + else if ( tokens.length == 3 ) { + schemaName = tokens[0]; + catalogName = tokens[1]; + localObjectName = tokens[2]; + } + else { + throw new HibernateException( "Unable to parse object name: " + text ); + } + + final Identifier schema = Identifier.toIdentifier( schemaName, wasQuoted ); + final Identifier catalog = Identifier.toIdentifier( catalogName, wasQuoted ); + final Identifier object = Identifier.toIdentifier( localObjectName, wasQuoted ); + return new ObjectName( catalog, schema, object ); + } + + public ObjectName(Identifier name) { + this( null, null, name ); + } + + public ObjectName(Schema schema, String name) { + this( schema.getName().getCatalog(), schema.getName().getSchema(), Identifier.toIdentifier( name ) ); + } + + public ObjectName(Schema schema, Identifier name) { + this( schema.getName().getCatalog(), schema.getName().getSchema(), name ); + } + + public ObjectName(Schema.Name schemaName, Identifier name) { + this( schemaName.getCatalog(), schemaName.getSchema(), name ); + } + + public ObjectName(String catalogName, String schemaName, String name) { + this( + Identifier.toIdentifier( catalogName ), + Identifier.toIdentifier( schemaName ), + Identifier.toIdentifier( name ) + ); + } + + /** + * Creates a qualified name reference. + * + * @param catalog The catalog in which the object is defined (optional) + * @param schema The in which the object is defined (optional) + * @param name The name (required) + */ + public ObjectName(Identifier catalog, Identifier schema, Identifier name) { + if ( name == null ) { + // Identifier cannot be constructed with an 'empty' name + throw new IllegalIdentifierException( "Object name must be specified" ); + } + this.catalog = catalog; + this.schema = schema; + this.name = name; + + this.identifier = qualify( + catalog == null ? null : catalog.toString(), + schema == null ? null : schema.toString(), + name.toString() + ); + + int tmpHashCode = schema != null ? schema.hashCode() : 0; + tmpHashCode = 31 * tmpHashCode + ( catalog != null ? catalog.hashCode() : 0 ); + tmpHashCode = 31 * tmpHashCode + name.hashCode(); + this.hashCode = tmpHashCode; + } + + public Identifier getSchema() { + return schema; + } + + public Identifier getCatalog() { + return catalog; + } + + public Identifier getName() { + return name; + } + + public String toText() { + return identifier; + } + + public String toText(Dialect dialect) { + if ( dialect == null ) { + throw new IllegalArgumentException( "dialect must be non-null." ); + } + return qualify( + encloseInQuotesIfQuoted( catalog, dialect ), + encloseInQuotesIfQuoted( schema, dialect ), + encloseInQuotesIfQuoted( name, dialect ) + ); + } + + private static String encloseInQuotesIfQuoted(Identifier identifier, Dialect dialect) { + return identifier == null ? + null : + identifier.getText( dialect ); + } + + private static String qualify(String schema, String catalog, String name) { + StringBuilder buff = new StringBuilder( name ); + if ( catalog != null ) { + buff.insert( 0, catalog + '.' ); + } + if ( schema != null ) { + buff.insert( 0, schema + '.' ); + } + return buff.toString(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + ObjectName that = (ObjectName) o; + + return name.equals( that.name ) + && areEqual( catalog, that.catalog ) + && areEqual( schema, that.schema ); + } + + @Override + public int hashCode() { + return hashCode; + } + + + @Override + public String toString() { + return "ObjectName{" + + "catalog='" + catalog + '\'' + + ", schema='" + schema + '\'' + + ", name='" + name + '\'' + + '}'; + } + + private boolean areEqual(Identifier one, Identifier other) { + return one == null + ? other == null + : one.equals( other ); + } +} + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/PrimaryKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/PrimaryKey.java new file mode 100644 index 000000000000..08a217307f1d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/PrimaryKey.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.dialect.Dialect; + +/** + * Models a table's primary key. + *

        + * NOTE : This need not be a physical primary key; we just mean a column or columns which uniquely identify rows in + * the table. Of course it is recommended to define proper integrity constraints, including primary keys. + * + * @author Gavin King + * @author Steve Ebersole + */ +public class PrimaryKey extends AbstractConstraint { + + protected PrimaryKey(TableSpecification table) { + super( table, null ); + } + + // TODO: Can this be removed? + public String sqlConstraintStringInCreateTable(Dialect dialect) { + StringBuilder buf = new StringBuilder("primary key ("); + boolean first = true; + for ( Column column : getColumns() ) { + if ( first ) { + first = false; + } + else { + buf.append(", "); + } + buf.append( column.getColumnName().getText( dialect ) ); + } + return buf.append(')').toString(); + } + + @Override + public String getExportIdentifier() { + return getTable().getLoggableValueQualifier() + ".PK"; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java new file mode 100644 index 000000000000..3de639f37246 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Schema.java @@ -0,0 +1,213 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.compare.EqualsHelper; + +import org.jboss.logging.Logger; + +/** + * Represents a named schema/catalog pair and manages objects defined within. + * + * @author Steve Ebersole + */ +public class Schema { + private static final CoreMessageLogger log = Logger.getMessageLogger( + CoreMessageLogger.class, + Schema.class.getName() + ); + + private final Name name; + + private Map inLineViews = new HashMap(); + private Map tables = new HashMap(); + private Map sequences = new HashMap(); + + public Schema(Name name) { + this.name = name; + } + + public Schema(Identifier catalog, Identifier schema) { + this( new Name( catalog, schema ) ); + } + + public Name getName() { + return name; + } + + /** + * Returns the table with the specified logical table name. + * + * @param logicalTableName - the logical name of the table + * + * @return the table with the specified table name, + * or null if there is no table with the specified + * table name. + */ + public Table locateTable(Identifier logicalTableName) { + return tables.get( logicalTableName ); + } + + /** + * Creates a {@link Table} with the specified name. + * + * @param logicalTableName The logical table name + * @param physicalTableName - the name of the table + * + * @return the created table. + */ + public Table createTable(Identifier logicalTableName, Identifier physicalTableName) { + Table table = new Table( this, logicalTableName, physicalTableName ); + tables.put( logicalTableName, table ); + return table; + } + + public DenormalizedTable createDenormalizedTable(Identifier logicalTableName, Identifier physicalTableName, Table includedTable) { + DenormalizedTable table = new DenormalizedTable( this, logicalTableName, physicalTableName, includedTable ); + tables.put( logicalTableName, table ); + return table; + } + + public Iterable

    getTables() { + return tables.values(); + } + + public InLineView getInLineView(Identifier logicalName) { + return inLineViews.get( logicalName ); + } + + public InLineView createInLineView(Identifier logicalName, String subSelect) { + InLineView inLineView = new InLineView( this, logicalName, subSelect ); + inLineViews.put( logicalName, inLineView ); + return inLineView; + } + + public Sequence locateSequence(Identifier name) { + return sequences.get( name ); + } + + public Sequence createSequence(Identifier name, int initialValue, int increment) { + if ( sequences.containsKey( name ) ) { + throw new HibernateException( "Sequence was already registered with that name [" + name.toString() + "]" ); + } + + Sequence sequence = new Sequence( + new ObjectName( this.name.catalog, this.name.schema, name ), + initialValue, + increment + ); + sequences.put( name, sequence ); + return sequence; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "Schema" ); + sb.append( "{name=" ).append( name ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final Schema that = (Schema) o; + return EqualsHelper.equals( this.name, that.name ); + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + + public Iterable getSequences() { + return sequences.values(); + } + + public static class Name { + private final Identifier catalog; + private final Identifier schema; + + public Name(Identifier catalog, Identifier schema) { + this.schema = schema; + this.catalog = catalog; + } + + public Name(String catalog, String schema) { + this( Identifier.toIdentifier( catalog ), Identifier.toIdentifier( schema ) ); + } + + public Identifier getCatalog() { + return catalog; + } + + public Identifier getSchema() { + return schema; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "Name" ); + sb.append( "{catalog=" ).append( catalog ); + sb.append( ", schema=" ).append( schema ); + sb.append( '}' ); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + final Name that = (Name) o; + + return EqualsHelper.equals( this.catalog, that.catalog ) + && EqualsHelper.equals( this.schema, that.schema ); + } + + @Override + public int hashCode() { + int result = catalog != null ? catalog.hashCode() : 0; + result = 31 * result + (schema != null ? schema.hashCode() : 0); + return result; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Sequence.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Sequence.java new file mode 100644 index 000000000000..d9739562defb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Sequence.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.HibernateException; + +/** + * Models a database {@code SEQUENCE}. + * + * @author Steve Ebersole + */ +public class Sequence implements Exportable { + private final ObjectName name; + private final String nameText; + private int initialValue = 1; + private int incrementSize = 1; + + public Sequence(ObjectName name) { + this.name = name; + this.nameText = name.toText(); + } + + public Sequence(ObjectName name, int initialValue, int incrementSize) { + this( name ); + this.initialValue = initialValue; + this.incrementSize = incrementSize; + } + + public ObjectName getName() { + return name; + } + + @Override + public String getExportIdentifier() { + return nameText; + } + + public int getInitialValue() { + return initialValue; + } + + public int getIncrementSize() { + return incrementSize; + } + + public void validate(int initialValue, int incrementSize) { + if ( this.initialValue != initialValue ) { + throw new HibernateException( + String.format( + "Multiple references to database sequence [%s] were encountered attempting to" + + "set conflicting values for 'initial value'. Found [%s] and [%s]", + nameText, + this.initialValue, + initialValue + ) + ); + } + if ( this.incrementSize != incrementSize ) { + throw new HibernateException( + String.format( + "Multiple references to database sequence [%s] were encountered attempting to" + + "set conflicting values for 'increment size'. Found [%s] and [%s]", + nameText, + this.incrementSize, + incrementSize + ) + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Size.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Size.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/Size.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Size.java index 731d05af7841..59c3b407f386 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Size.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Size.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; import java.io.Serializable; @@ -115,6 +115,7 @@ public void initialize(Size size) { this.precision = size.precision; this.scale = size.scale; this.length = size.length; + this.lobMultiplier = size.lobMultiplier; } public void setPrecision(int precision) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java new file mode 100644 index 000000000000..99ee898fbaf1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java @@ -0,0 +1,317 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.compare.EqualsHelper; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * Models the concept of a relational TABLE (or VIEW). + * + * @author Gavin King + * @author Steve Ebersole + */ +public class Table extends AbstractTableSpecification implements Exportable { + private final Schema database; + private Identifier physicalName; + private Identifier logicalName; + private ObjectName qualifiedName; + private String exportIdentifier; + private boolean isPhysicalTable = true; + private boolean hasDenormalizedTables = false; + + private String rowId; + + private final Set indexes = new LinkedHashSet(); + private final Set uniqueKeys = new LinkedHashSet(); + private final List checkConstraints = new ArrayList(); + private final List comments = new ArrayList(); + + /** + * Constructs a {@link Table} instance. + * + * @param database - the schema + * @param logicalName - The logical name + * @param physicalName - the physical table name. + */ + public Table(Schema database, Identifier logicalName, Identifier physicalName) { + this.database = database; + this.logicalName = logicalName; + this.physicalName = physicalName; + this.qualifiedName = new ObjectName( database, physicalName ); + this.exportIdentifier = qualifiedName.toText(); + } + + @Override + public Schema getSchema() { + return database; + } + + /** + * Gets the logical table name. + * + * @return the logical table name. + */ + @Override + public Identifier getLogicalName() { + return logicalName; + } + + /** + * Returns the simple physical name. + * + * @return The simple (non-qualfied) table name. For the qualified name, see {@link #getTableName()} + * + * @see {@link #getTableName()} + */ + public Identifier getPhysicalName() { + return physicalName; + } + + /** + * Is this a physical table or should it be a virtual table representing as root entity in table-per-class hierarchy. + * + * It's {@code false} only when the entity is {@code abstract} and also having union sub-class + */ + public boolean isPhysicalTable() { + return isPhysicalTable; + } + + public void setPhysicalTable(boolean physicalTable) { + isPhysicalTable = physicalTable; + } + + public boolean hasDenormalizedTables() { + return hasDenormalizedTables; + } + + protected void setHasDenormalizedTables(boolean hasDenormalizedTables) { + this.hasDenormalizedTables = hasDenormalizedTables; + } + + /** + * Gets the qualified table name. + * + * @return the qualified table name. + */ + public ObjectName getTableName() { + return qualifiedName; + } + + @Override + public String getLoggableValueQualifier() { + return exportIdentifier; + } + + @Override + public String getExportIdentifier() { + return exportIdentifier; + } + + @Override + public String toLoggableString() { + return exportIdentifier; + } + + @Override + public Iterable getIndexes() { + return Collections.unmodifiableSet( indexes ); + } + + @Override + public void addIndex(Index idx) { + indexes.add( idx ); + } + + @Override + public Iterable getUniqueKeys() { + return Collections.unmodifiableSet( uniqueKeys ); + } + + @Override + public void addUniqueKey(UniqueKey uk) { + uniqueKeys.add( uk ); + } + + @Override + public boolean hasUniqueKey(Column column) { + for ( UniqueKey uniqueKey : uniqueKeys ) { + if ( uniqueKey.hasColumn( column ) ) { + return true; + } + } + return false; + } + + @Override + public Iterable getCheckConstraints() { + return checkConstraints; + } + + @Override + public void addCheckConstraint(String checkCondition) { + //todo ? StringHelper.isEmpty( checkCondition ); + //todo default name? + checkConstraints.add( new CheckConstraint( this, "", checkCondition ) ); + } + + @Override + public Iterable getComments() { + return comments; + } + + @Override + public void addComment(String comment) { + comments.add( comment ); + } + + public String getRowId() { + return rowId; + } + + public void setRowId(String rowId) { + this.rowId = rowId; + } + + @Override + public String getQualifiedName(Dialect dialect) { + return qualifiedName.toText( dialect ); + } + + @Override + public String toString() { + return "Table{name=" + exportIdentifier + '}'; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( ! ( o instanceof Table ) ) { + return false; + } + + final Table that = (Table) o; + + return EqualsHelper.equals( this.database, that.database ) + && EqualsHelper.equals( this.logicalName, that.logicalName ) + && EqualsHelper.equals( this.physicalName, that.physicalName ); + } + + @Override + public int hashCode() { + int result = database != null ? database.hashCode() : 0; + result = 31 * result + ( physicalName != null ? physicalName.hashCode() : 0 ); + result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 ); + return result; + } + + public String[] sqlAlterStrings(TableInformation tableInformation, JdbcEnvironment jdbcEnvironment) { + final Dialect dialect = jdbcEnvironment.getDialect(); + final String baseAlterCommand = "alter table " + + jdbcEnvironment.getQualifiedObjectNameSupport().formatName( getTableName() ) + + ' ' + dialect.getAddColumnString(); + + final List commands = new ArrayList(); + + for ( Value value : values() ) { + if ( ! Column.class.isInstance( value ) ) { + continue; + } + + final Column column = (Column) value; + final ColumnInformation columnInformation = tableInformation.getColumn( column.getColumnName() ); + + if ( columnInformation != null ) { + continue; + } + + StringBuilder alter = new StringBuilder( baseAlterCommand ) + .append( ' ' ) + .append( column.getColumnName().getText( dialect ) ) + .append( ' ' ) + .append( column.getSqlType() ); + + + final String defaultValue = column.getDefaultValue(); + if ( defaultValue != null ) { + alter.append( " default " ) + .append( defaultValue ); + } + String nullablePostfix = column.isNullable() ? dialect.getNullColumnString() : " not null"; + alter.append( nullablePostfix ); + + final String checkCondition = column.getCheckCondition(); + if ( checkCondition != null && dialect.supportsColumnCheck() ) { + alter.append( " check(" ) + .append( checkCondition ) + .append( ")" ); + } + + final String columnComment = column.getComment(); + if ( columnComment != null ) { + alter.append( dialect.getColumnComment( columnComment ) ); + } + + commands.add( alter.toString() ); + } + + return commands.toArray( new String[ commands.size() ] ); + } + + /** + * @return Sorted column list so that primary key appears first, followed by foreign keys and other properties. + * Within each group columns are not sorted in any way. + */ + public Iterable sortedColumns() { + final Set sortedColumns = new LinkedHashSet(); + + // Adding primary key columns. + sortedColumns.addAll( getPrimaryKey().getColumns() ); + // Adding foreign key columns. + for ( ForeignKey fk : getForeignKeys() ) { + sortedColumns.addAll( fk.getColumns() ); + } + // Adding other columns. + for ( Value value : values() ) { + if ( value instanceof Column ) { + final Column column = (Column) value; + if ( ! sortedColumns.contains( column ) ) { + sortedColumns.add( column ); + } + } + } + return sortedColumns; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java new file mode 100644 index 000000000000..8651879cc658 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java @@ -0,0 +1,159 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.dialect.Dialect; + +/** + * Models what ANSI SQL terms a table specification which is a table or a view or an inline view. + * + * @author Steve Ebersole + */ +public interface TableSpecification extends ValueContainer, Loggable { + /** + * Obtain a reference to the schema to which this table specification belongs. + * + * @return The schema to which this table specification belongs. + */ + public Schema getSchema(); + + /** + * Gets the logical table name. + * + * @return the logical table name. + */ + public Identifier getLogicalName(); + + /** + * Get the table number. + * + * @return the table number. + */ + public int getTableNumber(); + + /** + * Get the primary key definition for this table spec. + * + * @return The PK definition. + */ + public PrimaryKey getPrimaryKey(); + + /** + * Factory method for creating a {@link Column} associated with this container. + * + * @param name The column name + * + * @return The generated column + */ + public Column locateOrCreateColumn(String name); + + /** + * Attempt to locate a column with the given name + * + * @param name The column name + * + * @return The located column, or {@code null} is none found + */ + public Column locateColumn(String name); + + public Column createColumn(String name); + + public Column createColumn(Identifier name); + + /** + * Factory method for creating a {@link DerivedValue} associated with this container. + * + * @param fragment The value expression + * + * @return The generated value. + */ + public DerivedValue locateOrCreateDerivedValue(String fragment); + + /** + * Generates a unique ID for the specified columns in this table. + * + * @param columns - the columns used to generate the ID + * @return the ID unique to the specified columns in this table. + */ + public int columnListId(Iterable columns); + + /** + * Retrieve a read-only version of foreign keys currently defined for this table. + * + * @return a reforeign keys defined on this table. + */ + public Iterable getForeignKeys(); + + /** + * Locate a foreign key by name + * + * @param name The name of the foreign key to locate + * + * @return The foreign key, or {@code null} to indicate none with that name was found. + */ + public ForeignKey locateForeignKey(String name); + + /** + * Locate foreign keys with {@code this} table as source and the passed table as the target. + * + * @param targetTable The table that is the target of interest. + * + * @return The matching foreign keys, or {@code null} to indicate none were found. + */ + public Iterable locateForeignKey(TableSpecification targetTable); + + /** + * Create a foreign key targeting the specified table as the target. Columns should be handled through the + * returned reference. + * + * @param targetTable The table that is the target of the foreign key + * @param name The (optional) name of the foreign key + * @param createConstraint + * + * @return The foreign key reference. + */ + public ForeignKey createForeignKey(TableSpecification targetTable, String name, boolean createConstraint); + + public ForeignKey createForeignKey(TableSpecification targetTable, Identifier name, boolean createConstraint); + + public Iterable getIndexes(); + + public void addIndex(Index idx); + + public Iterable getUniqueKeys(); + + public void addUniqueKey(UniqueKey uk); + + public boolean hasUniqueKey(Column column); + + public Iterable getCheckConstraints(); + + public void addCheckConstraint(String checkCondition); + + public Iterable getComments(); + + public void addComment(String comment); + + public String getQualifiedName(Dialect dialect); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java new file mode 100644 index 000000000000..d3ffc92e3ff4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + + +/** + * Models a SQL INDEX defined as UNIQUE + * + * @author Gavin King + * @author Steve Ebersole + * @author Brett Meyer + */ +public class UniqueKey extends AbstractConstraint { + + public UniqueKey() { + this( null, null ); + } + + protected UniqueKey(Table table, Identifier name) { + super( table, name ); + } + + @Override + public String getExportIdentifier() { + StringBuilder sb = new StringBuilder( getTable().getLoggableValueQualifier() ); + sb.append( ".UK" ); + for ( Column column : getColumns() ) { + sb.append( '_' ).append( column.getColumnName().getText() ); + } + return sb.toString(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java new file mode 100644 index 000000000000..0c41d56b1b2c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java @@ -0,0 +1,110 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by + * third-party contributors as indicated by either @author tags or express + * copyright attribution statements applied by the authors. All + * third-party contributions are distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.dialect.Dialect; + +/** + * Models a value within a {@link ValueContainer}. Concretely, either a {@link Column column} or a + * {@link DerivedValue derived value}. + * + * @author Steve Ebersole + */ +public interface Value { + + public enum ValueType { + COLUMN, + DERIVED_VALUE + } + + /** + * Return the value type. + * + * @return The value type + */ + public ValueType getValueType(); + + /** + * Retrieve the JDBC data type of this value. + * + * @return The value's JDBC data type + */ + public JdbcDataType getJdbcDataType(); + + /** + * Obtain the string representation of this value usable in log statements. + * + * @return The loggable representation + */ + public String toLoggableString(); + + /** + * For any column name, generate an alias that is unique + * to that column name, and (optionally) unique across tables, and + * within alias size constraints determined by + * {@link org.hibernate.dialect.Dialect#getMaxAliasLength()}. + * + * todo : not sure this contract is the best place for this method + * + * @param dialect the dialect. + * @param tableSpecification, if non-null, the table specification to use + * to make the alias unambiguous across tables; if null, there is no need to need + * to use the table to make the alias unambiguous across tables. + * @return the alias. + */ + public String getAlias(Dialect dialect, TableSpecification tableSpecification); + + /** + * Validate the value against the incoming JDBC type code array, both in terms of number of types + * and compatibility of types. + * + * @param typeCodes The type codes. + * + * @throws org.hibernate.metamodel.ValidationException if validaton fails. + */ + public void validateJdbcTypes(JdbcCodes typeCodes); + + /** + * Used to track JDBC type usage throughout a series of potential recursive calls to component + * values since we do not know ahead of time which values correspond to which indexes of the + * jdbc type array. + */ + public static class JdbcCodes { + private final int[] typeCodes; + private int index = 0; + + public JdbcCodes(int[] typeCodes) { + this.typeCodes = typeCodes; + } + + public int nextJdbcCde() { + return typeCodes[index++]; + } + + public int getIndex() { + return index; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java index 5523716f4e22..301f7e14c856 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java @@ -21,22 +21,27 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.relational; +package org.hibernate.metamodel.spi.relational; + +import java.util.List; /** * Contract for data containers (what the ANSI SQL spec calls "table specifications") to which we can map - * entity state. The two flavors here are {@link Table physical table} and {@link InLineView inline view}, but a - * {@link Tuple} is a conceptual value container as well. + * entity state. The two flavors here are {@link Table physical table} and {@link InLineView inline view}. * * @author Steve Ebersole */ public interface ValueContainer { /** * Obtain an iterator over this containers current set of value definitions. + *

    + * The returned list is unmodifiable! * * @return Iterator over value definitions. */ - public Iterable values(); + public List values(); + + public boolean hasValue(Value value); /** * Get a qualifier which can be used to qualify {@link Value values} belonging to this container in diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/package.html b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/package.html similarity index 100% rename from hibernate-core/src/main/java/org/hibernate/metamodel/relational/package.html rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/package.html diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 70e0647ce631..72db73ef35c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -28,6 +28,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -39,15 +40,17 @@ import org.hibernate.MappingException; import org.hibernate.QueryException; import org.hibernate.TransientObjectException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.cache.spi.entry.CacheEntryStructure; import org.hibernate.cache.spi.entry.StructuredCollectionCacheEntry; import org.hibernate.cache.spi.entry.StructuredMapCacheEntry; import org.hibernate.cache.spi.entry.UnstructuredCacheEntry; -import org.hibernate.cfg.Configuration; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.spi.EntityKey; @@ -61,21 +64,31 @@ import org.hibernate.id.IdentifierGenerator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.FilterAliasGenerator; +import org.hibernate.internal.FilterConfiguration; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectations; import org.hibernate.loader.collection.CollectionInitializer; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Formula; -import org.hibernate.mapping.IdentifierCollection; -import org.hibernate.mapping.IndexedCollection; -import org.hibernate.mapping.List; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.Table; import org.hibernate.metadata.CollectionMetadata; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.PrimitiveTypeDescriptor; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.ListBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingManyToMany; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.PropertyMapping; @@ -107,6 +120,7 @@ import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; +import org.hibernate.type.PrimitiveType; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -246,15 +260,15 @@ public abstract class AbstractCollectionPersister private Map collectionPropertyColumnNames = new HashMap(); public AbstractCollectionPersister( - final Collection collection, - final CollectionRegionAccessStrategy cacheAccessStrategy, - final Configuration cfg, - final SessionFactoryImplementor factory) throws MappingException, CacheException { + AbstractPluralAttributeBinding collection, + CollectionRegionAccessStrategy cacheAccessStrategy, + MetadataImplementor metadataImplementor, + SessionFactoryImplementor factory) throws MappingException, CacheException { this.factory = factory; this.cacheAccessStrategy = cacheAccessStrategy; if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) { - cacheEntryStructure = collection.isMap() + cacheEntryStructure = collection.getAttribute().getPluralAttributeNature() == PluralAttributeNature.MAP ? StructuredMapCacheEntry.INSTANCE : StructuredCollectionCacheEntry.INSTANCE; } @@ -262,39 +276,55 @@ public AbstractCollectionPersister( cacheEntryStructure = UnstructuredCacheEntry.INSTANCE; } + dialect = factory.getDialect(); sqlExceptionHelper = factory.getSQLExceptionHelper(); - collectionType = collection.getCollectionType(); - role = collection.getRole(); - entityName = collection.getOwnerEntityName(); + if ( !collection.getHibernateTypeDescriptor().getResolvedTypeMapping().isCollectionType() ) { + throw new MappingException( + String.format( + "Unexpected resolved type for %s; expected a CollectionType; instead it is %s", + collection.getAttribute().getRole(), + collection.getHibernateTypeDescriptor().getResolvedTypeMapping() ) + ); + } + + collectionType = (CollectionType) collection.getHibernateTypeDescriptor().getResolvedTypeMapping(); + role = collection.getAttribute().getRole(); + entityName = collection.getContainer().seekEntityBinding().getEntityName(); ownerPersister = factory.getEntityPersister( entityName ); - queryLoaderName = collection.getLoaderName(); - nodeName = collection.getNodeName(); + queryLoaderName = collection.getCustomLoaderName(); + // TODO: is nodeName obsolete? + //nodeName = collection.getNodeName(); + nodeName = null; isMutable = collection.isMutable(); - mappedByProperty = collection.getMappedByProperty(); - Table table = collection.getCollectionTable(); - fetchMode = collection.getElement().getFetchMode(); - elementType = collection.getElement().getType(); + TableSpecification table = collection.getPluralAttributeKeyBinding().getCollectionTable(); + fetchMode = collection.getFetchMode(); + elementType = collection.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(); // isSet = collection.isSet(); // isSorted = collection.isSorted(); - isPrimitiveArray = collection.isPrimitiveArray(); - isArray = collection.isArray(); - subselectLoadable = collection.isSubselectLoadable(); - - qualifiedTableName = table.getQualifiedName( - dialect, - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); + isArray = collectionType.isArrayType(); + isPrimitiveArray = + isArray && + PrimitiveType.class.isInstance( + collection.getPluralAttributeElementBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping() + ); + subselectLoadable = collection.getFetchStyle() == FetchStyle.SUBSELECT; + + qualifiedTableName = table.getQualifiedName( dialect ); - int spacesSize = 1 + collection.getSynchronizedTables().size(); - spaces = new String[spacesSize]; + // TODO: fix this when synchronized tables are available + spaces = new String[1]; spaces[0] = qualifiedTableName; - Iterator iter = collection.getSynchronizedTables().iterator(); - for ( int i = 1; i < spacesSize; i++ ) { - spaces[i] = (String) iter.next(); - } + //int spacesSize = 1 + collection.getSynchronizedTables().size(); + //spaces = new String[spacesSize]; + //spaces[0] = qualifiedTableName; + //Iterator iter = collection.getSynchronizedTables().iterator(); + //for ( int i = 1; i < spacesSize; i++ ) { + // spaces[i] = (String) iter.next(); + //} sqlWhereString = StringHelper.isNotEmpty( collection.getWhere() ) ? "( " + collection.getWhere() + ") " : null; hasWhere = sqlWhereString != null; @@ -302,7 +332,9 @@ public AbstractCollectionPersister( Template.renderWhereStringTemplate( sqlWhereString, dialect, factory.getSqlFunctionRegistry() ) : null; - hasOrphanDelete = collection.hasOrphanDelete(); + hasOrphanDelete = + collection.getPluralAttributeElementBinding() instanceof Cascadeable && + ( (Cascadeable) collection.getPluralAttributeElementBinding() ).getCascadeStyle().hasOrphanDelete(); int batch = collection.getBatchSize(); if ( batch == -1 ) { @@ -310,44 +342,44 @@ public AbstractCollectionPersister( } batchSize = batch; - isVersioned = collection.isOptimisticLocked(); + isVersioned = collection.isIncludedInOptimisticLocking(); // KEY - keyType = collection.getKey().getType(); - iter = collection.getKey().getColumnIterator(); - int keySpan = collection.getKey().getColumnSpan(); + PluralAttributeKeyBinding keyBinding = collection.getPluralAttributeKeyBinding(); + keyType = keyBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + + int keySpan = keyBinding.getRelationalValueBindings().size(); keyColumnNames = new String[keySpan]; keyColumnAliases = new String[keySpan]; int k = 0; - while ( iter.hasNext() ) { + for ( RelationalValueBinding keyRelationalValueBinding : keyBinding.getRelationalValueBindings() ) { + org.hibernate.metamodel.spi.relational.Column keyColumn = + (org.hibernate.metamodel.spi.relational.Column) keyRelationalValueBinding.getValue(); // NativeSQL: collect key column and auto-aliases - Column col = ( (Column) iter.next() ); - keyColumnNames[k] = col.getQuotedName( dialect ); - keyColumnAliases[k] = col.getAlias( dialect, collection.getOwner().getRootTable() ); + keyColumnNames[k] = keyColumn.getColumnName().getText( dialect ); + // TODO: does the owner root table need to be in alias? + keyColumnAliases[k] = keyColumn.getAlias( + dialect, + collection.getContainer().seekEntityBinding().getPrimaryTable() + ); + // keyColumnAliases[k] = col.getAlias( dialect, collection.getOwner().getRootTable() ); k++; } - // unquotedKeyColumnNames = StringHelper.unQuote(keyColumnAliases); - // ELEMENT - String elemNode = collection.getElementNodeName(); if ( elementType.isEntityType() ) { String entityName = ( (EntityType) elementType ).getAssociatedEntityName(); elementPersister = factory.getEntityPersister( entityName ); - if ( elemNode == null ) { - elemNode = cfg.getClassMapping( entityName ).getNodeName(); - } - // NativeSQL: collect element column and auto-aliases - } else { elementPersister = null; } - elementNodeName = elemNode; - - int elementSpan = collection.getElement().getColumnSpan(); + elementNodeName = null; + int elementSpan = collection.getPluralAttributeElementBinding().getRelationalValueContainer().relationalValueBindings() == null + ? 0 + : collection.getPluralAttributeElementBinding().getRelationalValueContainer().relationalValueBindings().size(); elementColumnAliases = new String[elementSpan]; elementColumnNames = new String[elementSpan]; elementColumnWriters = new String[elementSpan]; @@ -360,29 +392,33 @@ public AbstractCollectionPersister( boolean isPureFormula = true; boolean hasNotNullableColumns = false; int j = 0; - iter = collection.getElement().getColumnIterator(); - while ( iter.hasNext() ) { - Selectable selectable = (Selectable) iter.next(); - elementColumnAliases[j] = selectable.getAlias( dialect, table ); - if ( selectable.isFormula() ) { - Formula form = (Formula) selectable; - elementFormulaTemplates[j] = form.getTemplate( dialect, factory.getSqlFunctionRegistry() ); - elementFormulas[j] = form.getFormula(); - } - else { - Column col = (Column) selectable; - elementColumnNames[j] = col.getQuotedName( dialect ); - elementColumnWriters[j] = col.getWriteExpr(); - elementColumnReaders[j] = col.getReadExpr( dialect ); - elementColumnReaderTemplates[j] = col.getTemplate( dialect, factory.getSqlFunctionRegistry() ); - elementColumnIsSettable[j] = true; - elementColumnIsInPrimaryKey[j] = !col.isNullable(); - if ( !col.isNullable() ) { - hasNotNullableColumns = true; + if ( elementSpan > 0 ) { + for ( RelationalValueBinding relationalValueBinding : collection.getPluralAttributeElementBinding().getRelationalValueContainer().relationalValueBindings() ) { + final Value value = relationalValueBinding.getValue(); + elementColumnAliases[j] = value.getAlias( dialect, table ); + if ( DerivedValue.class.isInstance( value ) ) { + DerivedValue form = (DerivedValue) value; + elementFormulaTemplates[j] = getTemplateFromString( form.getExpression(), factory); + elementFormulas[j] = form.getExpression(); } - isPureFormula = false; + else { + org.hibernate.metamodel.spi.relational.Column col = + (org.hibernate.metamodel.spi.relational.Column) value; + elementColumnNames[j] = col.getColumnName().getText( dialect ); + elementColumnWriters[j] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); + elementColumnReaders[j] = col.getReadFragment() == null ? + col.getColumnName().getText( factory.getDialect() ) : + col.getReadFragment(); + elementColumnReaderTemplates[j] = getTemplateFromColumn( col, factory ); + elementColumnIsSettable[j] = true; + elementColumnIsInPrimaryKey[j] = !col.isNullable(); + if ( !col.isNullable() ) { + hasNotNullableColumns = true; + } + isPureFormula = false; + } + j++; } - j++; } elementIsPureFormula = isPureFormula; @@ -395,45 +431,43 @@ public AbstractCollectionPersister( // INDEX AND ROW SELECT - hasIndex = collection.isIndexed(); + hasIndex = collection.hasIndex(); + + indexNodeName = null; + if ( hasIndex ) { // NativeSQL: collect index column and auto-aliases - IndexedCollection indexedCollection = (IndexedCollection) collection; - indexType = indexedCollection.getIndex().getType(); - int indexSpan = indexedCollection.getIndex().getColumnSpan(); - iter = indexedCollection.getIndex().getColumnIterator(); + IndexedPluralAttributeBinding indexedBinding = (IndexedPluralAttributeBinding) collection; + PluralAttributeIndexBinding indexBinding = indexedBinding.getPluralAttributeIndexBinding(); + indexType = indexBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + baseIndex = indexBinding instanceof ListBinding ? ( ( ListBinding ) indexBinding ).base() : 0; + final java.util.List indexRelationalValueBindings = indexBinding.getRelationalValueBindings(); + int indexSpan = indexRelationalValueBindings.size(); + boolean hasFormulas = false; indexColumnNames = new String[indexSpan]; indexFormulaTemplates = new String[indexSpan]; indexFormulas = new String[indexSpan]; indexColumnIsSettable = new boolean[indexSpan]; indexColumnAliases = new String[indexSpan]; - int i = 0; - boolean hasFormula = false; - while ( iter.hasNext() ) { - Selectable s = (Selectable) iter.next(); - indexColumnAliases[i] = s.getAlias( dialect ); - if ( s.isFormula() ) { - Formula indexForm = (Formula) s; - indexFormulaTemplates[i] = indexForm.getTemplate( dialect, factory.getSqlFunctionRegistry() ); - indexFormulas[i] = indexForm.getFormula(); - hasFormula = true; - } - else { - Column indexCol = (Column) s; - indexColumnNames[i] = indexCol.getQuotedName( dialect ); - indexColumnIsSettable[i] = true; + for ( int i = 0 ; i < indexSpan ; i++ ) { + final RelationalValueBinding rb = indexRelationalValueBindings.get( i ); + final Value value = rb.getValue(); + indexColumnAliases[ i ] = value.getAlias( dialect, + collection.getContainer().seekEntityBinding().getPrimaryTable() ); + if ( !rb.isDerived() ) { + indexColumnIsSettable[ i ] = true; + org.hibernate.metamodel.spi.relational.Column column = + ( org.hibernate.metamodel.spi.relational.Column ) value; + indexColumnNames[ i ] = column.getColumnName().getText( dialect ); + } else { + DerivedValue derivedValue = ( DerivedValue ) value; + indexFormulaTemplates[ i ] = getTemplateFromString( derivedValue.getExpression(), factory); + indexFormulas[ i ] = derivedValue.getExpression(); + hasFormulas = true; } - i++; } - indexContainsFormula = hasFormula; - baseIndex = indexedCollection.isList() ? - ( (List) indexedCollection ).getBaseIndex() : 0; - - indexNodeName = indexedCollection.getIndexNodeName(); - - } - else { - indexContainsFormula = false; + this.indexContainsFormula = hasFormulas; + } else { indexColumnIsSettable = null; indexFormulaTemplates = null; indexFormulas = null; @@ -441,104 +475,102 @@ public AbstractCollectionPersister( indexColumnNames = null; indexColumnAliases = null; baseIndex = 0; - indexNodeName = null; + indexContainsFormula = false; } - hasIdentifier = collection.isIdentified(); - if ( hasIdentifier ) { - if ( collection.isOneToMany() ) { - throw new MappingException( "one-to-many collections with identifiers are not supported" ); - } - IdentifierCollection idColl = (IdentifierCollection) collection; - identifierType = idColl.getIdentifier().getType(); - iter = idColl.getIdentifier().getColumnIterator(); - Column col = (Column) iter.next(); - identifierColumnName = col.getQuotedName( dialect ); - identifierColumnAlias = col.getAlias( dialect ); - // unquotedIdentifierColumnName = identifierColumnAlias; - identifierGenerator = idColl.getIdentifier().createIdentifierGenerator( - cfg.getIdentifierGeneratorFactory(), - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName(), - null - ); - } - else { - identifierType = null; - identifierColumnName = null; - identifierColumnAlias = null; - // unquotedIdentifierColumnName = null; - identifierGenerator = null; - } + hasIdentifier = collection.getAttribute().getPluralAttributeNature() == PluralAttributeNature.ID_BAG; + // TODO: fix this when IdBags are supported. + //if ( hasIdentifier ) { + //} + //else { + identifierType = null; + identifierColumnName = null; + identifierColumnAlias = null; + // unquotedIdentifierColumnName = null; + identifierGenerator = null; + //} // GENERATE THE SQL: // sqlSelectString = sqlSelectString(); // sqlSelectRowString = sqlSelectRowString(); - if ( collection.getCustomSQLInsert() == null ) { + if ( collection.getCustomSqlInsert() == null ) { sqlInsertRowString = generateInsertRowString(); insertCallable = false; insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT; } else { - sqlInsertRowString = collection.getCustomSQLInsert(); - insertCallable = collection.isCustomInsertCallable(); - insertCheckStyle = collection.getCustomSQLInsertCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( collection.getCustomSQLInsert(), insertCallable ) - : collection.getCustomSQLInsertCheckStyle(); + final CustomSQL customSqlInsert = collection.getCustomSqlInsert(); + sqlInsertRowString = customSqlInsert.getSql(); + insertCallable = customSqlInsert.isCallable(); + insertCheckStyle = customSqlInsert.getCheckStyle() == null + ? ExecuteUpdateResultCheckStyle.determineDefault( customSqlInsert.getSql(), insertCallable ) + : customSqlInsert.getCheckStyle(); } - if ( collection.getCustomSQLUpdate() == null ) { + if ( collection.getCustomSqlUpdate() == null ) { sqlUpdateRowString = generateUpdateRowString(); updateCallable = false; updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT; } else { - sqlUpdateRowString = collection.getCustomSQLUpdate(); - updateCallable = collection.isCustomUpdateCallable(); - updateCheckStyle = collection.getCustomSQLUpdateCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( collection.getCustomSQLUpdate(), insertCallable ) - : collection.getCustomSQLUpdateCheckStyle(); + final CustomSQL customSqlUpdate = collection.getCustomSqlUpdate(); + sqlUpdateRowString = customSqlUpdate.getSql(); + updateCallable = customSqlUpdate.isCallable(); + updateCheckStyle = customSqlUpdate.getCheckStyle() == null + ? ExecuteUpdateResultCheckStyle.determineDefault( customSqlUpdate.getSql(), insertCallable ) + : customSqlUpdate.getCheckStyle(); } - if ( collection.getCustomSQLDelete() == null ) { + if ( collection.getCustomSqlDelete() == null ) { sqlDeleteRowString = generateDeleteRowString(); deleteCallable = false; deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE; } else { - sqlDeleteRowString = collection.getCustomSQLDelete(); - deleteCallable = collection.isCustomDeleteCallable(); + final CustomSQL customSqlDelete = collection.getCustomSqlDelete(); + sqlDeleteRowString = customSqlDelete.getSql(); + deleteCallable = customSqlDelete.isCallable(); deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE; } - if ( collection.getCustomSQLDeleteAll() == null ) { + if ( collection.getCustomSqlDeleteAll() == null ) { sqlDeleteString = generateDeleteString(); deleteAllCallable = false; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE; } else { - sqlDeleteString = collection.getCustomSQLDeleteAll(); - deleteAllCallable = collection.isCustomDeleteAllCallable(); + final CustomSQL customSqlDeleteAll = collection.getCustomSqlDeleteAll(); + sqlDeleteString = customSqlDeleteAll.getSql(); + deleteAllCallable = customSqlDeleteAll.isCallable(); deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE; } - sqlSelectSizeString = generateSelectSizeString( collection.isIndexed() && !collection.isMap() ); + sqlSelectSizeString = generateSelectSizeString( + collection.hasIndex() && + collection.getAttribute().getPluralAttributeNature() != PluralAttributeNature.MAP + ); sqlDetectRowByIndexString = generateDetectRowByIndexString(); sqlDetectRowByElementString = generateDetectRowByElementString(); sqlSelectRowByIndexString = generateSelectRowByIndexString(); logStaticSQL(); - isLazy = collection.isLazy(); - isExtraLazy = collection.isExtraLazy(); - - isInverse = collection.isInverse(); + isLazy = collection.getFetchTiming() != FetchTiming.IMMEDIATE; + isExtraLazy = collection.getFetchTiming() == FetchTiming.EXTRA_LAZY; - if ( collection.isArray() ) { - elementClass = ( (org.hibernate.mapping.Array) collection ).getElementClass(); + isInverse = keyBinding.isInverse(); + if ( isArray ) { + // TODO: Move into a util? + final JavaTypeDescriptor descriptor = collection.getAttribute().getElementType().getDescriptor(); + if (PrimitiveTypeDescriptor.class.isInstance( descriptor )) { + elementClass = ( (PrimitiveTypeDescriptor) descriptor ).getClassType(); + } + else { + final ClassLoaderService cls = factory.getServiceRegistry().getService( ClassLoaderService.class ); + elementClass = cls.classForName( descriptor.getName().toString() ); + } } else { // for non-arrays, we don't need to know the element class @@ -553,13 +585,13 @@ public AbstractCollectionPersister( elementFormulaTemplates, (CompositeType) elementType, factory - ); + ); } else if ( !elementType.isEntityType() ) { elementPropertyMapping = new ElementPropertyMapping( elementColumnNames, elementType - ); + ); } else { if ( elementPersister instanceof PropertyMapping ) { // not all classpersisters implement PropertyMapping! @@ -569,7 +601,7 @@ else if ( !elementType.isEntityType() ) { elementPropertyMapping = new ElementPropertyMapping( elementColumnNames, elementType - ); + ); } } @@ -588,28 +620,41 @@ else if ( !elementType.isEntityType() ) { } // Handle any filters applied to this collection - filterHelper = new FilterHelper( collection.getFilters(), factory); - - // Handle any filters applied to this collection for many-to-many - manyToManyFilterHelper = new FilterHelper( collection.getManyToManyFilters(), factory); - manyToManyWhereString = StringHelper.isNotEmpty( collection.getManyToManyWhere() ) ? - "( " + collection.getManyToManyWhere() + ")" : - null; - manyToManyWhereTemplate = manyToManyWhereString == null ? - null : - Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() ); + filterHelper = new FilterHelper( collection.getFilterConfigurations(), factory ); + + if ( collection.getPluralAttributeElementBinding() + .getNature() == PluralAttributeElementNature.MANY_TO_MANY ) { + final PluralAttributeElementBindingManyToMany manyToManyElementBinding = + (PluralAttributeElementBindingManyToMany) collection.getPluralAttributeElementBinding(); + manyToManyFilterHelper = new FilterHelper( manyToManyElementBinding.getFilterConfigurations(), factory ); + manyToManyWhereString = StringHelper.isNotEmpty( manyToManyElementBinding.getManyToManyWhere() ) ? + "( " +manyToManyElementBinding.getManyToManyWhere() + ")" : + null; + manyToManyWhereTemplate = manyToManyWhereString == null ? + null : + Template.renderWhereStringTemplate( + manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() + ); - hasManyToManyOrder = collection.getManyToManyOrdering() != null; - if ( hasManyToManyOrder ) { - manyToManyOrderByTranslation = Template.translateOrderBy( - collection.getManyToManyOrdering(), - new ColumnMapperImpl(), - factory, - dialect, - factory.getSqlFunctionRegistry() - ); + hasManyToManyOrder = manyToManyElementBinding.getManyToManyOrderBy() != null; + if ( hasManyToManyOrder ) { + manyToManyOrderByTranslation = Template.translateOrderBy( + manyToManyElementBinding.getManyToManyOrderBy(), + new ColumnMapperImpl(), + factory, + dialect, + factory.getSqlFunctionRegistry() + ); + } + else { + manyToManyOrderByTranslation = null; + } } else { + manyToManyFilterHelper = new FilterHelper( Collections.emptyList(), factory ); + manyToManyWhereString = null; + manyToManyWhereTemplate = null; + hasManyToManyOrder = false; manyToManyOrderByTranslation = null; } @@ -671,6 +716,24 @@ private String[] formulaTemplates(String reference, int expectedSize) { } } + protected static String getTemplateFromString(String string, SessionFactoryImplementor factory) { + return string == null ? + null : + Template.renderWhereStringTemplate( string, factory.getDialect(), factory.getSqlFunctionRegistry() ); + } + + public String getTemplateFromColumn(org.hibernate.metamodel.spi.relational.Column column, SessionFactoryImplementor factory) { + String templateString; + if ( column.getReadFragment() != null ) { + templateString = getTemplateFromString( column.getReadFragment(), factory ); + } + else { + String columnName = column.getColumnName().getText( factory.getDialect() ); + templateString = Template.TEMPLATE + '.' + columnName; + } + return templateString; + } + @Override public void postInstantiate() throws MappingException { initializer = queryLoaderName == null ? @@ -1703,11 +1766,13 @@ protected abstract int doUpdateRows(Serializable key, PersistentCollection colle public void processQueuedOps(PersistentCollection collection, Serializable key, SessionImplementor session) throws HibernateException { if ( collection.hasQueuedOperations() ) { - doProcessQueuedOps( collection, key, session ); + int nextIndex = getSize( key, session ); + doProcessQueuedOps( collection, key, nextIndex, session ); } } - protected abstract void doProcessQueuedOps(PersistentCollection collection, Serializable key, SessionImplementor session) + protected abstract void doProcessQueuedOps(PersistentCollection collection, Serializable key, + int nextIndex, SessionImplementor session) throws HibernateException; @Override diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java index c0b7582a2b3e..e76f3925e31f 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java @@ -50,6 +50,8 @@ import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.loader.collection.SubselectCollectionLoader; import org.hibernate.mapping.Collection; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; import org.hibernate.persister.entity.Joinable; import org.hibernate.pretty.MessageHelper; import org.hibernate.sql.Delete; @@ -69,12 +71,13 @@ public boolean isCascadeDeleteEnabled() { return false; } + @SuppressWarnings( {"UnusedDeclaration"}) public BasicCollectionPersister( - Collection collection, + AbstractPluralAttributeBinding collection, CollectionRegionAccessStrategy cacheAccessStrategy, - Configuration cfg, + MetadataImplementor metadataImplementor, SessionFactoryImplementor factory) throws MappingException, CacheException { - super( collection, cacheAccessStrategy, cfg, factory ); + super( collection, cacheAccessStrategy, metadataImplementor, factory ); } /** @@ -155,7 +158,8 @@ else if ( hasIndex && !indexContainsFormula ) { } @Override - protected void doProcessQueuedOps(PersistentCollection collection, Serializable id, SessionImplementor session) + protected void doProcessQueuedOps(PersistentCollection collection, Serializable id, + int nextIndex, SessionImplementor session) throws HibernateException { // nothing to do } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index cf86a134e729..b790acc7a858 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -34,7 +34,6 @@ import org.hibernate.MappingException; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; -import org.hibernate.cfg.Configuration; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.spi.LoadQueryInfluencers; @@ -49,7 +48,10 @@ import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.loader.collection.SubselectOneToManyLoader; import org.hibernate.loader.entity.CollectionElementLoader; -import org.hibernate.mapping.Collection; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.pretty.MessageHelper; @@ -67,6 +69,28 @@ public class OneToManyPersister extends AbstractCollectionPersister { private final boolean keyIsNullable; private final boolean keyIsUpdateable; + @SuppressWarnings( {"UnusedDeclaration"}) + public OneToManyPersister( + AbstractPluralAttributeBinding collection, + CollectionRegionAccessStrategy cacheAccessStrategy, + MetadataImplementor metadataImplementor, + SessionFactoryImplementor factory) throws MappingException, CacheException { + super( collection, cacheAccessStrategy, metadataImplementor, factory ); + if ( collection.getPluralAttributeElementBinding().getNature() != + PluralAttributeElementNature.ONE_TO_MANY ) { + throw new AssertionError( + String.format( "Unexpected plural attribute nature; expected=(%s), actual=(%s)", + PluralAttributeElementNature.ONE_TO_MANY, + collection.getPluralAttributeElementBinding().getNature() + ) + ); + } + final PluralAttributeKeyBinding keyBinding = collection.getPluralAttributeKeyBinding(); + cascadeDeleteEnabled = keyBinding.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete(); + keyIsNullable = keyBinding.isNullable(); + keyIsUpdateable = keyBinding.isUpdatable(); + } + @Override protected boolean isRowDeleteEnabled() { return keyIsUpdateable && keyIsNullable; @@ -81,17 +105,6 @@ public boolean isCascadeDeleteEnabled() { return cascadeDeleteEnabled; } - public OneToManyPersister( - Collection collection, - CollectionRegionAccessStrategy cacheAccessStrategy, - Configuration cfg, - SessionFactoryImplementor factory) throws MappingException, CacheException { - super( collection, cacheAccessStrategy, cfg, factory ); - cascadeDeleteEnabled = collection.getKey().isCascadeDeleteEnabled() && - factory.getDialect().supportsCascadeDelete(); - keyIsNullable = collection.getKey().isNullable(); - keyIsUpdateable = collection.getKey().isUpdateable(); - } /** * Generate the SQL UPDATE that updates all the foreign keys to null @@ -182,34 +195,33 @@ protected String generateDeleteRowString() { public void recreate(PersistentCollection collection, Serializable id, SessionImplementor session) throws HibernateException { super.recreate( collection, id, session ); - writeIndex( collection, collection.entries( this ), id, session ); + writeIndex( collection, collection.entries( this ), id, 0, session ); } @Override public void insertRows(PersistentCollection collection, Serializable id, SessionImplementor session) throws HibernateException { super.insertRows( collection, id, session ); - writeIndex( collection, collection.entries( this ), id, session ); + writeIndex( collection, collection.entries( this ), id, 0, session ); } @Override - protected void doProcessQueuedOps(PersistentCollection collection, Serializable id, SessionImplementor session) - throws HibernateException { - writeIndex( collection, collection.queuedAdditionIterator(), id, session ); + protected void doProcessQueuedOps(PersistentCollection collection, Serializable id, + int nextIndex, SessionImplementor session) throws HibernateException { + writeIndex( collection, collection.queuedAdditionIterator(), id, nextIndex, session ); } - private void writeIndex(PersistentCollection collection, Iterator entries, Serializable id, SessionImplementor session) { + private void writeIndex(PersistentCollection collection, Iterator entries, Serializable id, + int nextIndex, SessionImplementor session) { // If one-to-many and inverse, still need to create the index. See HHH-5732. if ( isInverse && hasIndex && !indexContainsFormula ) { try { if ( entries.hasNext() ) { Expectation expectation = Expectations.appropriateExpectation( getUpdateCheckStyle() ); - int i = 0; - int count = 0; while ( entries.hasNext() ) { final Object entry = entries.next(); - if ( entry != null && collection.entryExists( entry, i ) ) { + if ( entry != null && collection.entryExists( entry, nextIndex ) ) { int offset = 1; PreparedStatement st = null; boolean callable = isUpdateCallable(); @@ -238,9 +250,9 @@ private void writeIndex(PersistentCollection collection, Iterator entries, Seria try { offset += expectation.prepare( st ); if ( hasIdentifier ) { - offset = writeIdentifier( st, collection.getIdentifier( entry, i ), offset, session ); + offset = writeIdentifier( st, collection.getIdentifier( entry, nextIndex ), offset, session ); } - offset = writeIndex( st, collection.getIndex( entry, i, this ), offset, session ); + offset = writeIndex( st, collection.getIndex( entry, nextIndex, this ), offset, session ); offset = writeElement( st, collection.getElement( entry ), offset, session ); if ( useBatch ) { @@ -252,7 +264,6 @@ private void writeIndex(PersistentCollection collection, Iterator entries, Seria else { expectation.verifyOutcome( session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( st ), st, -1 ); } - count++; } catch ( SQLException sqle ) { if ( useBatch ) { @@ -267,7 +278,7 @@ private void writeIndex(PersistentCollection collection, Iterator entries, Seria } } - i++; + nextIndex++; } } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 4f432b28c03c..eca85d72c974 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -68,6 +68,7 @@ import org.hibernate.engine.internal.StatefulPersistenceContext; import org.hibernate.engine.internal.Versioning; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.spi.CachedNaturalIdValueSource; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; @@ -75,7 +76,6 @@ import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper; @@ -88,7 +88,6 @@ import org.hibernate.id.insert.Binder; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.FilterConfiguration; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; @@ -99,19 +98,26 @@ import org.hibernate.loader.entity.CascadeEntityLoader; import org.hibernate.loader.entity.EntityLoader; import org.hibernate.loader.entity.UniqueEntityLoader; -import org.hibernate.mapping.Column; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Selectable; import org.hibernate.metadata.ClassMetadata; -import org.hibernate.metamodel.binding.AssociationAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.Value; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.Fetchable; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper; import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; @@ -127,6 +133,7 @@ import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.Template; import org.hibernate.sql.Update; +import org.hibernate.tool.schema.internal.TemporaryTableExporter; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.InDatabaseValueGenerationStrategy; import org.hibernate.tuple.InMemoryValueGenerationStrategy; @@ -178,7 +185,7 @@ public abstract class AbstractEntityPersister private final boolean hasSubselectLoadableCollections; protected final String rowIdName; - private final Set lazyProperties; + private final Set lazyProperties; // The optional SQL string defined in the where attribute private final String sqlWhereString; @@ -238,8 +245,8 @@ public abstract class AbstractEntityPersister private final Set affectingFetchProfileNames = new HashSet(); - private final Map uniqueKeyLoaders = new HashMap(); - private final Map lockers = new HashMap(); + private final Map uniqueKeyLoaders = new HashMap(); + private final Map lockers = new HashMap(); private final Map loaders = new HashMap(); // SQL strings @@ -281,8 +288,8 @@ public abstract class AbstractEntityPersister private final String temporaryIdTableName; private final String temporaryIdTableDDL; - private final Map subclassPropertyAliases = new HashMap(); - private final Map subclassPropertyColumnNames = new HashMap(); + private final Map subclassPropertyAliases = new HashMap(); + private final Map subclassPropertyColumnNames = new HashMap(); protected final BasicEntityPropertyMapping propertyMapping; @@ -394,6 +401,19 @@ protected String[] getSQLLazyUpdateByRowIdStrings() { return result; } + protected static void initializeCustomSql( + CustomSQL customSql, + int i, + String[] sqlStrings, + boolean[] callable, + ExecuteUpdateResultCheckStyle[] checkStyles) { + sqlStrings[i] = customSql != null ? customSql.getSql(): null; + callable[i] = customSql != null && customSql.isCallable(); + checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ? + customSql.getCheckStyle() : + ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] ); + } + protected String getSQLSnapshotSelectString() { return sqlSnapshotSelectString; } @@ -505,295 +525,6 @@ protected boolean[] getPropertySelectable() { return propertySelectable; } - public AbstractEntityPersister( - final PersistentClass persistentClass, - final EntityRegionAccessStrategy cacheAccessStrategy, - final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - final SessionFactoryImplementor factory) throws HibernateException { - - // moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - this.factory = factory; - this.cacheAccessStrategy = cacheAccessStrategy; - this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy; - isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable(); - - this.entityMetamodel = new EntityMetamodel( persistentClass, this, factory ); - this.entityTuplizer = this.entityMetamodel.getTuplizer(); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - int batch = persistentClass.getBatchSize(); - if ( batch == -1 ) { - batch = factory.getSettings().getDefaultBatchFetchSize(); - } - batchSize = batch; - hasSubselectLoadableCollections = persistentClass.hasSubselectLoadableCollections(); - - propertyMapping = new BasicEntityPropertyMapping( this ); - - // IDENTIFIER - - identifierColumnSpan = persistentClass.getIdentifier().getColumnSpan(); - rootTableKeyColumnNames = new String[identifierColumnSpan]; - rootTableKeyColumnReaders = new String[identifierColumnSpan]; - rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan]; - identifierAliases = new String[identifierColumnSpan]; - - rowIdName = persistentClass.getRootTable().getRowId(); - - loaderName = persistentClass.getLoaderName(); - - Iterator iter = persistentClass.getIdentifier().getColumnIterator(); - int i = 0; - while ( iter.hasNext() ) { - Column col = ( Column ) iter.next(); - rootTableKeyColumnNames[i] = col.getQuotedName( factory.getDialect() ); - rootTableKeyColumnReaders[i] = col.getReadExpr( factory.getDialect() ); - rootTableKeyColumnReaderTemplates[i] = col.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - identifierAliases[i] = col.getAlias( factory.getDialect(), persistentClass.getRootTable() ); - i++; - } - - // VERSION - - if ( persistentClass.isVersioned() ) { - versionColumnName = ( ( Column ) persistentClass.getVersion().getColumnIterator().next() ).getQuotedName( factory.getDialect() ); - } - else { - versionColumnName = null; - } - - //WHERE STRING - - sqlWhereString = StringHelper.isNotEmpty( persistentClass.getWhere() ) ? "( " + persistentClass.getWhere() + ") " : null; - sqlWhereStringTemplate = sqlWhereString == null ? - null : - Template.renderWhereStringTemplate( sqlWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() ); - - // PROPERTIES - - final boolean lazyAvailable = isInstrumented(); - - int hydrateSpan = entityMetamodel.getPropertySpan(); - propertyColumnSpans = new int[hydrateSpan]; - propertySubclassNames = new String[hydrateSpan]; - propertyColumnAliases = new String[hydrateSpan][]; - propertyColumnNames = new String[hydrateSpan][]; - propertyColumnFormulaTemplates = new String[hydrateSpan][]; - propertyColumnReaderTemplates = new String[hydrateSpan][]; - propertyColumnWriters = new String[hydrateSpan][]; - propertyUniqueness = new boolean[hydrateSpan]; - propertySelectable = new boolean[hydrateSpan]; - propertyColumnUpdateable = new boolean[hydrateSpan][]; - propertyColumnInsertable = new boolean[hydrateSpan][]; - HashSet thisClassProperties = new HashSet(); - - lazyProperties = new HashSet(); - ArrayList lazyNames = new ArrayList(); - ArrayList lazyNumbers = new ArrayList(); - ArrayList lazyTypes = new ArrayList(); - ArrayList lazyColAliases = new ArrayList(); - - iter = persistentClass.getPropertyClosureIterator(); - i = 0; - boolean foundFormula = false; - while ( iter.hasNext() ) { - Property prop = ( Property ) iter.next(); - thisClassProperties.add( prop ); - - int span = prop.getColumnSpan(); - propertyColumnSpans[i] = span; - propertySubclassNames[i] = prop.getPersistentClass().getEntityName(); - String[] colNames = new String[span]; - String[] colAliases = new String[span]; - String[] colReaderTemplates = new String[span]; - String[] colWriters = new String[span]; - String[] formulaTemplates = new String[span]; - Iterator colIter = prop.getColumnIterator(); - int k = 0; - while ( colIter.hasNext() ) { - Selectable thing = ( Selectable ) colIter.next(); - colAliases[k] = thing.getAlias( factory.getDialect() , prop.getValue().getTable() ); - if ( thing.isFormula() ) { - foundFormula = true; - formulaTemplates[k] = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - } - else { - Column col = (Column)thing; - colNames[k] = col.getQuotedName( factory.getDialect() ); - colReaderTemplates[k] = col.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - colWriters[k] = col.getWriteExpr(); - } - k++; - } - propertyColumnNames[i] = colNames; - propertyColumnFormulaTemplates[i] = formulaTemplates; - propertyColumnReaderTemplates[i] = colReaderTemplates; - propertyColumnWriters[i] = colWriters; - propertyColumnAliases[i] = colAliases; - - if ( lazyAvailable && prop.isLazy() ) { - lazyProperties.add( prop.getName() ); - lazyNames.add( prop.getName() ); - lazyNumbers.add( i ); - lazyTypes.add( prop.getValue().getType() ); - lazyColAliases.add( colAliases ); - } - - propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability(); - propertyColumnInsertable[i] = prop.getValue().getColumnInsertability(); - - propertySelectable[i] = prop.isSelectable(); - - propertyUniqueness[i] = prop.getValue().isAlternateUniqueKey(); - - if (prop.isLob() && getFactory().getDialect().forceLobAsLastValue() ) { - lobProperties.add( i ); - } - - i++; - - } - hasFormulaProperties = foundFormula; - lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases ); - lazyPropertyNames = ArrayHelper.toStringArray( lazyNames ); - lazyPropertyNumbers = ArrayHelper.toIntArray( lazyNumbers ); - lazyPropertyTypes = ArrayHelper.toTypeArray( lazyTypes ); - - // SUBCLASS PROPERTY CLOSURE - - ArrayList columns = new ArrayList(); - ArrayList columnsLazy = new ArrayList(); - ArrayList columnReaderTemplates = new ArrayList(); - ArrayList aliases = new ArrayList(); - ArrayList formulas = new ArrayList(); - ArrayList formulaAliases = new ArrayList(); - ArrayList formulaTemplates = new ArrayList(); - ArrayList formulasLazy = new ArrayList(); - ArrayList types = new ArrayList(); - ArrayList names = new ArrayList(); - ArrayList classes = new ArrayList(); - ArrayList templates = new ArrayList(); - ArrayList propColumns = new ArrayList(); - ArrayList propColumnReaders = new ArrayList(); - ArrayList propColumnReaderTemplates = new ArrayList(); - ArrayList joinedFetchesList = new ArrayList(); - ArrayList cascades = new ArrayList(); - ArrayList definedBySubclass = new ArrayList(); - ArrayList propColumnNumbers = new ArrayList(); - ArrayList propFormulaNumbers = new ArrayList(); - ArrayList columnSelectables = new ArrayList(); - ArrayList propNullables = new ArrayList(); - - iter = persistentClass.getSubclassPropertyClosureIterator(); - while ( iter.hasNext() ) { - Property prop = ( Property ) iter.next(); - names.add( prop.getName() ); - classes.add( prop.getPersistentClass().getEntityName() ); - boolean isDefinedBySubclass = !thisClassProperties.contains( prop ); - definedBySubclass.add( Boolean.valueOf( isDefinedBySubclass ) ); - propNullables.add( Boolean.valueOf( prop.isOptional() || isDefinedBySubclass ) ); //TODO: is this completely correct? - types.add( prop.getType() ); - - Iterator colIter = prop.getColumnIterator(); - String[] cols = new String[prop.getColumnSpan()]; - String[] readers = new String[prop.getColumnSpan()]; - String[] readerTemplates = new String[prop.getColumnSpan()]; - String[] forms = new String[prop.getColumnSpan()]; - int[] colnos = new int[prop.getColumnSpan()]; - int[] formnos = new int[prop.getColumnSpan()]; - int l = 0; - Boolean lazy = Boolean.valueOf( prop.isLazy() && lazyAvailable ); - while ( colIter.hasNext() ) { - Selectable thing = ( Selectable ) colIter.next(); - if ( thing.isFormula() ) { - String template = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - formnos[l] = formulaTemplates.size(); - colnos[l] = -1; - formulaTemplates.add( template ); - forms[l] = template; - formulas.add( thing.getText( factory.getDialect() ) ); - formulaAliases.add( thing.getAlias( factory.getDialect() ) ); - formulasLazy.add( lazy ); - } - else { - Column col = (Column)thing; - String colName = col.getQuotedName( factory.getDialect() ); - colnos[l] = columns.size(); //before add :-) - formnos[l] = -1; - columns.add( colName ); - cols[l] = colName; - aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) ); - columnsLazy.add( lazy ); - columnSelectables.add( Boolean.valueOf( prop.isSelectable() ) ); - - readers[l] = col.getReadExpr( factory.getDialect() ); - String readerTemplate = col.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - readerTemplates[l] = readerTemplate; - columnReaderTemplates.add( readerTemplate ); - } - l++; - } - propColumns.add( cols ); - propColumnReaders.add( readers ); - propColumnReaderTemplates.add( readerTemplates ); - templates.add( forms ); - propColumnNumbers.add( colnos ); - propFormulaNumbers.add( formnos ); - - joinedFetchesList.add( prop.getValue().getFetchMode() ); - cascades.add( prop.getCascadeStyle() ); - } - subclassColumnClosure = ArrayHelper.toStringArray( columns ); - subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases ); - subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy ); - subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables ); - subclassColumnReaderTemplateClosure = ArrayHelper.toStringArray( columnReaderTemplates ); - - subclassFormulaClosure = ArrayHelper.toStringArray( formulas ); - subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates ); - subclassFormulaAliasClosure = ArrayHelper.toStringArray( formulaAliases ); - subclassFormulaLazyClosure = ArrayHelper.toBooleanArray( formulasLazy ); - - subclassPropertyNameClosure = ArrayHelper.toStringArray( names ); - subclassPropertySubclassNameClosure = ArrayHelper.toStringArray( classes ); - subclassPropertyTypeClosure = ArrayHelper.toTypeArray( types ); - subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables ); - subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates ); - subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns ); - subclassPropertyColumnReaderClosure = ArrayHelper.to2DStringArray( propColumnReaders ); - subclassPropertyColumnReaderTemplateClosure = ArrayHelper.to2DStringArray( propColumnReaderTemplates ); - subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers ); - subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers ); - - subclassPropertyCascadeStyleClosure = new CascadeStyle[cascades.size()]; - iter = cascades.iterator(); - int j = 0; - while ( iter.hasNext() ) { - subclassPropertyCascadeStyleClosure[j++] = ( CascadeStyle ) iter.next(); - } - subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.size()]; - iter = joinedFetchesList.iterator(); - j = 0; - while ( iter.hasNext() ) { - subclassPropertyFetchModeClosure[j++] = ( FetchMode ) iter.next(); - } - - propertyDefinedOnSubclass = new boolean[definedBySubclass.size()]; - iter = definedBySubclass.iterator(); - j = 0; - while ( iter.hasNext() ) { - propertyDefinedOnSubclass[j++] = (Boolean) iter.next(); - } - - // Handle any filters applied to the class level - filterHelper = new FilterHelper( persistentClass.getFilters(), factory ); - - temporaryIdTableName = persistentClass.getTemporaryIdTableName(); - temporaryIdTableDDL = persistentClass.getTemporaryIdTableDDL(); - - this.cacheEntryHelper = buildCacheEntryHelper(); - } - protected CacheEntryHelper buildCacheEntryHelper() { if ( cacheAccessStrategy == null ) { // the entity defined no caching... @@ -844,8 +575,7 @@ public AbstractEntityPersister( this.cacheAccessStrategy = cacheAccessStrategy; this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy; this.isLazyPropertiesCacheable = - entityBinding.getHierarchyDetails().getCaching() == null ? - false : + entityBinding.getHierarchyDetails().getCaching() == null || entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties(); this.entityMetamodel = new EntityMetamodel( entityBinding, this, factory ); this.entityTuplizer = this.entityMetamodel.getTuplizer(); @@ -860,7 +590,7 @@ public AbstractEntityPersister( // IDENTIFIER - identifierColumnSpan = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding().getSimpleValueSpan(); + identifierColumnSpan = entityBinding.getHierarchyDetails().getEntityIdentifier().getColumnCount(); rootTableKeyColumnNames = new String[identifierColumnSpan]; rootTableKeyColumnReaders = new String[identifierColumnSpan]; rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan]; @@ -870,9 +600,12 @@ public AbstractEntityPersister( loaderName = entityBinding.getCustomLoaderName(); - int i = 0; - for ( org.hibernate.metamodel.relational.Column col : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { - rootTableKeyColumnNames[i] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + for ( int i = 0; i < identifierColumnSpan; i++ ) { + org.hibernate.metamodel.spi.relational.Column col = entityBinding.getHierarchyDetails().getRootEntityBinding().getPrimaryTable() + .getPrimaryKey() + .getColumns() + .get( i ); + rootTableKeyColumnNames[i] = col.getColumnName().getText( factory.getDialect() ); if ( col.getReadFragment() == null ) { rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i]; rootTableKeyColumnReaderTemplates[i] = getTemplateFromColumn( col, factory ); @@ -881,27 +614,38 @@ public AbstractEntityPersister( rootTableKeyColumnReaders[i] = col.getReadFragment(); rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( rootTableKeyColumnReaders[i], factory ); } - identifierAliases[i] = col.getAlias( factory.getDialect() ); - i++; + identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getHierarchyDetails().getRootEntityBinding().getPrimaryTable() ); } // VERSION - if ( entityBinding.isVersioned() ) { - final Value versioningValue = entityBinding.getHierarchyDetails().getVersioningAttributeBinding().getValue(); - if ( ! org.hibernate.metamodel.relational.Column.class.isInstance( versioningValue ) ) { - throw new AssertionFailure( "Bad versioning attribute binding : " + versioningValue ); + if ( entityBinding.getHierarchyDetails().isVersioned() ) { + final BasicAttributeBinding versionAttributeBinding = entityBinding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding(); + if ( versionAttributeBinding.getRelationalValueBindings().size() > 1 ) { + throw new AssertionFailure( + "Bad versioning attribute binding, expecting single column but found " + + versionAttributeBinding.getRelationalValueBindings().size() + ); } - org.hibernate.metamodel.relational.Column versionColumn = org.hibernate.metamodel.relational.Column.class.cast( versioningValue ); - versionColumnName = versionColumn.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + final Value versioningValue = versionAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + if ( ! org.hibernate.metamodel.spi.relational.Column.class.isInstance( versioningValue ) ) { + throw new AssertionFailure( + "Bad versioning attribute binding, expecting column but found [" + versioningValue + "]" + ); + } + org.hibernate.metamodel.spi.relational.Column versionColumn = org.hibernate.metamodel.spi.relational.Column.class.cast( versioningValue ); + versionColumnName = versionColumn.getColumnName().getText( factory.getDialect() ); } else { versionColumnName = null; } //WHERE STRING - - sqlWhereString = StringHelper.isNotEmpty( entityBinding.getWhereFilter() ) ? "( " + entityBinding.getWhereFilter() + ") " : null; + sqlWhereString = StringHelper.isNotEmpty( entityBinding.getHierarchyDetails().getWhere() ) + ? "( " + entityBinding.getHierarchyDetails().getWhere() + ") " + : null; sqlWhereStringTemplate = getTemplateFromString( sqlWhereString, factory ); // PROPERTIES @@ -920,34 +664,24 @@ public AbstractEntityPersister( propertySelectable = new boolean[hydrateSpan]; propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][]; - HashSet thisClassProperties = new HashSet(); + HashSet thisClassProperties = new HashSet(); lazyProperties = new HashSet(); - ArrayList lazyNames = new ArrayList(); - ArrayList lazyNumbers = new ArrayList(); - ArrayList lazyTypes = new ArrayList(); - ArrayList lazyColAliases = new ArrayList(); + ArrayList lazyNames = new ArrayList(); + ArrayList lazyNumbers = new ArrayList(); + ArrayList lazyTypes = new ArrayList(); + ArrayList lazyColAliases = new ArrayList(); - i = 0; + int i = 0; boolean foundFormula = false; - for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - // entity identifier is not considered a "normal" property - continue; - } - - if ( ! attributeBinding.getAttribute().isSingular() ) { - // collections handled separately - continue; - } - - final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + for ( AttributeBinding attributeBinding : entityBinding.getNonIdAttributeBindingClosure() ) { + thisClassProperties.add( attributeBinding ); - thisClassProperties.add( singularAttributeBinding ); + propertySubclassNames[i] = attributeBinding.getContainer().seekEntityBinding().getEntityName(); - propertySubclassNames[i] = ( (EntityBinding) singularAttributeBinding.getContainer() ).getEntity().getName(); - - int span = singularAttributeBinding.getSimpleValueSpan(); + int span = attributeBinding.getAttribute().isSingular() ? + ( (SingularAttributeBinding) attributeBinding).getRelationalValueBindings().size() : + 0; propertyColumnSpans[i] = span; String[] colNames = new String[span]; @@ -958,23 +692,30 @@ public AbstractEntityPersister( boolean[] propertyColumnInsertability = new boolean[span]; boolean[] propertyColumnUpdatability = new boolean[span]; - int k = 0; + if ( attributeBinding.getAttribute().isSingular() ) { + SingularAttributeBinding singularAttributeBinding = ( SingularAttributeBinding ) attributeBinding; - for ( SimpleValueBinding valueBinding : singularAttributeBinding.getSimpleValueBindings() ) { - colAliases[k] = valueBinding.getSimpleValue().getAlias( factory.getDialect() ); - if ( valueBinding.isDerived() ) { - foundFormula = true; - formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) valueBinding.getSimpleValue() ).getExpression(), factory ); - } - else { - org.hibernate.metamodel.relational.Column col = ( org.hibernate.metamodel.relational.Column ) valueBinding.getSimpleValue(); - colNames[k] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); - colReaderTemplates[k] = getTemplateFromColumn( col, factory ); - colWriters[k] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); + int k = 0; + + for ( RelationalValueBinding valueBinding : singularAttributeBinding.getRelationalValueBindings() ) { + colAliases[k] = valueBinding.getValue().getAlias( + factory.getDialect(), + valueBinding.getTable() + ); + if ( valueBinding.isDerived() ) { + foundFormula = true; + formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) valueBinding.getValue() ).getExpression(), factory ); + } + else { + org.hibernate.metamodel.spi.relational.Column col = (org.hibernate.metamodel.spi.relational.Column) valueBinding.getValue(); + colNames[k] = col.getColumnName().getText( factory.getDialect() ); + colReaderTemplates[k] = getTemplateFromColumn( col, factory ); + colWriters[k] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); + } + propertyColumnInsertability[k] = valueBinding.isIncludeInInsert(); + propertyColumnUpdatability[k] = valueBinding.isIncludeInUpdate(); + k++; } - propertyColumnInsertability[k] = valueBinding.isIncludeInInsert(); - propertyColumnUpdatability[k] = valueBinding.isIncludeInUpdate(); - k++; } propertyColumnNames[i] = colNames; propertyColumnFormulaTemplates[i] = formulaTemplates; @@ -985,25 +726,24 @@ public AbstractEntityPersister( propertyColumnUpdateable[i] = propertyColumnUpdatability; propertyColumnInsertable[i] = propertyColumnInsertability; - if ( lazyAvailable && singularAttributeBinding.isLazy() ) { - lazyProperties.add( singularAttributeBinding.getAttribute().getName() ); - lazyNames.add( singularAttributeBinding.getAttribute().getName() ); + if ( lazyAvailable && attributeBinding.isLazy() ) { + lazyProperties.add( attributeBinding.getAttribute().getName() ); + lazyNames.add( attributeBinding.getAttribute().getName() ); lazyNumbers.add( i ); - lazyTypes.add( singularAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping()); + lazyTypes.add( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping()); lazyColAliases.add( colAliases ); } + propertySelectable[i] = !attributeBinding.isBackRef(); - // TODO: fix this when backrefs are working - //propertySelectable[i] = singularAttributeBinding.isBackRef(); - propertySelectable[i] = true; + propertyUniqueness[i] = attributeBinding.isAlternateUniqueKey(); - propertyUniqueness[i] = singularAttributeBinding.isAlternateUniqueKey(); - - // TODO: Does this need AttributeBindings wired into lobProperties? Currently in Property only. + // TODO: set lobProperties correctly. + //if (attributeBinding.isLob() && getFactory().getDialect().forceLobAsLastValue() ) { + // lobProperties.add( i ); + //} i++; - } hasFormulaProperties = foundFormula; lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases ); @@ -1036,27 +776,29 @@ public AbstractEntityPersister( List columnSelectables = new ArrayList(); List propNullables = new ArrayList(); - for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - // entity identifier is not considered a "normal" property - continue; + for ( AttributeBinding attributeBinding : entityBinding.getNonIdEntitiesAttributeBindingClosure() ) { + names.add( attributeBinding.getAttribute().getName() ); + classes.add( ( (EntityBinding) attributeBinding.getContainer() ).getEntityName() ); + boolean isDefinedBySubclass = ! thisClassProperties.contains( attributeBinding ); + definedBySubclass.add( isDefinedBySubclass ); + final boolean propIsNullable; + final List relationalValueBindings; + if ( attributeBinding.getAttribute().isSingular() ) { + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + propIsNullable = + singularAttributeBinding.isOptional() || + singularAttributeBinding.isNullable() || + isDefinedBySubclass; + relationalValueBindings = singularAttributeBinding.getRelationalValueBindings(); } - - if ( ! attributeBinding.getAttribute().isSingular() ) { - // collections handled separately - continue; + else { + // plural attributes are considered nullable + propIsNullable = true; + relationalValueBindings = Collections.emptyList(); } - - final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; - - names.add( singularAttributeBinding.getAttribute().getName() ); - classes.add( ( (EntityBinding) singularAttributeBinding.getContainer() ).getEntity().getName() ); - boolean isDefinedBySubclass = ! thisClassProperties.contains( singularAttributeBinding ); - definedBySubclass.add( isDefinedBySubclass ); - propNullables.add( singularAttributeBinding.isNullable() || isDefinedBySubclass ); //TODO: is this completely correct? - types.add( singularAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - - final int span = singularAttributeBinding.getSimpleValueSpan(); + propNullables.add( propIsNullable ); + types.add( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); + final int span = relationalValueBindings.size(); String[] cols = new String[ span ]; String[] readers = new String[ span ]; String[] readerTemplates = new String[ span ]; @@ -1064,34 +806,40 @@ public AbstractEntityPersister( int[] colnos = new int[ span ]; int[] formnos = new int[ span ]; int l = 0; - Boolean lazy = singularAttributeBinding.isLazy() && lazyAvailable; - for ( SimpleValueBinding valueBinding : singularAttributeBinding.getSimpleValueBindings() ) { + Boolean lazy = attributeBinding.isLazy() && lazyAvailable; + + for ( RelationalValueBinding valueBinding : relationalValueBindings ) { if ( valueBinding.isDerived() ) { - DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getSimpleValue() ); + DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getValue() ); String template = getTemplateFromString( derivedValue.getExpression(), factory ); formnos[l] = formulaTemplates.size(); colnos[l] = -1; formulaTemplates.add( template ); forms[l] = template; + // TODO: should be derivedValue.getText( factory.getDialect() ). formulas.add( derivedValue.getExpression() ); - formulaAliases.add( derivedValue.getAlias( factory.getDialect() ) ); + formulaAliases.add( derivedValue.getAlias( factory.getDialect(), null ) ); formulasLazy.add( lazy ); } else { - org.hibernate.metamodel.relational.Column col = org.hibernate.metamodel.relational.Column.class.cast( valueBinding.getSimpleValue() ); - String colName = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + org.hibernate.metamodel.spi.relational.Column col = org.hibernate.metamodel.spi.relational.Column.class.cast( valueBinding.getValue() ); + String colName = col.getColumnName().getText( factory.getDialect() ); colnos[l] = columns.size(); //before add :-) formnos[l] = -1; columns.add( colName ); cols[l] = colName; - aliases.add( col.getAlias( factory.getDialect() ) ); + aliases.add( + col.getAlias( + factory.getDialect(), + valueBinding.getTable() + ) + ); columnsLazy.add( lazy ); - // TODO: properties only selectable if they are non-plural??? - columnSelectables.add( singularAttributeBinding.getAttribute().isSingular() ); + columnSelectables.add( ! attributeBinding.isBackRef() ); readers[l] = col.getReadFragment() == null ? - col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ) : + col.getColumnName().getText( factory.getDialect() ) : col.getReadFragment(); String readerTemplate = getTemplateFromColumn( col, factory ); readerTemplates[l] = readerTemplate; @@ -1106,14 +854,26 @@ public AbstractEntityPersister( propColumnNumbers.add( colnos ); propFormulaNumbers.add( formnos ); - if ( singularAttributeBinding.isAssociation() ) { - AssociationAttributeBinding associationAttributeBinding = - ( AssociationAttributeBinding ) singularAttributeBinding; - cascades.add( associationAttributeBinding.getCascadeStyle() ); - joinedFetchesList.add( associationAttributeBinding.getFetchMode() ); + CascadeStyle cascadeStyle = null; + if ( attributeBinding.isCascadeable() ) { + if ( attributeBinding.getAttribute().isSingular() ) { + cascadeStyle = ( (Cascadeable) attributeBinding ).getCascadeStyle(); + } + else { + PluralAttributeElementBinding pluralAttributeElementBinding = + ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding(); + cascadeStyle = ( (Cascadeable) pluralAttributeElementBinding).getCascadeStyle(); + } + } + if ( cascadeStyle == null ) { + cascadeStyle = CascadeStyles.NONE; + } + cascades.add( cascadeStyle ); + + if ( attributeBinding instanceof Fetchable ) { + joinedFetchesList.add( ( (Fetchable) attributeBinding ).getFetchMode() ); } else { - cascades.add( CascadeStyles.NONE ); joinedFetchesList.add( FetchMode.SELECT ); } } @@ -1145,15 +905,25 @@ public AbstractEntityPersister( propertyDefinedOnSubclass = ArrayHelper.toBooleanArray( definedBySubclass ); - List filterDefaultConditions = new ArrayList(); - for ( FilterDefinition filterDefinition : entityBinding.getFilterDefinitions() ) { - filterDefaultConditions.add(new FilterConfiguration(filterDefinition.getFilterName(), - filterDefinition.getDefaultFilterCondition(), true, null, null, null)); - } - filterHelper = new FilterHelper( filterDefaultConditions, factory); + filterHelper = new FilterHelper( entityBinding.getFilterConfigurations(), factory); - temporaryIdTableName = null; - temporaryIdTableDDL = null; + temporaryIdTableName = TemporaryTableExporter.generateTableName( + factory.getDialect(), + entityBinding.getPrimaryTable() + ); + TableSpecification primaryTable = entityBinding.getPrimaryTable(); + if ( factory.getDialect().supportsTemporaryTables() && primaryTable instanceof Table ) { + temporaryIdTableDDL = factory + .getDialect() + .getTemporaryTableExporter() + .getSqlCreateStrings( + Table.class.cast( primaryTable ), + factory.getServiceRegistry().getService( JdbcEnvironment.class ) + )[0]; + } + else { + temporaryIdTableDDL = null; + } this.cacheEntryHelper = buildCacheEntryHelper(); } @@ -1164,13 +934,13 @@ protected static String getTemplateFromString(String string, SessionFactoryImple Template.renderWhereStringTemplate( string, factory.getDialect(), factory.getSqlFunctionRegistry() ); } - public String getTemplateFromColumn(org.hibernate.metamodel.relational.Column column, SessionFactoryImplementor factory) { + public String getTemplateFromColumn(org.hibernate.metamodel.spi.relational.Column column, SessionFactoryImplementor factory) { String templateString; if ( column.getReadFragment() != null ) { templateString = getTemplateFromString( column.getReadFragment(), factory ); } else { - String columnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + String columnName = column.getColumnName().getText( factory.getDialect() ); templateString = Template.TEMPLATE + '.' + columnName; } return templateString; @@ -2285,12 +2055,11 @@ protected void initSubclassPropertyAliasesMap(PersistentClass model) throws Mapp /** * Must be called by subclasses, at the end of their constructors */ - protected void initSubclassPropertyAliasesMap(EntityBinding model) throws MappingException { + protected void initSubclassPropertyAliasesMap(EntityBinding entityBinding) throws MappingException { // ALIASES - // TODO: Fix when subclasses are working (HHH-6337) - //internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosureIterator() ); + internalInitSubclassPropertyAliasesMap( null, entityBinding.getEntitiesAttributeBindingClosure() ); // aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id' if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) { @@ -2378,6 +2147,59 @@ private void internalInitSubclassPropertyAliasesMap(String path, Iterator proper } + protected static boolean isIdentifierAttributeBinding(final AttributeBinding prop){ + return prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop ); + } + + private void internalInitSubclassPropertyAliasesMap(String path, AttributeBinding[] attributeBindings) { + for ( AttributeBinding prop : attributeBindings ) { + if ( isIdentifierAttributeBinding( prop ) ) { + // ID propertie aliases are dealt with elsewhere. + continue; + } + if ( ! prop.getAttribute().isSingular() ) { + // skip plural attributes + continue; + } + SingularAttributeBinding singularProp = (SingularAttributeBinding) prop; + String propname = path == null ? prop.getAttribute().getName() : path + "." + prop.getAttribute().getName(); + if ( prop instanceof EmbeddedAttributeBinding ) { + EmbeddedAttributeBinding component = (EmbeddedAttributeBinding) prop; + AttributeBinding[] abs = new AttributeBinding[component.getEmbeddableBinding().attributeBindingSpan()]; + int i=0; + for(AttributeBinding ab : component.getEmbeddableBinding().attributeBindings()){ + abs[i++] = ab; + } + internalInitSubclassPropertyAliasesMap( propname, abs ); + } + else { + int span = singularProp.getRelationalValueBindings().size(); + String[] aliases = new String[span]; + String[] cols = new String[span]; + int l = 0; + for ( RelationalValueBinding relationalValueBinding : singularProp.getRelationalValueBindings() ) { + aliases[l] = relationalValueBinding.getValue().getAlias( + getFactory().getDialect(), + relationalValueBinding.getTable() + ); + if ( relationalValueBinding.isDerived() ) { + cols[l] = ( (DerivedValue) relationalValueBinding.getValue() ).getExpression(); // TODO: skip formulas? + } + else { + cols[l] = + ( (org.hibernate.metamodel.spi.relational.Column) relationalValueBinding.getValue() ) + .getColumnName().getText( getFactory().getDialect() ); + } + l++; + } + + subclassPropertyAliases.put( propname, aliases ); + subclassPropertyColumnNames.put( propname, cols ); + } + } + + } + public Object loadByUniqueKey( String propertyName, Object uniqueKey, @@ -3540,7 +3362,9 @@ else if ( ! isModifiableEntity( entry ) ) { public Serializable insert(Object[] fields, Object object, SessionImplementor session) throws HibernateException { - + // apply any pre-insert in-memory value generation + preInsertInMemoryValueGeneration( fields, object, session ); + final int span = getTableSpan(); final Serializable id; if ( entityMetamodel.isDynamicInsert() ) { @@ -3563,15 +3387,7 @@ public Serializable insert(Object[] fields, Object object, SessionImplementor se public void insert(Serializable id, Object[] fields, Object object, SessionImplementor session) { // apply any pre-insert in-memory value generation - if ( getEntityMetamodel().hasPreInsertGeneratedValues() ) { - final InMemoryValueGenerationStrategy[] strategies = getEntityMetamodel().getInMemoryValueGenerationStrategies(); - for ( int i = 0; i < strategies.length; i++ ) { - if ( strategies[i] != null && strategies[i].getGenerationTiming().includesInsert() ) { - fields[i] = strategies[i].getValueGenerator().generateValue( (Session) session, object ); - setPropertyValue( object, i, fields[i] ); - } - } - } + preInsertInMemoryValueGeneration( fields, object, session ); final int span = getTableSpan(); if ( entityMetamodel.isDynamicInsert() ) { @@ -3588,6 +3404,18 @@ public void insert(Serializable id, Object[] fields, Object object, SessionImple } } } + + private void preInsertInMemoryValueGeneration(Object[] fields, Object object, SessionImplementor session) { + if ( getEntityMetamodel().hasPreInsertGeneratedValues() ) { + final InMemoryValueGenerationStrategy[] strategies = getEntityMetamodel().getInMemoryValueGenerationStrategies(); + for ( int i = 0; i < strategies.length; i++ ) { + if ( strategies[i] != null && strategies[i].getGenerationTiming().includesInsert() ) { + fields[i] = strategies[i].getValueGenerator().generateValue( (Session) session, object ); + setPropertyValue( object, i, fields[i] ); + } + } + } + } /** * Delete an object diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java index dc0f31dc43ba..65e0436841f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java @@ -174,11 +174,12 @@ protected void initPropertyPaths( final Mapping factory) throws MappingException { - if ( columns.length!=type.getColumnSpan(factory) ) { + if ( columns.length != type.getColumnSpan(factory) ) { throw new MappingException( - "broken column mapping for: " + path + - " of: " + getEntityName() - ); + "broken column mapping [" + getEntityName() + '#' + path + + "]; expecting " + columns.length + " columns, but type defined " + + type.getColumnSpan(factory) + ); } if ( type.isAssociationType() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java index 61357afdac5f..1a12a2e995c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java @@ -36,7 +36,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.compare.EqualsHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.type.AbstractType; import org.hibernate.type.Type; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index d90331606e94..3af19873d6d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -25,18 +25,20 @@ import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; -import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.QueryException; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.hibernate.engine.FetchStyle; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.Mapping; @@ -45,24 +47,27 @@ import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.util.MarkerObject; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Formula; import org.hibernate.mapping.Join; -import org.hibernate.mapping.KeyValue; -import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Subclass; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Hierarchical; +import org.hibernate.metamodel.spi.domain.MappedSuperclass; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.InFragment; import org.hibernate.sql.Insert; import org.hibernate.sql.SelectFragment; -import org.hibernate.type.*; import org.hibernate.type.DiscriminatorType; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -78,8 +83,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { private static final String IMPLICIT_DISCRIMINATOR_ALIAS = "clazz_"; private static final Object NULL_DISCRIMINATOR = new MarkerObject(""); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject(""); - private static final String NULL_STRING = "null"; - private static final String NOT_NULL_STRING = "not null"; // the class hierarchy structure private final int tableSpan; @@ -141,460 +144,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { //INITIALIZATION: - public JoinedSubclassEntityPersister( - final PersistentClass persistentClass, - final EntityRegionAccessStrategy cacheAccessStrategy, - final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - final SessionFactoryImplementor factory, - final Mapping mapping) throws HibernateException { - - super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - - // DISCRIMINATOR - - if ( persistentClass.isPolymorphic() ) { - final Value discriminatorMapping = persistentClass.getDiscriminator(); - if ( discriminatorMapping != null ) { - log.debug( "Encountered explicit discriminator mapping for joined inheritance" ); - - final Selectable selectable = discriminatorMapping.getColumnIterator().next(); - if ( Formula.class.isInstance( selectable ) ) { - throw new MappingException( "Discriminator formulas on joined inheritance hierarchies not supported at this time" ); - } - else { - final Column column = (Column) selectable; - explicitDiscriminatorColumnName = column.getQuotedName( factory.getDialect() ); - discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() ); - } - discriminatorType = (DiscriminatorType) persistentClass.getDiscriminator().getType(); - if ( persistentClass.isDiscriminatorValueNull() ) { - discriminatorValue = NULL_DISCRIMINATOR; - discriminatorSQLString = InFragment.NULL; - } - else if ( persistentClass.isDiscriminatorValueNotNull() ) { - discriminatorValue = NOT_NULL_DISCRIMINATOR; - discriminatorSQLString = InFragment.NOT_NULL; - } - else { - try { - discriminatorValue = discriminatorType.stringToObject( persistentClass.getDiscriminatorValue() ); - discriminatorSQLString = discriminatorType.objectToSQLString( discriminatorValue, factory.getDialect() ); - } - catch (ClassCastException cce) { - throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() ); - } - catch (Exception e) { - throw new MappingException("Could not format discriminator value to SQL string", e); - } - } - } - else { - explicitDiscriminatorColumnName = null; - discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; - discriminatorType = StandardBasicTypes.INTEGER; - try { - discriminatorValue = persistentClass.getSubclassId(); - discriminatorSQLString = discriminatorValue.toString(); - } - catch ( Exception e ) { - throw new MappingException( "Could not format discriminator value to SQL string", e ); - } - } - } - else { - explicitDiscriminatorColumnName = null; - discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; - discriminatorType = StandardBasicTypes.INTEGER; - discriminatorValue = null; - discriminatorSQLString = null; - } - - if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) { - throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" ); - } - - //MULTITABLES - - final int idColumnSpan = getIdentifierColumnSpan(); - - ArrayList tables = new ArrayList(); - ArrayList keyColumns = new ArrayList(); - ArrayList keyColumnReaders = new ArrayList(); - ArrayList keyColumnReaderTemplates = new ArrayList(); - ArrayList cascadeDeletes = new ArrayList(); - Iterator titer = persistentClass.getTableClosureIterator(); - Iterator kiter = persistentClass.getKeyClosureIterator(); - while ( titer.hasNext() ) { - Table tab = (Table) titer.next(); - KeyValue key = (KeyValue) kiter.next(); - String tabname = tab.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - tables.add( tabname ); - String[] keyCols = new String[idColumnSpan]; - String[] keyColReaders = new String[idColumnSpan]; - String[] keyColReaderTemplates = new String[idColumnSpan]; - Iterator citer = key.getColumnIterator(); - for ( int k = 0; k < idColumnSpan; k++ ) { - Column column = (Column) citer.next(); - keyCols[k] = column.getQuotedName( factory.getDialect() ); - keyColReaders[k] = column.getReadExpr( factory.getDialect() ); - keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - } - keyColumns.add( keyCols ); - keyColumnReaders.add( keyColReaders ); - keyColumnReaderTemplates.add( keyColReaderTemplates ); - cascadeDeletes.add( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() ); - } - - //Span of the tables directly mapped by this entity and super-classes, if any - coreTableSpan = tables.size(); - - isNullableTable = new boolean[persistentClass.getJoinClosureSpan()]; - - int tableIndex = 0; - Iterator joinIter = persistentClass.getJoinClosureIterator(); - while ( joinIter.hasNext() ) { - Join join = (Join) joinIter.next(); - - isNullableTable[tableIndex++] = join.isOptional(); - - Table table = join.getTable(); - - String tableName = table.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - tables.add( tableName ); - - KeyValue key = join.getKey(); - int joinIdColumnSpan = key.getColumnSpan(); - - String[] keyCols = new String[joinIdColumnSpan]; - String[] keyColReaders = new String[joinIdColumnSpan]; - String[] keyColReaderTemplates = new String[joinIdColumnSpan]; - - Iterator citer = key.getColumnIterator(); - - for ( int k = 0; k < joinIdColumnSpan; k++ ) { - Column column = (Column) citer.next(); - keyCols[k] = column.getQuotedName( factory.getDialect() ); - keyColReaders[k] = column.getReadExpr( factory.getDialect() ); - keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - } - keyColumns.add( keyCols ); - keyColumnReaders.add( keyColReaders ); - keyColumnReaderTemplates.add( keyColReaderTemplates ); - cascadeDeletes.add( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() ); - } - - naturalOrderTableNames = ArrayHelper.toStringArray( tables ); - naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray( keyColumns ); - naturalOrderTableKeyColumnReaders = ArrayHelper.to2DStringArray( keyColumnReaders ); - naturalOrderTableKeyColumnReaderTemplates = ArrayHelper.to2DStringArray( keyColumnReaderTemplates ); - naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray( cascadeDeletes ); - - ArrayList subtables = new ArrayList(); - ArrayList isConcretes = new ArrayList(); - ArrayList isDeferreds = new ArrayList(); - ArrayList isLazies = new ArrayList(); - - keyColumns = new ArrayList(); - titer = persistentClass.getSubclassTableClosureIterator(); - while ( titer.hasNext() ) { - Table tab = (Table) titer.next(); - isConcretes.add( persistentClass.isClassOrSuperclassTable( tab ) ); - isDeferreds.add( Boolean.FALSE ); - isLazies.add( Boolean.FALSE ); - String tabname = tab.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - subtables.add( tabname ); - String[] key = new String[idColumnSpan]; - Iterator citer = tab.getPrimaryKey().getColumnIterator(); - for ( int k = 0; k < idColumnSpan; k++ ) { - key[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() ); - } - keyColumns.add( key ); - } - - //Add joins - joinIter = persistentClass.getSubclassJoinClosureIterator(); - while ( joinIter.hasNext() ) { - Join join = (Join) joinIter.next(); - - Table tab = join.getTable(); - - isConcretes.add( persistentClass.isClassOrSuperclassTable( tab ) ); - isDeferreds.add( join.isSequentialSelect() ); - isLazies.add( join.isLazy() ); - - String tabname = tab.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - subtables.add( tabname ); - String[] key = new String[idColumnSpan]; - Iterator citer = tab.getPrimaryKey().getColumnIterator(); - for ( int k = 0; k < idColumnSpan; k++ ) { - key[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() ); - } - keyColumns.add( key ); - } - - String[] naturalOrderSubclassTableNameClosure = ArrayHelper.toStringArray( subtables ); - String[][] naturalOrderSubclassTableKeyColumnClosure = ArrayHelper.to2DStringArray( keyColumns ); - isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes ); - subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds ); - subclassTableIsLazyClosure = ArrayHelper.toBooleanArray( isLazies ); - - constraintOrderedTableNames = new String[naturalOrderSubclassTableNameClosure.length]; - constraintOrderedKeyColumnNames = new String[naturalOrderSubclassTableNameClosure.length][]; - int currentPosition = 0; - for ( int i = naturalOrderSubclassTableNameClosure.length - 1; i >= 0; i--, currentPosition++ ) { - constraintOrderedTableNames[currentPosition] = naturalOrderSubclassTableNameClosure[i]; - constraintOrderedKeyColumnNames[currentPosition] = naturalOrderSubclassTableKeyColumnClosure[i]; - } - - /** - * Suppose an entity Client extends Person, mapped to the tables CLIENT and PERSON respectively. - * For the Client entity: - * naturalOrderTableNames -> PERSON, CLIENT; this reflects the sequence in which the tables are - * added to the meta-data when the annotated entities are processed. - * However, in some instances, for example when generating joins, the CLIENT table needs to be - * the first table as it will the driving table. - * tableNames -> CLIENT, PERSON - */ - - tableSpan = naturalOrderTableNames.length; - tableNames = reverse( naturalOrderTableNames, coreTableSpan ); - tableKeyColumns = reverse( naturalOrderTableKeyColumns, coreTableSpan ); - tableKeyColumnReaders = reverse( naturalOrderTableKeyColumnReaders, coreTableSpan ); - tableKeyColumnReaderTemplates = reverse( naturalOrderTableKeyColumnReaderTemplates, coreTableSpan ); - subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan ); - subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan ); - - spaces = ArrayHelper.join( - tableNames, - ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() ) - ); - - // Custom sql - customSQLInsert = new String[tableSpan]; - customSQLUpdate = new String[tableSpan]; - customSQLDelete = new String[tableSpan]; - insertCallable = new boolean[tableSpan]; - updateCallable = new boolean[tableSpan]; - deleteCallable = new boolean[tableSpan]; - insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; - updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; - deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; - - PersistentClass pc = persistentClass; - int jk = coreTableSpan - 1; - while ( pc != null ) { - customSQLInsert[jk] = pc.getCustomSQLInsert(); - insertCallable[jk] = customSQLInsert[jk] != null && pc.isCustomInsertCallable(); - insertResultCheckStyles[jk] = pc.getCustomSQLInsertCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( - customSQLInsert[jk], insertCallable[jk] - ) - : pc.getCustomSQLInsertCheckStyle(); - customSQLUpdate[jk] = pc.getCustomSQLUpdate(); - updateCallable[jk] = customSQLUpdate[jk] != null && pc.isCustomUpdateCallable(); - updateResultCheckStyles[jk] = pc.getCustomSQLUpdateCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[jk], updateCallable[jk] ) - : pc.getCustomSQLUpdateCheckStyle(); - customSQLDelete[jk] = pc.getCustomSQLDelete(); - deleteCallable[jk] = customSQLDelete[jk] != null && pc.isCustomDeleteCallable(); - deleteResultCheckStyles[jk] = pc.getCustomSQLDeleteCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[jk], deleteCallable[jk] ) - : pc.getCustomSQLDeleteCheckStyle(); - jk--; - pc = pc.getSuperclass(); - } - - if ( jk != -1 ) { - throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." ); - } - - joinIter = persistentClass.getJoinClosureIterator(); - int j = coreTableSpan; - while ( joinIter.hasNext() ) { - Join join = (Join) joinIter.next(); - - customSQLInsert[j] = join.getCustomSQLInsert(); - insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable(); - insertResultCheckStyles[j] = join.getCustomSQLInsertCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] ) - : join.getCustomSQLInsertCheckStyle(); - customSQLUpdate[j] = join.getCustomSQLUpdate(); - updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable(); - updateResultCheckStyles[j] = join.getCustomSQLUpdateCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] ) - : join.getCustomSQLUpdateCheckStyle(); - customSQLDelete[j] = join.getCustomSQLDelete(); - deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable(); - deleteResultCheckStyles[j] = join.getCustomSQLDeleteCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] ) - : join.getCustomSQLDeleteCheckStyle(); - j++; - } - - // PROPERTIES - int hydrateSpan = getPropertySpan(); - naturalOrderPropertyTableNumbers = new int[hydrateSpan]; - propertyTableNumbers = new int[hydrateSpan]; - Iterator iter = persistentClass.getPropertyClosureIterator(); - int i = 0; - while ( iter.hasNext() ) { - Property prop = (Property) iter.next(); - String tabname = prop.getValue().getTable().getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - propertyTableNumbers[i] = getTableId( tabname, tableNames ); - naturalOrderPropertyTableNumbers[i] = getTableId( tabname, naturalOrderTableNames ); - i++; - } - - // subclass closure properties - - //TODO: code duplication with SingleTableEntityPersister - - ArrayList columnTableNumbers = new ArrayList(); - ArrayList formulaTableNumbers = new ArrayList(); - ArrayList propTableNumbers = new ArrayList(); - - iter = persistentClass.getSubclassPropertyClosureIterator(); - while ( iter.hasNext() ) { - Property prop = (Property) iter.next(); - Table tab = prop.getValue().getTable(); - String tabname = tab.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - Integer tabnum = getTableId( tabname, subclassTableNameClosure ); - propTableNumbers.add( tabnum ); - - Iterator citer = prop.getColumnIterator(); - while ( citer.hasNext() ) { - Selectable thing = (Selectable) citer.next(); - if ( thing.isFormula() ) { - formulaTableNumbers.add( tabnum ); - } - else { - columnTableNumbers.add( tabnum ); - } - } - - } - - subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnTableNumbers ); - subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propTableNumbers ); - subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaTableNumbers ); - - // SUBCLASSES - - int subclassSpan = persistentClass.getSubclassSpan() + 1; - subclassClosure = new String[subclassSpan]; - subclassClosure[subclassSpan - 1] = getEntityName(); - if ( persistentClass.isPolymorphic() ) { - subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() ); - discriminatorValues = new String[subclassSpan]; - discriminatorValues[subclassSpan - 1] = discriminatorSQLString; - notNullColumnTableNumbers = new int[subclassSpan]; - final int id = getTableId( - persistentClass.getTable().getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ), - subclassTableNameClosure - ); - notNullColumnTableNumbers[subclassSpan - 1] = id; - notNullColumnNames = new String[subclassSpan]; - notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0]; //( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); - } - else { - discriminatorValues = null; - notNullColumnTableNumbers = null; - notNullColumnNames = null; - } - - iter = persistentClass.getSubclassIterator(); - int k = 0; - while ( iter.hasNext() ) { - Subclass sc = (Subclass) iter.next(); - subclassClosure[k] = sc.getEntityName(); - try { - if ( persistentClass.isPolymorphic() ) { - final Object discriminatorValue; - if ( explicitDiscriminatorColumnName != null ) { - if ( sc.isDiscriminatorValueNull() ) { - discriminatorValue = NULL_DISCRIMINATOR; - } - else if ( sc.isDiscriminatorValueNotNull() ) { - discriminatorValue = NOT_NULL_DISCRIMINATOR; - } - else { - try { - discriminatorValue = discriminatorType.stringToObject( sc.getDiscriminatorValue() ); - } - catch (ClassCastException cce) { - throw new MappingException( "Illegal discriminator type: " + discriminatorType.getName() ); - } - catch (Exception e) { - throw new MappingException( "Could not format discriminator value to SQL string", e); - } - } - } - else { - // we now use subclass ids that are consistent across all - // persisters for a class hierarchy, so that the use of - // "foo.class = Bar" works in HQL - discriminatorValue = sc.getSubclassId(); - } - - subclassesByDiscriminatorValue.put( discriminatorValue, sc.getEntityName() ); - discriminatorValues[k] = discriminatorValue.toString(); - int id = getTableId( - sc.getTable().getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ), - subclassTableNameClosure - ); - notNullColumnTableNumbers[k] = id; - notNullColumnNames[k] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); - } - } - catch ( Exception e ) { - throw new MappingException( "Error parsing discriminator value", e ); - } - k++; - } - - subclassNamesBySubclassTable = buildSubclassNamesBySubclassTableMapping( persistentClass, factory ); - - initLockers(); - - initSubclassPropertyAliasesMap( persistentClass ); - - postConstruct( mapping ); - - } - - /** * Used to hold the name of subclasses that each "subclass table" is part of. For example, given a hierarchy like: * {@code JoinedEntity <- JoinedEntitySubclass <- JoinedEntitySubSubclass}.. @@ -650,6 +199,18 @@ private String[][] buildSubclassNamesBySubclassTableMapping(PersistentClass pers return mapping; } + private String[][] buildSubclassNamesBySubclassTableMapping(EntityBinding entityBinding, SessionFactoryImplementor factory) { + // this value represents the number of subclasses (and not the class itself) + final int numberOfSubclassTables = subclassTableNameClosure.length - coreTableSpan; + if ( numberOfSubclassTables == 0 ) { + return new String[0][]; + } + + final String[][] mapping = new String[numberOfSubclassTables][]; + processPersistentClassHierarchy( entityBinding, true, factory, mapping ); + return mapping; + } + private Set processPersistentClassHierarchy( PersistentClass persistentClass, boolean isBase, @@ -676,7 +237,7 @@ private Set processPersistentClassHierarchy( classNames.add( persistentClass.getEntityName() ); if ( ! isBase ) { - MappedSuperclass msc = persistentClass.getSuperMappedSuperclass(); + org.hibernate.mapping.MappedSuperclass msc = persistentClass.getSuperMappedSuperclass(); while ( msc != null ) { classNames.add( msc.getMappedClass().getName() ); msc = msc.getSuperMappedSuperclass(); @@ -688,6 +249,44 @@ private Set processPersistentClassHierarchy( return classNames; } + private Set processPersistentClassHierarchy( + EntityBinding entityBinding, + boolean isBase, + SessionFactoryImplementor factory, + String[][] mapping) { + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // collect all the class names that indicate that the "main table" of the given PersistentClass should be + // included when one of the collected class names is used in TREAT + final Set classNames = new HashSet(); + + for ( EntityBinding subEntityBinding : entityBinding.getDirectSubEntityBindings() ) { + final Set subclassSubclassNames = processPersistentClassHierarchy( + subEntityBinding, + false, + factory, + mapping + ); + classNames.addAll( subclassSubclassNames ); + } + + classNames.add( entityBinding.getEntityName() ); + + if ( ! isBase ) { + Hierarchical superType = entityBinding.getEntity().getSuperType(); + while ( superType != null ) { + if ( MappedSuperclass.class.isInstance( superType ) ) { + classNames.add( superType.getDescriptor().getName().toString() ); + } + superType = superType.getSuperType(); + } + + associateSubclassNamesToSubclassTableIndexes( entityBinding, classNames, mapping, factory ); + } + + return classNames; + } + private void associateSubclassNamesToSubclassTableIndexes( PersistentClass persistentClass, Set classNames, @@ -714,6 +313,23 @@ private void associateSubclassNamesToSubclassTableIndexes( } } + private void associateSubclassNamesToSubclassTableIndexes( + EntityBinding entityBinding, + Set classNames, + String[][] mapping, + SessionFactoryImplementor factory) { + + final String tableName = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); + + associateSubclassNamesToSubclassTableIndex( tableName, classNames, mapping ); + + for ( SecondaryTable secondaryTable : entityBinding.getSecondaryTables().values() ) { + final String secondaryTableName = + secondaryTable.getSecondaryTableReference().getQualifiedName( factory.getDialect() ); + associateSubclassNamesToSubclassTableIndex( secondaryTableName, classNames, mapping ); + } + } + private void associateSubclassNamesToSubclassTableIndex( String tableName, Set classNames, @@ -754,43 +370,416 @@ public JoinedSubclassEntityPersister( final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, final SessionFactoryImplementor factory, final Mapping mapping) throws HibernateException { + super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - // TODO: implement!!! initializing final fields to null to make compiler happy - tableSpan = -1; - tableNames = null; - naturalOrderTableNames = null; - tableKeyColumns = null; - tableKeyColumnReaders = null; - tableKeyColumnReaderTemplates = null; - naturalOrderTableKeyColumns = null; - naturalOrderTableKeyColumnReaders = null; - naturalOrderTableKeyColumnReaderTemplates = null; - naturalOrderCascadeDeleteEnabled = null; - spaces = null; - subclassClosure = null; - subclassTableNameClosure = null; - subclassTableKeyColumnClosure = null; - isClassOrSuperclassTable = null; - naturalOrderPropertyTableNumbers = null; - propertyTableNumbers = null; - subclassPropertyTableNumberClosure = null; - subclassColumnTableNumberClosure = null; - subclassFormulaTableNumberClosure = null; - subclassTableSequentialSelect = null; - subclassTableIsLazyClosure = null; - discriminatorValues = null; - notNullColumnNames = null; - notNullColumnTableNumbers = null; - constraintOrderedTableNames = null; - constraintOrderedKeyColumnNames = null; - discriminatorValue = null; - discriminatorSQLString = null; - discriminatorType = StandardBasicTypes.INTEGER; - explicitDiscriminatorColumnName = null; - discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; - coreTableSpan = -1; - isNullableTable = null; - subclassNamesBySubclassTable = null; + + assertOptimisticLockStyle(); + + final boolean isCascadeDeleteDefault = factory.getDialect().supportsCascadeDelete(); + + final EntityBinding[] entityBindings = entityBinding.getEntityBindingClosure(); + final TableSpecification[] tables = entityBinding.getTableClosure(); + final SecondaryTable[] secondaryTables = entityBinding.getSecondaryTableClosure(); + final String[] synchronizedTableNames = entityBinding.getSynchronizedTableNameClosure(); + final AttributeBinding[] attributeBindings = entityBinding.getNonIdAttributeBindingClosure(); + //todo the count of these two are not equal, which they should be + final EntityBinding[] preOrderSubEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure(); + final EntityBinding[] postOrderSubEntityBindings = entityBinding.getPostOrderSubEntityBindingClosure(); + final TableSpecification[] subTables = entityBinding.getPreOrderSubTableClosure(); + final SecondaryTable[] subSecondaryTables = entityBinding.getSubEntitySecondaryTables(); + final AttributeBinding[] allAttributeBindings = entityBinding.getNonIdEntitiesAttributeBindingClosure(); + + final int idColumnSpan = getIdentifierColumnSpan(); + coreTableSpan = tables.length; + final int secondaryTableSpan = secondaryTables.length; + tableSpan = coreTableSpan + secondaryTableSpan; + final int subclassSpan = postOrderSubEntityBindings.length; + final int subclassSecondaryTableSpan = subSecondaryTables.length; + final int subTableSpan = subclassSpan + subclassSecondaryTableSpan; + final int allTableSpan = tableSpan + subTableSpan; + final int hydrateSpan = getPropertySpan(); + isClassOrSuperclassTable = new boolean[allTableSpan]; + subclassTableSequentialSelect = new boolean[allTableSpan]; + subclassTableIsLazyClosure = new boolean[allTableSpan]; + naturalOrderTableNames = new String[tableSpan]; + naturalOrderCascadeDeleteEnabled = new boolean[tableSpan]; + + naturalOrderTableKeyColumns = new String[tableSpan][]; + naturalOrderTableKeyColumnReaders = new String[tableSpan][]; + naturalOrderTableKeyColumnReaderTemplates = new String[tableSpan][]; + //custom sql + customSQLInsert = new String[tableSpan]; + customSQLUpdate = new String[tableSpan]; + customSQLDelete = new String[tableSpan]; + insertCallable = new boolean[tableSpan]; + updateCallable = new boolean[tableSpan]; + deleteCallable = new boolean[tableSpan]; + insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; + updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; + deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; + subclassClosure = new String[subclassSpan+1]; + subclassClosure[subclassSpan] = getEntityName(); + isNullableTable = new boolean[secondaryTableSpan]; + naturalOrderPropertyTableNumbers = new int[hydrateSpan]; + propertyTableNumbers = new int[hydrateSpan]; + constraintOrderedTableNames = new String[allTableSpan]; + constraintOrderedKeyColumnNames = new String[allTableSpan][]; + /** + * 1. core table names + * 2. direct sub entity table names + * 3. core joined table names + * 4. direct sub entity joined table names + */ + final String[] naturalOrderSubclassTableNameClosure = new String[allTableSpan]; + final String[][] naturalOrderSubclassTableKeyColumnClosure = new String[allTableSpan][]; + + + int tableIndex = 0; + int allTableIndex =0; + //first, process tables / entitybindings mapped directly by the current entitybinding and its super entitybindings + for ( int i = 0; i < coreTableSpan; i++, tableIndex++, allTableIndex++ ) { + final TableSpecification table = tables[i]; + final EntityBinding currentEntityBinding = entityBindings[i]; + naturalOrderTableNames[tableIndex] = table.getQualifiedName( factory.getDialect() ); + naturalOrderCascadeDeleteEnabled[tableIndex] = currentEntityBinding.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete(); + naturalOrderTableKeyColumns[tableIndex] = new String[idColumnSpan]; + naturalOrderTableKeyColumnReaders[tableIndex] = new String[idColumnSpan]; + naturalOrderTableKeyColumnReaderTemplates[tableIndex] = new String[idColumnSpan]; + PrimaryKey primaryKey = table.getPrimaryKey(); + resolvePkColumnNames( + factory, + primaryKey, + naturalOrderTableKeyColumns[tableIndex], + naturalOrderTableKeyColumnReaders[tableIndex], + naturalOrderTableKeyColumnReaderTemplates[tableIndex] + ); + final EntityBinding eb = entityBindings[i]; + //Custom SQL + initializeCustomSql( eb.getCustomInsert(), tableIndex, customSQLInsert, insertCallable, insertResultCheckStyles ); + initializeCustomSql( eb.getCustomUpdate(), tableIndex, customSQLUpdate, updateCallable, updateResultCheckStyles ); + initializeCustomSql( eb.getCustomDelete(), tableIndex, customSQLDelete, deleteCallable, deleteResultCheckStyles ); + isClassOrSuperclassTable[allTableIndex] = true;//EntityBindingHelper.isClassOrSuperclassTable( entityBinding, table ); + subclassTableSequentialSelect[allTableIndex] = false; + subclassTableIsLazyClosure[allTableIndex] = false; + } + + //#1 + System.arraycopy( naturalOrderTableNames, 0, naturalOrderSubclassTableNameClosure, 0, coreTableSpan ); + System.arraycopy( naturalOrderTableKeyColumns, 0, naturalOrderSubclassTableKeyColumnClosure, 0, coreTableSpan ); + //--------------------------------- directly sub entities + final String[] naturalOrderSubTableNames = new String[subclassSpan]; + final String[][] naturalOrderSubTableKeyColumns = new String[subclassSpan][idColumnSpan]; + + for ( int i = 0; i < subclassSpan; i++, allTableIndex++ ) { + final EntityBinding subEntityBinding = preOrderSubEntityBindings[i]; //todo post order?? + final TableSpecification table = subEntityBinding.getPrimaryTable(); + naturalOrderSubTableNames[i] = table.getQualifiedName( factory.getDialect() ); + + final PrimaryKey pk = table.getPrimaryKey(); + for(int j=0;j= 0; i--, currentPosition++ ) { + constraintOrderedTableNames[currentPosition] = naturalOrderSubclassTableNameClosure[i]; + constraintOrderedKeyColumnNames[currentPosition] = naturalOrderSubclassTableKeyColumnClosure[i]; + } + subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan ); + subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan ); + + // PROPERTIES + + + ArrayList columnTableNumbers = new ArrayList(); + ArrayList formulaTableNumbers = new ArrayList(); + ArrayList propTableNumbers = new ArrayList(); + for(int i=0;i valueBindings; + if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { + SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class.cast( + attributeBinding + ); + valueBindings = singularAttributeBinding.getRelationalValueBindings(); + } + else { + valueBindings = Collections.EMPTY_LIST; + } + final TableSpecification table; + if ( valueBindings.isEmpty() ) { + table = attributeBinding.getContainer().seekEntityBinding().getPrimaryTable(); + } + else { + // TODO: Can relational value bindings for an attribute binding be in more than one table? + // For now, just get the table from the first one. + table = valueBindings.get( 0 ).getTable(); + } + + final String tableName = table.getQualifiedName( factory.getDialect() ); + if ( i < hydrateSpan ) { + propertyTableNumbers[i] = getTableId( tableName, tableNames ); + naturalOrderPropertyTableNumbers[i] = getTableId( tableName, naturalOrderTableNames ); + } + final int tableNumberInSubclass = getTableId( tableName, subclassTableNameClosure ); + propTableNumbers.add( tableNumberInSubclass ); + for ( RelationalValueBinding vb : valueBindings ) { + if ( vb.isDerived() ) { + formulaTableNumbers.add( tableNumberInSubclass ); + } + else { + columnTableNumbers.add( tableNumberInSubclass ); + } + } + } + + + + subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnTableNumbers ); + subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propTableNumbers ); + subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaTableNumbers ); + // SUBCLASSES + + // DISCRIMINATOR + + if ( entityBinding.isPolymorphic() ) { + final EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator(); + if ( discriminator != null ) { + log.debug( "Encountered explicit discriminator mapping for joined inheritance" ); + + final org.hibernate.metamodel.spi.relational.Value relationalValue = discriminator.getRelationalValue(); + if ( DerivedValue.class.isInstance( relationalValue ) ) { + throw new MappingException( "Discriminator formulas on joined inheritance hierarchies not supported at this time" ); + } + else { + final org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) relationalValue; + explicitDiscriminatorColumnName = column.getColumnName().getText( factory.getDialect() ); + discriminatorAlias = column.getAlias( factory.getDialect(), entityBinding.getPrimaryTable() ); + } + discriminatorType = + (DiscriminatorType) discriminator.getExplicitHibernateTypeDescriptor().getResolvedTypeMapping(); + if ( entityBinding.isDiscriminatorMatchValueNull() ) { + discriminatorValue = NULL_DISCRIMINATOR; + discriminatorSQLString = InFragment.NULL; + } + else if ( entityBinding.isDiscriminatorMatchValueNotNull() ) { + discriminatorValue = NOT_NULL_DISCRIMINATOR; + discriminatorSQLString = InFragment.NOT_NULL; + } + else { + try { + discriminatorValue = discriminatorType.stringToObject( entityBinding.getDiscriminatorMatchValue() ); + discriminatorSQLString = discriminatorType.objectToSQLString( discriminatorValue, factory.getDialect() ); + } + catch (ClassCastException cce) { + throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() ); + } + catch (Exception e) { + throw new MappingException("Could not format discriminator value to SQL string", e); + } + } + } + else { + explicitDiscriminatorColumnName = null; + discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; + discriminatorType = StandardBasicTypes.INTEGER; + try { + discriminatorValue = entityBinding.getSubEntityBindingId(); + discriminatorSQLString = discriminatorValue.toString(); + } + catch ( Exception e ) { + throw new MappingException( "Could not format discriminator value to SQL string", e ); + } + } + subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() ); + discriminatorValues = new String[subclassSpan+1]; + discriminatorValues[subclassSpan] = discriminatorSQLString; + notNullColumnTableNumbers = new int[subclassSpan+1]; + final int id = getTableId( + tableNames[0], //the current entitybinding's primary table name + subclassTableNameClosure + ); + notNullColumnTableNumbers[subclassSpan] = id; + notNullColumnNames = new String[subclassSpan+1]; + notNullColumnNames[subclassSpan] = subclassTableKeyColumnClosure[id][0]; + } + else { + explicitDiscriminatorColumnName = null; + discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS; + discriminatorValues = null; + notNullColumnTableNumbers = null; + notNullColumnNames = null; + discriminatorType = StandardBasicTypes.INTEGER; + discriminatorValue = null; + discriminatorSQLString = null; + } + + for ( int k = 0; k < postOrderSubEntityBindings.length; k++ ) { + final EntityBinding eb = postOrderSubEntityBindings[k]; + subclassClosure[k] = eb.getEntityName(); + try { + if ( entityBinding.isPolymorphic() ) { + // we now use subclass ids that are consistent across all + // persisters for a class hierarchy, so that the use of + // "foo.class = Bar" works in HQL + Integer subclassId = eb.getSubEntityBindingId(); + subclassesByDiscriminatorValue.put( subclassId, eb.getEntityName() ); + discriminatorValues[k] = subclassId.toString(); + int id = getTableId( + eb.getPrimaryTable().getQualifiedName( factory.getDialect() ), + subclassTableNameClosure + ); + notNullColumnTableNumbers[k] = id; + notNullColumnNames[k] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName(); + if(notNullColumnNames[k] == null){ + System.out.println(); + } + } + } + catch ( Exception e ) { + throw new MappingException( "Error parsing discriminator value", e ); + } + } + + subclassNamesBySubclassTable = buildSubclassNamesBySubclassTableMapping( entityBinding, factory ); + + initLockers(); + initSubclassPropertyAliasesMap( entityBinding ); + + postConstruct( mapping ); + } + + + private void resolvePkColumnNames(SessionFactoryImplementor factory, PrimaryKey primaryKey, String[] columns, String[] readers, String[] templates) { + for ( int k = 0; k < primaryKey.getColumnSpan(); k++ ) { + org.hibernate.metamodel.spi.relational.Column column = primaryKey.getColumns().get( k ); + columns[k] = column.getColumnName().getText( factory.getDialect() ); + readers[k] = column.getReadExpr( factory.getDialect() ); + templates[k] = column.getTemplate( + factory.getDialect(), + factory.getSqlFunctionRegistry() + ); + } + } + + private void assertOptimisticLockStyle() { + if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) { + throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" ); + } } protected boolean isNullableTable(int j) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 8196261aaad7..33c223192fe5 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -23,11 +23,11 @@ * */ package org.hibernate.persister.entity; + import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -36,6 +36,7 @@ import org.hibernate.MappingException; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.hibernate.engine.FetchStyle; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -43,23 +44,14 @@ import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.util.MarkerObject; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Formula; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.Subclass; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.TableSpecification; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.sql.InFragment; import org.hibernate.sql.Insert; import org.hibernate.sql.SelectFragment; @@ -127,333 +119,15 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private final String[][] constraintOrderedKeyColumnNames; //private final Map propertyTableNumbersByName = new HashMap(); - private final Map propertyTableNumbersByNameAndSubclass = new HashMap(); + private final Map propertyTableNumbersByNameAndSubclass = new HashMap(); - private final Map sequentialSelectStringsByEntityName = new HashMap(); + private final Map sequentialSelectStringsByEntityName = new HashMap(); private static final Object NULL_DISCRIMINATOR = new MarkerObject(""); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject(""); - private static final String NULL_STRING = "null"; - private static final String NOT_NULL_STRING = "not null"; //INITIALIZATION: - public SingleTableEntityPersister( - final PersistentClass persistentClass, - final EntityRegionAccessStrategy cacheAccessStrategy, - final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - final SessionFactoryImplementor factory, - final Mapping mapping) throws HibernateException { - - super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - - // CLASS + TABLE - - joinSpan = persistentClass.getJoinClosureSpan()+1; - qualifiedTableNames = new String[joinSpan]; - isInverseTable = new boolean[joinSpan]; - isNullableTable = new boolean[joinSpan]; - keyColumnNames = new String[joinSpan][]; - final Table table = persistentClass.getRootTable(); - qualifiedTableNames[0] = table.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - isInverseTable[0] = false; - isNullableTable[0] = false; - keyColumnNames[0] = getIdentifierColumnNames(); - cascadeDeleteEnabled = new boolean[joinSpan]; - - // Custom sql - customSQLInsert = new String[joinSpan]; - customSQLUpdate = new String[joinSpan]; - customSQLDelete = new String[joinSpan]; - insertCallable = new boolean[joinSpan]; - updateCallable = new boolean[joinSpan]; - deleteCallable = new boolean[joinSpan]; - insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; - updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; - deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan]; - - customSQLInsert[0] = persistentClass.getCustomSQLInsert(); - insertCallable[0] = customSQLInsert[0] != null && persistentClass.isCustomInsertCallable(); - insertResultCheckStyles[0] = persistentClass.getCustomSQLInsertCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[0], insertCallable[0] ) - : persistentClass.getCustomSQLInsertCheckStyle(); - customSQLUpdate[0] = persistentClass.getCustomSQLUpdate(); - updateCallable[0] = customSQLUpdate[0] != null && persistentClass.isCustomUpdateCallable(); - updateResultCheckStyles[0] = persistentClass.getCustomSQLUpdateCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[0], updateCallable[0] ) - : persistentClass.getCustomSQLUpdateCheckStyle(); - customSQLDelete[0] = persistentClass.getCustomSQLDelete(); - deleteCallable[0] = customSQLDelete[0] != null && persistentClass.isCustomDeleteCallable(); - deleteResultCheckStyles[0] = persistentClass.getCustomSQLDeleteCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[0], deleteCallable[0] ) - : persistentClass.getCustomSQLDeleteCheckStyle(); - - // JOINS - - Iterator joinIter = persistentClass.getJoinClosureIterator(); - int j = 1; - while ( joinIter.hasNext() ) { - Join join = (Join) joinIter.next(); - qualifiedTableNames[j] = join.getTable().getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - isInverseTable[j] = join.isInverse(); - isNullableTable[j] = join.isOptional(); - cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() && - factory.getDialect().supportsCascadeDelete(); - - customSQLInsert[j] = join.getCustomSQLInsert(); - insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable(); - insertResultCheckStyles[j] = join.getCustomSQLInsertCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] ) - : join.getCustomSQLInsertCheckStyle(); - customSQLUpdate[j] = join.getCustomSQLUpdate(); - updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable(); - updateResultCheckStyles[j] = join.getCustomSQLUpdateCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] ) - : join.getCustomSQLUpdateCheckStyle(); - customSQLDelete[j] = join.getCustomSQLDelete(); - deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable(); - deleteResultCheckStyles[j] = join.getCustomSQLDeleteCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] ) - : join.getCustomSQLDeleteCheckStyle(); - - Iterator iter = join.getKey().getColumnIterator(); - keyColumnNames[j] = new String[ join.getKey().getColumnSpan() ]; - int i = 0; - while ( iter.hasNext() ) { - Column col = (Column) iter.next(); - keyColumnNames[j][i++] = col.getQuotedName( factory.getDialect() ); - } - - j++; - } - - constraintOrderedTableNames = new String[qualifiedTableNames.length]; - constraintOrderedKeyColumnNames = new String[qualifiedTableNames.length][]; - for ( int i = qualifiedTableNames.length - 1, position = 0; i >= 0; i--, position++ ) { - constraintOrderedTableNames[position] = qualifiedTableNames[i]; - constraintOrderedKeyColumnNames[position] = keyColumnNames[i]; - } - - spaces = ArrayHelper.join( - qualifiedTableNames, - ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() ) - ); - - final boolean lazyAvailable = isInstrumented(); - - boolean hasDeferred = false; - ArrayList subclassTables = new ArrayList(); - ArrayList joinKeyColumns = new ArrayList(); - ArrayList isConcretes = new ArrayList(); - ArrayList isDeferreds = new ArrayList(); - ArrayList isInverses = new ArrayList(); - ArrayList isNullables = new ArrayList(); - ArrayList isLazies = new ArrayList(); - subclassTables.add( qualifiedTableNames[0] ); - joinKeyColumns.add( getIdentifierColumnNames() ); - isConcretes.add(Boolean.TRUE); - isDeferreds.add(Boolean.FALSE); - isInverses.add(Boolean.FALSE); - isNullables.add(Boolean.FALSE); - isLazies.add(Boolean.FALSE); - joinIter = persistentClass.getSubclassJoinClosureIterator(); - while ( joinIter.hasNext() ) { - Join join = (Join) joinIter.next(); - isConcretes.add( persistentClass.isClassOrSuperclassJoin(join) ); - isDeferreds.add( join.isSequentialSelect() ); - isInverses.add( join.isInverse() ); - isNullables.add( join.isOptional() ); - isLazies.add( lazyAvailable && join.isLazy() ); - if ( join.isSequentialSelect() && !persistentClass.isClassOrSuperclassJoin(join) ) hasDeferred = true; - subclassTables.add( join.getTable().getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ) ); - Iterator iter = join.getKey().getColumnIterator(); - String[] keyCols = new String[ join.getKey().getColumnSpan() ]; - int i = 0; - while ( iter.hasNext() ) { - Column col = (Column) iter.next(); - keyCols[i++] = col.getQuotedName( factory.getDialect() ); - } - joinKeyColumns.add(keyCols); - } - - subclassTableSequentialSelect = ArrayHelper.toBooleanArray(isDeferreds); - subclassTableNameClosure = ArrayHelper.toStringArray(subclassTables); - subclassTableIsLazyClosure = ArrayHelper.toBooleanArray(isLazies); - subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray( joinKeyColumns ); - isClassOrSuperclassTable = ArrayHelper.toBooleanArray(isConcretes); - isInverseSubclassTable = ArrayHelper.toBooleanArray(isInverses); - isNullableSubclassTable = ArrayHelper.toBooleanArray(isNullables); - hasSequentialSelects = hasDeferred; - - // DISCRIMINATOR - - if ( persistentClass.isPolymorphic() ) { - Value discrimValue = persistentClass.getDiscriminator(); - if (discrimValue==null) { - throw new MappingException("discriminator mapping required for single table polymorphic persistence"); - } - forceDiscriminator = persistentClass.isForceDiscriminator(); - Selectable selectable = (Selectable) discrimValue.getColumnIterator().next(); - if ( discrimValue.hasFormula() ) { - Formula formula = (Formula) selectable; - discriminatorFormula = formula.getFormula(); - discriminatorFormulaTemplate = formula.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - discriminatorColumnName = null; - discriminatorColumnReaders = null; - discriminatorColumnReaderTemplate = null; - discriminatorAlias = "clazz_"; - } - else { - Column column = (Column) selectable; - discriminatorColumnName = column.getQuotedName( factory.getDialect() ); - discriminatorColumnReaders = column.getReadExpr( factory.getDialect() ); - discriminatorColumnReaderTemplate = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); - discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() ); - discriminatorFormula = null; - discriminatorFormulaTemplate = null; - } - discriminatorType = persistentClass.getDiscriminator().getType(); - if ( persistentClass.isDiscriminatorValueNull() ) { - discriminatorValue = NULL_DISCRIMINATOR; - discriminatorSQLValue = InFragment.NULL; - discriminatorInsertable = false; - } - else if ( persistentClass.isDiscriminatorValueNotNull() ) { - discriminatorValue = NOT_NULL_DISCRIMINATOR; - discriminatorSQLValue = InFragment.NOT_NULL; - discriminatorInsertable = false; - } - else { - discriminatorInsertable = persistentClass.isDiscriminatorInsertable() && !discrimValue.hasFormula(); - try { - DiscriminatorType dtype = (DiscriminatorType) discriminatorType; - discriminatorValue = dtype.stringToObject( persistentClass.getDiscriminatorValue() ); - discriminatorSQLValue = dtype.objectToSQLString( discriminatorValue, factory.getDialect() ); - } - catch (ClassCastException cce) { - throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() ); - } - catch (Exception e) { - throw new MappingException("Could not format discriminator value to SQL string", e); - } - } - } - else { - forceDiscriminator = false; - discriminatorInsertable = false; - discriminatorColumnName = null; - discriminatorColumnReaders = null; - discriminatorColumnReaderTemplate = null; - discriminatorAlias = null; - discriminatorType = null; - discriminatorValue = null; - discriminatorSQLValue = null; - discriminatorFormula = null; - discriminatorFormulaTemplate = null; - } - - // PROPERTIES - - propertyTableNumbers = new int[ getPropertySpan() ]; - Iterator iter = persistentClass.getPropertyClosureIterator(); - int i=0; - while( iter.hasNext() ) { - Property prop = (Property) iter.next(); - propertyTableNumbers[i++] = persistentClass.getJoinNumber(prop); - - } - - //TODO: code duplication with JoinedSubclassEntityPersister - - ArrayList columnJoinNumbers = new ArrayList(); - ArrayList formulaJoinedNumbers = new ArrayList(); - ArrayList propertyJoinNumbers = new ArrayList(); - - iter = persistentClass.getSubclassPropertyClosureIterator(); - while ( iter.hasNext() ) { - Property prop = (Property) iter.next(); - Integer join = persistentClass.getJoinNumber(prop); - propertyJoinNumbers.add(join); - - //propertyTableNumbersByName.put( prop.getName(), join ); - propertyTableNumbersByNameAndSubclass.put( - prop.getPersistentClass().getEntityName() + '.' + prop.getName(), - join - ); - - Iterator citer = prop.getColumnIterator(); - while ( citer.hasNext() ) { - Selectable thing = (Selectable) citer.next(); - if ( thing.isFormula() ) { - formulaJoinedNumbers.add(join); - } - else { - columnJoinNumbers.add(join); - } - } - } - subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers); - subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers); - subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propertyJoinNumbers); - - int subclassSpan = persistentClass.getSubclassSpan() + 1; - subclassClosure = new String[subclassSpan]; - subclassClosure[0] = getEntityName(); - if ( persistentClass.isPolymorphic() ) { - addSubclassByDiscriminatorValue( discriminatorValue, getEntityName() ); - } - - // SUBCLASSES - if ( persistentClass.isPolymorphic() ) { - iter = persistentClass.getSubclassIterator(); - int k=1; - while ( iter.hasNext() ) { - Subclass sc = (Subclass) iter.next(); - subclassClosure[k++] = sc.getEntityName(); - if ( sc.isDiscriminatorValueNull() ) { - addSubclassByDiscriminatorValue( NULL_DISCRIMINATOR, sc.getEntityName() ); - } - else if ( sc.isDiscriminatorValueNotNull() ) { - addSubclassByDiscriminatorValue( NOT_NULL_DISCRIMINATOR, sc.getEntityName() ); - } - else { - try { - DiscriminatorType dtype = (DiscriminatorType) discriminatorType; - addSubclassByDiscriminatorValue( - dtype.stringToObject( sc.getDiscriminatorValue() ), - sc.getEntityName() - ); - } - catch (ClassCastException cce) { - throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() ); - } - catch (Exception e) { - throw new MappingException("Error parsing discriminator value", e); - } - } - } - } - - initLockers(); - - initSubclassPropertyAliasesMap(persistentClass); - - postConstruct(mapping); - - } - private void addSubclassByDiscriminatorValue(Object discriminatorValue, String entityName) { String mappedEntityName = (String) subclassesByDiscriminatorValue.put( discriminatorValue, entityName ); if ( mappedEntityName != null ) { @@ -475,9 +149,7 @@ public SingleTableEntityPersister( // CLASS + TABLE - // TODO: fix when joins are working (HHH-6391) - //joinSpan = entityBinding.getJoinClosureSpan() + 1; - joinSpan = 1; + joinSpan = entityBinding.getSecondaryTableClosureSpan() + 1; qualifiedTableNames = new String[joinSpan]; isInverseTable = new boolean[joinSpan]; isNullableTable = new boolean[joinSpan]; @@ -507,7 +179,26 @@ public SingleTableEntityPersister( // JOINS - // TODO: add join stuff when HHH-6391 is working + int j = 1; + for ( SecondaryTable join : entityBinding.getSecondaryTableClosure() ) { + qualifiedTableNames[j] = join.getSecondaryTableReference().getQualifiedName( factory.getDialect() ); + isInverseTable[j] = join.isInverse(); + isNullableTable[j] = join.isOptional(); + cascadeDeleteEnabled[j] = join.isCascadeDeleteEnabled() && + factory.getDialect().supportsCascadeDelete(); + + initializeCustomSql( join.getCustomInsert(), j, customSQLInsert, insertCallable, insertResultCheckStyles ); + initializeCustomSql( join.getCustomUpdate(), j, customSQLUpdate, updateCallable, updateResultCheckStyles ); + initializeCustomSql( join.getCustomDelete(), j, customSQLDelete, deleteCallable, deleteResultCheckStyles ); + + final List joinColumns = join.getForeignKeyReference().getSourceColumns(); + keyColumnNames[j] = new String[ joinColumns.size() ]; + int i = 0; + for ( org.hibernate.metamodel.spi.relational.Column joinColumn : joinColumns ) { + keyColumnNames[j][i++] = joinColumn.getColumnName().getText( factory.getDialect() ); + } + j++; + } constraintOrderedTableNames = new String[qualifiedTableNames.length]; constraintOrderedKeyColumnNames = new String[qualifiedTableNames.length][]; @@ -518,7 +209,7 @@ public SingleTableEntityPersister( spaces = ArrayHelper.join( qualifiedTableNames, - ArrayHelper.toStringArray( entityBinding.getSynchronizedTableNames() ) + entityBinding.getSynchronizedTableNames() ); final boolean lazyAvailable = isInstrumented(); @@ -539,8 +230,24 @@ public SingleTableEntityPersister( isNullables.add(Boolean.FALSE); isLazies.add(Boolean.FALSE); - // TODO: add join stuff when HHH-6391 is working - + for ( SecondaryTable join : entityBinding.getEntitiesSecondaryTableClosure() ) { + final boolean isConcrete = entityBinding.isClassOrSuperclassSecondaryTable( join ); + isConcretes.add( isConcrete ); + final boolean isDeferred = join.getFetchStyle() != FetchStyle.JOIN; + isDeferreds.add( isDeferred ); + isInverses.add( join.isInverse() ); + isNullables.add( join.isOptional() ); + isLazies.add( lazyAvailable && join.isLazy() ); + hasDeferred = isDeferred && !isConcrete; + subclassTables.add( join.getSecondaryTableReference().getQualifiedName( factory.getDialect() ) ); + final List joinColumns = join.getForeignKeyReference().getSourceColumns(); + String[] keyCols = new String[ joinColumns.size() ]; + int i = 0; + for ( org.hibernate.metamodel.spi.relational.Column joinColumn : joinColumns ) { + keyCols[i++] = joinColumn.getColumnName().getText( factory.getDialect() ); + } + joinKeyColumns.add(keyCols); + } subclassTableSequentialSelect = ArrayHelper.toBooleanArray(isDeferreds); subclassTableNameClosure = ArrayHelper.toStringArray(subclassTables); @@ -554,11 +261,12 @@ public SingleTableEntityPersister( // DISCRIMINATOR if ( entityBinding.isPolymorphic() ) { - SimpleValue discriminatorRelationalValue = entityBinding.getHierarchyDetails().getEntityDiscriminator().getBoundValue(); + EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator(); + org.hibernate.metamodel.spi.relational.Value discriminatorRelationalValue = discriminator.getRelationalValue(); if ( discriminatorRelationalValue == null ) { throw new MappingException("discriminator mapping required for single table polymorphic persistence"); } - forceDiscriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator().isForced(); + forceDiscriminator = discriminator.isForced(); if ( DerivedValue.class.isInstance( discriminatorRelationalValue ) ) { DerivedValue formula = ( DerivedValue ) discriminatorRelationalValue; discriminatorFormula = formula.getExpression(); @@ -569,39 +277,34 @@ public SingleTableEntityPersister( discriminatorAlias = "clazz_"; } else { - org.hibernate.metamodel.relational.Column column = ( org.hibernate.metamodel.relational.Column ) discriminatorRelationalValue; - discriminatorColumnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) discriminatorRelationalValue; + discriminatorColumnName = column.getColumnName().getText( factory.getDialect() ); discriminatorColumnReaders = column.getReadFragment() == null ? - column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ) : + column.getColumnName().getText( factory.getDialect() ) : column.getReadFragment(); discriminatorColumnReaderTemplate = getTemplateFromColumn( column, factory ); - discriminatorAlias = column.getAlias( factory.getDialect() ); + discriminatorAlias = column.getAlias( factory.getDialect(), entityBinding.getPrimaryTable() ); discriminatorFormula = null; discriminatorFormulaTemplate = null; } - discriminatorType = entityBinding.getHierarchyDetails() - .getEntityDiscriminator() + discriminatorType = discriminator .getExplicitHibernateTypeDescriptor() .getResolvedTypeMapping(); - if ( entityBinding.getDiscriminatorMatchValue() == null ) { + + if ( entityBinding.isDiscriminatorMatchValueNull() ) { discriminatorValue = NULL_DISCRIMINATOR; discriminatorSQLValue = InFragment.NULL; discriminatorInsertable = false; } - else if ( entityBinding.getDiscriminatorMatchValue().equals( NULL_STRING ) ) { - discriminatorValue = NOT_NULL_DISCRIMINATOR; - discriminatorSQLValue = InFragment.NOT_NULL; - discriminatorInsertable = false; - } - else if ( entityBinding.getDiscriminatorMatchValue().equals( NOT_NULL_STRING ) ) { + else if ( entityBinding.isDiscriminatorMatchValueNotNull() ) { discriminatorValue = NOT_NULL_DISCRIMINATOR; discriminatorSQLValue = InFragment.NOT_NULL; discriminatorInsertable = false; } else { - discriminatorInsertable = entityBinding.getHierarchyDetails().getEntityDiscriminator().isInserted() + discriminatorInsertable = discriminator.isInserted() && ! DerivedValue.class.isInstance( discriminatorRelationalValue ); try { DiscriminatorType dtype = ( DiscriminatorType ) discriminatorType; @@ -634,49 +337,49 @@ else if ( entityBinding.getDiscriminatorMatchValue().equals( NOT_NULL_STRING ) ) propertyTableNumbers = new int[ getPropertySpan() ]; int i=0; - for( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { + for( AttributeBinding attributeBinding : entityBinding.getNonIdAttributeBindingClosure() ) { // TODO: fix when joins are working (HHH-6391) //propertyTableNumbers[i++] = entityBinding.getJoinNumber( attributeBinding); - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - continue; // skip identifier binding + final int tableNumber; + if ( attributeBinding.getAttribute().isSingular() ) { + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + tableNumber = entityBinding.getSecondaryTableNumber( singularAttributeBinding ); } - if ( ! attributeBinding.getAttribute().isSingular() ) { - continue; + else { + tableNumber = 0; } - propertyTableNumbers[ i++ ] = 0; + propertyTableNumbers[ i++ ] = tableNumber; } //TODO: code duplication with JoinedSubclassEntityPersister - ArrayList columnJoinNumbers = new ArrayList(); - ArrayList formulaJoinedNumbers = new ArrayList(); - ArrayList propertyJoinNumbers = new ArrayList(); - - for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) { - if ( ! attributeBinding.getAttribute().isSingular() ) { - continue; - } - SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; - - // TODO: fix when joins are working (HHH-6391) - //int join = entityBinding.getJoinNumber(singularAttributeBinding); - int join = 0; - propertyJoinNumbers.add(join); - - //propertyTableNumbersByName.put( singularAttributeBinding.getName(), join ); - propertyTableNumbersByNameAndSubclass.put( - singularAttributeBinding.getContainer().getPathBase() + '.' + singularAttributeBinding.getAttribute().getName(), - join - ); - - for ( SimpleValueBinding simpleValueBinding : singularAttributeBinding.getSimpleValueBindings() ) { - if ( DerivedValue.class.isInstance( simpleValueBinding.getSimpleValue() ) ) { - formulaJoinedNumbers.add( join ); - } - else { - columnJoinNumbers.add( join ); + ArrayList columnJoinNumbers = new ArrayList(); + ArrayList formulaJoinedNumbers = new ArrayList(); + ArrayList propertyJoinNumbers = new ArrayList(); + + for ( AttributeBinding attributeBinding : entityBinding.getNonIdEntitiesAttributeBindingClosure() ) { + final String entityName = attributeBinding.getContainer().seekEntityBinding().getEntityName(); + final String path = entityName + '.' + attributeBinding.getAttributePath().getFullPath(); + if ( attributeBinding.getAttribute().isSingular() ) { + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + int join = entityBinding.getSecondaryTableNumber( singularAttributeBinding ); + propertyJoinNumbers.add( join ); + // We need the name of the actual entity that contains this attribute binding. + //TODO it should be folder.children but now it is ".children" + propertyTableNumbersByNameAndSubclass.put( path, join ); + for ( RelationalValueBinding relationalValueBinding : singularAttributeBinding.getRelationalValueBindings() ) { + if ( relationalValueBinding.isDerived() ) { + formulaJoinedNumbers.add( join ); + } + else { + columnJoinNumbers.add( join ); + } } } + else { + propertyJoinNumbers.add( 0 ); + propertyTableNumbersByNameAndSubclass.put( path, 0 ); + } } subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers); subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers); @@ -693,19 +396,19 @@ else if ( entityBinding.getDiscriminatorMatchValue().equals( NOT_NULL_STRING ) ) if ( entityBinding.isPolymorphic() ) { int k=1; for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) { - subclassClosure[k++] = subEntityBinding.getEntity().getName(); + subclassClosure[k++] = subEntityBinding.getEntityName(); if ( subEntityBinding.isDiscriminatorMatchValueNull() ) { - addSubclassByDiscriminatorValue( NULL_DISCRIMINATOR, subEntityBinding.getEntity().getName() ); + addSubclassByDiscriminatorValue( NULL_DISCRIMINATOR, subEntityBinding.getEntityName() ); } else if ( subEntityBinding.isDiscriminatorMatchValueNotNull() ) { - addSubclassByDiscriminatorValue( NOT_NULL_DISCRIMINATOR, subEntityBinding.getEntity().getName() ); + addSubclassByDiscriminatorValue( NOT_NULL_DISCRIMINATOR, subEntityBinding.getEntityName() ); } else { try { DiscriminatorType dtype = (DiscriminatorType) discriminatorType; addSubclassByDiscriminatorValue( dtype.stringToObject( subEntityBinding.getDiscriminatorMatchValue() ), - subEntityBinding.getEntity().getName() + subEntityBinding.getEntityName() ); } catch (ClassCastException cce) { @@ -725,19 +428,6 @@ else if ( subEntityBinding.isDiscriminatorMatchValueNotNull() ) { postConstruct( mapping ); } - private static void initializeCustomSql( - CustomSQL customSql, - int i, - String[] sqlStrings, - boolean[] callable, - ExecuteUpdateResultCheckStyle[] checkStyles) { - sqlStrings[i] = customSql != null ? customSql.getSql(): null; - callable[i] = sqlStrings[i] != null && customSql.isCallable(); - checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ? - customSql.getCheckStyle() : - ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] ); - } - protected boolean isInverseTable(int j) { return isInverseTable[j]; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index 06521b13f04f..a8a2d517be71 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -29,6 +29,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -51,9 +52,10 @@ import org.hibernate.internal.util.collections.SingletonIterator; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.sql.SelectFragment; import org.hibernate.sql.SimpleSelect; import org.hibernate.type.StandardBasicTypes; @@ -84,144 +86,116 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { //INITIALIZATION: public UnionSubclassEntityPersister( - final PersistentClass persistentClass, + final EntityBinding entityBinding, final EntityRegionAccessStrategy cacheAccessStrategy, final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, final SessionFactoryImplementor factory, final Mapping mapping) throws HibernateException { - - super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - + super(entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); if ( getIdentifierGenerator() instanceof IdentityGenerator ) { throw new MappingException( - "Cannot use identity column key generation with mapping for: " + - getEntityName() + "Cannot use identity column key generation with mapping for: " + + getEntityName() ); } + tableName = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); - // TABLE - - tableName = persistentClass.getTable().getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); - /*rootTableName = persistentClass.getRootTable().getQualifiedName( - factory.getDialect(), - factory.getDefaultCatalog(), - factory.getDefaultSchema() - );*/ //Custom SQL - - String sql; - boolean callable = false; - ExecuteUpdateResultCheckStyle checkStyle = null; - sql = persistentClass.getCustomSQLInsert(); - callable = sql != null && persistentClass.isCustomInsertCallable(); - checkStyle = sql == null - ? ExecuteUpdateResultCheckStyle.COUNT - : persistentClass.getCustomSQLInsertCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable ) - : persistentClass.getCustomSQLInsertCheckStyle(); - customSQLInsert = new String[] { sql }; - insertCallable = new boolean[] { callable }; - insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; - - sql = persistentClass.getCustomSQLUpdate(); - callable = sql != null && persistentClass.isCustomUpdateCallable(); - checkStyle = sql == null - ? ExecuteUpdateResultCheckStyle.COUNT - : persistentClass.getCustomSQLUpdateCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable ) - : persistentClass.getCustomSQLUpdateCheckStyle(); - customSQLUpdate = new String[] { sql }; - updateCallable = new boolean[] { callable }; - updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; - - sql = persistentClass.getCustomSQLDelete(); - callable = sql != null && persistentClass.isCustomDeleteCallable(); - checkStyle = sql == null - ? ExecuteUpdateResultCheckStyle.COUNT - : persistentClass.getCustomSQLDeleteCheckStyle() == null - ? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable ) - : persistentClass.getCustomSQLDeleteCheckStyle(); - customSQLDelete = new String[] { sql }; - deleteCallable = new boolean[] { callable }; - deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle }; - - discriminatorValue = persistentClass.getSubclassId(); - discriminatorSQLValue = String.valueOf( persistentClass.getSubclassId() ); + // Custom sql + customSQLInsert = new String[1]; + customSQLUpdate = new String[1]; + customSQLDelete = new String[1]; + insertCallable = new boolean[1]; + updateCallable = new boolean[1]; + deleteCallable = new boolean[1]; + insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; + updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; + deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[1]; + + initializeCustomSql( entityBinding.getCustomInsert(), 0, customSQLInsert, insertCallable, insertResultCheckStyles ); + initializeCustomSql( entityBinding.getCustomUpdate(), 0, customSQLUpdate, updateCallable, updateResultCheckStyles ); + initializeCustomSql( entityBinding.getCustomDelete(), 0, customSQLDelete, deleteCallable, deleteResultCheckStyles ); + //discriminator + { + discriminatorValue = entityBinding.getSubEntityBindingId(); + discriminatorSQLValue = String.valueOf( discriminatorValue ); + } // PROPERTIES - int subclassSpan = persistentClass.getSubclassSpan() + 1; + int subclassSpan = entityBinding.getSubEntityBindingClosureSpan() + 1; subclassClosure = new String[subclassSpan]; subclassClosure[0] = getEntityName(); // SUBCLASSES - subclassByDiscriminatorValue.put( - persistentClass.getSubclassId(), - persistentClass.getEntityName() + subclassByDiscriminatorValue.put( + entityBinding.getSubEntityBindingId(), + entityBinding.getEntityName() ); - if ( persistentClass.isPolymorphic() ) { - Iterator iter = persistentClass.getSubclassIterator(); + if ( entityBinding.isPolymorphic() ) { int k=1; - while ( iter.hasNext() ) { - Subclass sc = (Subclass) iter.next(); - subclassClosure[k++] = sc.getEntityName(); - subclassByDiscriminatorValue.put( sc.getSubclassId(), sc.getEntityName() ); + for(EntityBinding subEntityBinding : entityBinding.getPreOrderSubEntityBindingClosure()){ + subclassClosure[k++] = subEntityBinding.getEntityName(); + subclassByDiscriminatorValue.put( subEntityBinding.getSubEntityBindingId(), subEntityBinding.getEntityName() ); } } - + + //SPACES //TODO: i'm not sure, but perhaps we should exclude // abstract denormalized tables? - - int spacesSize = 1 + persistentClass.getSynchronizedTables().size(); + + String[] synchronizedTableNames = entityBinding.getSynchronizedTableNames(); + int spacesSize = 1 +synchronizedTableNames.length; spaces = new String[spacesSize]; spaces[0] = tableName; - Iterator iter = persistentClass.getSynchronizedTables().iterator(); - for ( int i=1; i subclassTables = new HashSet(); + final EntityBinding[] subEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure(); + /* + TODO: here we actually need all entitybindings in the hierarchy, for example: + A + / \ + B C + / \ + D E + + if the current entity is A, then here we need to process all A,B,C,D,E + but if the current entity D, then here we need D,B,A + if the current entity is B, then still A,B,D + */ + + + EntityBinding[] ebs = ArrayHelper.join( entityBinding.getEntityBindingClosure(), subEntityBindings ); + for ( EntityBinding subEntityBinding : ebs ) { + subclassTables.add( subEntityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ) ); } - subclassSpaces = ArrayHelper.toStringArray(subclassTables); + subclassSpaces = ArrayHelper.toStringArray( subclassTables ); - subquery = generateSubquery(persistentClass, mapping); + subquery = generateSubquery( entityBinding ); if ( isMultiTable() ) { int idColumnSpan = getIdentifierColumnSpan(); - ArrayList tableNames = new ArrayList(); - ArrayList keyColumns = new ArrayList(); + ArrayList tableNames = new ArrayList(); + ArrayList keyColumns = new ArrayList(); if ( !isAbstract() ) { tableNames.add( tableName ); keyColumns.add( getIdentifierColumnNames() ); } - iter = persistentClass.getSubclassTableClosureIterator(); - while ( iter.hasNext() ) { - Table tab = ( Table ) iter.next(); - if ( !tab.isAbstractUnionTable() ) { - String tableName = tab.getQualifiedName( - factory.getDialect(), - factory.getSettings().getDefaultCatalogName(), - factory.getSettings().getDefaultSchemaName() - ); + ebs = ArrayHelper.join( new EntityBinding[]{entityBinding}, subEntityBindings ); + for(final EntityBinding eb : ebs){ + TableSpecification tab = eb.getPrimaryTable(); + if ( isNotAbstractUnionTable( eb ) ) { + String tableName = tab.getQualifiedName( factory.getDialect() ); tableNames.add( tableName ); String[] key = new String[idColumnSpan]; - Iterator citer = tab.getPrimaryKey().getColumnIterator(); - for ( int k=0; k columns = tab.getPrimaryKey().getColumns(); + for ( int k = 0; k < idColumnSpan; k++ ) { + key[k] = columns.get( k ).getColumnName().getText( factory.getDialect() ); } keyColumns.add( key ); } @@ -234,32 +208,9 @@ public UnionSubclassEntityPersister( constraintOrderedTableNames = new String[] { tableName }; constraintOrderedKeyColumnNames = new String[][] { getIdentifierColumnNames() }; } - initLockers(); - - initSubclassPropertyAliasesMap(persistentClass); - + initSubclassPropertyAliasesMap(entityBinding); postConstruct(mapping); - - } - - public UnionSubclassEntityPersister( - final EntityBinding entityBinding, - final EntityRegionAccessStrategy cacheAccessStrategy, - final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - final SessionFactoryImplementor factory, - final Mapping mapping) throws HibernateException { - super(entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); - // TODO: implement!!! initializing final fields to null to make compiler happy. - subquery = null; - tableName = null; - subclassClosure = null; - spaces = null; - subclassSpaces = null; - discriminatorValue = null; - discriminatorSQLValue = null; - constraintOrderedTableNames = null; - constraintOrderedKeyColumnNames = null; } public Serializable[] getQuerySpaces() { @@ -414,6 +365,106 @@ protected int[] getPropertyTableNumbers() { return new int[ getPropertySpan() ]; } + private boolean isNotAbstractUnionTable(EntityBinding entityBinding) { +// return !entityBinding.isAbstract() && entityBinding.getHierarchyDetails() +// .getInheritanceType() != InheritanceType.TABLE_PER_CLASS; + return !entityBinding.isAbstract(); + } + private void visitEntityHierarchy(EntityBinding entityBinding, Callback callback){ + EntityBinding rootEntityBinding = entityBinding.getHierarchyDetails().getRootEntityBinding(); + callback.execute( rootEntityBinding ); + visitSubEntityBindings( rootEntityBinding, callback ); + } + private void visitSubEntityBindings(EntityBinding superEntityBinding, Callback callback){ + callback.execute( superEntityBinding ); + Iterable entityBindings= superEntityBinding.getDirectSubEntityBindings(); +// for(EntityBinding entityBinding : entityBindings){ +// callback.execute( entityBinding ); +// } + for(EntityBinding entityBinding : entityBindings){ + visitSubEntityBindings( entityBinding, callback ); + } + } + private static interface Callback{ + void execute(EntityBinding entityBinding); + } + protected String generateSubquery(EntityBinding entityBinding){ + final Dialect dialect = getFactory().getDialect(); + + if ( !entityBinding.hasSubEntityBindings() ) { + return entityBinding.getPrimaryTable().getQualifiedName( dialect ); + } + + final HashSet columns = new LinkedHashSet(); +// Iterable subEntityBindings = entityBinding.getHierarchyDetails()..getEntityBindingClosure(); + +// for(EntityBinding eb : subEntityBindings){ +// if ( isNotAbstractUnionTable( eb ) ) { +// TableSpecification table = entityBinding.getPrimaryTable(); +// for ( Value v : table.values() ) { +// if ( org.hibernate.metamodel.spi.relational.Column.class.isInstance( v ) ) { +// columns.add( org.hibernate.metamodel.spi.relational.Column.class.cast( v ) ); +// } +// } +// } +// } + + visitSubEntityBindings( + entityBinding, new Callback() { + @Override + public void execute(EntityBinding eb) { + if ( isNotAbstractUnionTable( eb ) ) { + TableSpecification table = eb.getPrimaryTable(); + for ( Value v : table.values() ) { + if ( org.hibernate.metamodel.spi.relational.Column.class.isInstance( v ) ) { + columns.add( org.hibernate.metamodel.spi.relational.Column.class.cast( v ) ); + } + } + } + } + } + ); + + + final StringBuilder buf = new StringBuilder() + .append("( "); + + visitSubEntityBindings( entityBinding, new Callback() { + @Override + public void execute(EntityBinding eb) { + TableSpecification table = eb.getPrimaryTable(); + if ( isNotAbstractUnionTable( eb )) { + //TODO: move to .sql package!! + buf.append("select "); + for(org.hibernate.metamodel.spi.relational.Column column : columns){ + if(!table.hasValue( column )){ + buf.append( dialect.getSelectClauseNullString(column.getJdbcDataType().getTypeCode()) ) + .append(" as "); + } + buf.append( column.getColumnName().getText( dialect ) ); + buf.append( ", " ); + } + buf.append( eb.getSubEntityBindingId() ) + .append( " as clazz_" ); + buf.append(" from ") + .append( table.getQualifiedName( dialect )); + buf.append(" union "); + if ( dialect.supportsUnionAll() ) { + buf.append("all "); + } + } + } + } ); + + + if ( buf.length() > 2 ) { + //chop the last union (all) + buf.setLength( buf.length() - ( dialect.supportsUnionAll() ? 11 : 7 ) ); + } + + return buf.append(" )").toString(); + } + protected String generateSubquery(PersistentClass model, Mapping mapping) { Dialect dialect = getFactory().getDialect(); @@ -459,7 +510,7 @@ protected String generateSubquery(PersistentClass model, Mapping mapping) { buf.append( dialect.getSelectClauseNullString(sqlType) ) .append(" as "); } - buf.append( col.getName() ); + buf.append( col.getQuotedName(dialect) ); buf.append(", "); } buf.append( clazz.getSubclassId() ) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java index 41550e06bf7c..f3b1a24df8a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java @@ -36,10 +36,10 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.spi.PersisterClassResolver; @@ -99,7 +99,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi /** * The constructor signature for {@link CollectionPersister} implementations using - * a {@link org.hibernate.metamodel.binding.AbstractPluralAttributeBinding} + * a {@link org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding} * * @todo still need to make collection persisters EntityMode-aware * @todo make EntityPersister *not* depend on {@link SessionFactoryImplementor} if possible. @@ -125,27 +125,29 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) { public EntityPersister createEntityPersister( PersistentClass metadata, EntityRegionAccessStrategy cacheAccessStrategy, - NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdAccessStrategy, SessionFactoryImplementor factory, Mapping cfg) { Class persisterClass = metadata.getEntityPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( metadata ); } - return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS, metadata, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, cfg ); + return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS, metadata, cacheAccessStrategy, naturalIdAccessStrategy, factory, cfg ); } @Override @SuppressWarnings( {"unchecked"}) - public EntityPersister createEntityPersister(EntityBinding metadata, - EntityRegionAccessStrategy cacheAccessStrategy, - SessionFactoryImplementor factory, - Mapping cfg) { + public EntityPersister createEntityPersister( + EntityBinding metadata, + EntityRegionAccessStrategy cacheAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdAccessStrategy, + SessionFactoryImplementor factory, + Mapping cfg) { Class persisterClass = metadata.getCustomEntityPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( metadata ); } - return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, cacheAccessStrategy, null, factory, cfg ); + return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, cacheAccessStrategy, naturalIdAccessStrategy, factory, cfg ); } // TODO: change metadata arg type to EntityBinding when new metadata is integrated @@ -208,12 +210,12 @@ public CollectionPersister createCollectionPersister( PluralAttributeBinding collectionMetadata, CollectionRegionAccessStrategy cacheAccessStrategy, SessionFactoryImplementor factory) throws HibernateException { - Class persisterClass = collectionMetadata.getCollectionPersisterClass(); + Class persisterClass = collectionMetadata.getExplicitPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getCollectionPersisterClass( collectionMetadata ); } - return create( persisterClass, COLLECTION_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, collectionMetadata, cacheAccessStrategy, factory ); + return create( persisterClass, COLLECTION_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, collectionMetadata, cacheAccessStrategy, factory ); } // TODO: change collectionMetadata arg type to AbstractPluralAttributeBinding when new metadata is integrated diff --git a/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java b/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java index 8c7118a2b4fd..f671f8cc9622 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/internal/StandardPersisterClassResolver.java @@ -31,9 +31,9 @@ import org.hibernate.mapping.RootClass; import org.hibernate.mapping.SingleTableSubclass; import org.hibernate.mapping.UnionSubclass; -import org.hibernate.metamodel.binding.CollectionElementNature; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.BasicCollectionPersister; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.OneToManyPersister; @@ -72,7 +72,7 @@ public Class getEntityPersisterClass(EntityBinding me } default: { throw new UnknownPersisterException( - "Could not determine persister implementation for entity [" + metadata.getEntity().getName() + "]" + "Could not determine persister implementation for entity [" + metadata.getEntityName() + "]" ); } @@ -126,7 +126,7 @@ public Class getCollectionPersisterClass(Collecti @Override public Class getCollectionPersisterClass(PluralAttributeBinding metadata) { - return metadata.getCollectionElement().getCollectionElementNature() == CollectionElementNature.ONE_TO_MANY + return metadata.getPluralAttributeElementBinding().getNature() == PluralAttributeElementNature.ONE_TO_MANY ? oneToManyPersister() : basicCollectionPersister(); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java index 3ce6e660a014..04b29b28601c 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterClassResolver.java @@ -25,8 +25,8 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.Service; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java index d03b20816a9d..bd97fef1bdce 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java @@ -32,9 +32,9 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.Service; @@ -60,6 +60,7 @@ public interface PersisterFactory extends Service { * * @param model The O/R mapping metamodel definition for the entity * @param cacheAccessStrategy The caching strategy for this entity + * @param naturalIdAccessStrategy The caching strategy for accessing this entity's natural ID * @param factory The session factory * @param cfg The overall mapping * @@ -89,6 +90,7 @@ public EntityPersister createEntityPersister( public EntityPersister createEntityPersister( EntityBinding model, EntityRegionAccessStrategy cacheAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdAccessStrategy, SessionFactoryImplementor factory, Mapping cfg) throws HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java index fb01a6a29280..f2f144f228b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java @@ -38,7 +38,7 @@ import org.hibernate.QueryException; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionFactoryImplementor; diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/Util.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/Util.java index ef332619e52a..d8500df52d33 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/Util.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/Util.java @@ -23,6 +23,7 @@ */ package org.hibernate.procedure.internal; +import java.util.Collection; import java.util.Map; import java.util.Set; @@ -148,6 +149,31 @@ public static void resolveResultSetMappings(ResultSetMappingResolutionContext co } } + /** + * Resolve the given result set mapping names + * + * @param context The context for the resolution. See {@link ResultSetMappingResolutionContext} + * @param resultSetMappingNames The names of the result-set-mappings to resolve + */ + public static void resolveResultSetMappings(ResultSetMappingResolutionContext context, Collection resultSetMappingNames) { + for ( String resultSetMappingName : resultSetMappingNames ) { + log.tracef( "Starting attempt resolve named result-set-mapping : %s", resultSetMappingName ); + final ResultSetMappingDefinition mapping = context.findResultSetMapping( resultSetMappingName ); + if ( mapping == null ) { + throw new UnknownSqlResultSetMappingException( "Unknown SqlResultSetMapping [" + resultSetMappingName + "]" ); + } + + log.tracef( "Found result-set-mapping : %s", mapping.traceLoggableFormat() ); + + context.addQueryReturns( mapping.getQueryReturns() ); + + final SQLQueryReturnProcessor processor = + new SQLQueryReturnProcessor( mapping.getQueryReturns(), context.getSessionFactory() ); + final SQLQueryReturnProcessor.ResultAliasContext processResult = processor.process(); + context.addQuerySpaces( processResult.collectQuerySpaces() ); + } + } + /** * Context for resolving result-class definitions */ diff --git a/hibernate-core/src/main/java/org/hibernate/property/BasicPropertyAccessor.java b/hibernate-core/src/main/java/org/hibernate/property/BasicPropertyAccessor.java index ea835a736f63..75d18625aa3c 100644 --- a/hibernate-core/src/main/java/org/hibernate/property/BasicPropertyAccessor.java +++ b/hibernate-core/src/main/java/org/hibernate/property/BasicPropertyAccessor.java @@ -37,9 +37,6 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; - -import org.jboss.logging.Logger; /** * Accesses property values via a get/set pair, which may be nonpublic. @@ -260,7 +257,7 @@ private static BasicSetter getSetterOrNull(Class theClass, String propertyName) Method method = setterMethod(theClass, propertyName); if (method!=null) { - if ( !ReflectHelper.isPublic(theClass, method) ) method.setAccessible(true); + method.setAccessible(true); return new BasicSetter(theClass, method, propertyName); } else { @@ -308,10 +305,8 @@ public static Getter createGetter(Class theClass, String propertyName) throws Pr BasicGetter result = getGetterOrNull(theClass, propertyName); if (result==null) { throw new PropertyNotFoundException( - "Could not find a getter for " + - propertyName + - " in class " + - theClass.getName() + "Could not find a getter for [" + propertyName + + "] in class [" + theClass.getName() + "]" ); } return result; @@ -325,9 +320,7 @@ private static BasicGetter getGetterOrNull(Class theClass, String propertyName) Method method = getterMethod(theClass, propertyName); if (method!=null) { - if ( !ReflectHelper.isPublic( theClass, method ) ) { - method.setAccessible(true); - } + method.setAccessible(true); return new BasicGetter(theClass, method, propertyName); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/property/DirectPropertyAccessor.java b/hibernate-core/src/main/java/org/hibernate/property/DirectPropertyAccessor.java index 1858960b279a..89a358a9963d 100644 --- a/hibernate-core/src/main/java/org/hibernate/property/DirectPropertyAccessor.java +++ b/hibernate-core/src/main/java/org/hibernate/property/DirectPropertyAccessor.java @@ -157,7 +157,7 @@ private static Field getField(Class clazz, String name) throws PropertyNotFoundE catch (NoSuchFieldException nsfe) { field = getField( clazz, clazz.getSuperclass(), name ); } - if ( !ReflectHelper.isPublic(clazz, field) ) field.setAccessible(true); + field.setAccessible(true); return field; } @@ -172,7 +172,7 @@ private static Field getField(Class root, Class clazz, String name) throws Prope catch (NoSuchFieldException nsfe) { field = getField( root, clazz.getSuperclass(), name ); } - if ( !ReflectHelper.isPublic(clazz, field) ) field.setAccessible(true); + field.setAccessible(true); return field; } diff --git a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java index bc5969935a73..dae34e9da1d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java @@ -30,7 +30,7 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; /** * A factory for building/retrieving PropertyAccessor instances. diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java b/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java index 3e77376a64a9..e79b8021656c 100755 --- a/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java @@ -26,6 +26,7 @@ import java.io.Serializable; import javax.naming.NamingException; +import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.LazyInitializationException; import org.hibernate.Session; @@ -59,7 +60,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { private Boolean readOnlyBeforeAttachedToSession; private String sessionFactoryUuid; - private boolean specjLazyLoad; + private boolean allowLoadOutsideTransaction; /** * For serialization from the non-pojo initializers (HHH-3309) @@ -148,7 +149,7 @@ private static EntityKey generateEntityKeyOrNull(Serializable id, SessionImpleme @Override public final void unsetSession() { - prepareForPossibleSpecialSpecjInitialization(); + prepareForPossibleLoadingOutsideTransaction(); session = null; readOnly = false; readOnlyBeforeAttachedToSession = null; @@ -157,8 +158,8 @@ public final void unsetSession() { @Override public final void initialize() throws HibernateException { if ( !initialized ) { - if ( specjLazyLoad ) { - specialSpecjInitialization(); + if ( allowLoadOutsideTransaction ) { + permissiveInitialization(); } else if ( session == null ) { throw new LazyInitializationException( "could not initialize proxy - no Session" ); @@ -180,7 +181,7 @@ else if ( !session.isConnected() ) { } } - protected void specialSpecjInitialization() { + protected void permissiveInitialization() { if ( session == null ) { //we have a detached collection thats set to null, reattach if ( sessionFactoryUuid == null ) { @@ -190,9 +191,9 @@ protected void specialSpecjInitialization() { SessionFactoryImplementor sf = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid ); SessionImplementor session = (SessionImplementor) sf.openSession(); - - // TODO: On the next major release, add an - // 'isJTA' or 'getTransactionFactory' method to Session. + session.getPersistenceContext().setDefaultReadOnly( true ); + session.setFlushMode( FlushMode.MANUAL ); + boolean isJTA = session.getTransactionCoordinator() .getTransactionContext().getTransactionEnvironment() .getTransactionFactory() @@ -240,11 +241,11 @@ else if ( session.isOpen() && session.isConnected() ) { } } - protected void prepareForPossibleSpecialSpecjInitialization() { + protected void prepareForPossibleLoadingOutsideTransaction() { if ( session != null ) { - specjLazyLoad = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled(); + allowLoadOutsideTransaction = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled(); - if ( specjLazyLoad && sessionFactoryUuid == null ) { + if ( allowLoadOutsideTransaction && sessionFactoryUuid == null ) { try { sessionFactoryUuid = (String) session.getFactory().getReference().get( "uuid" ).getContent(); } diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java index b539e7178952..0734307ed421 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java @@ -187,14 +187,16 @@ public Object invoke( try { if ( ReflectHelper.isPublic( persistentClass, thisMethod ) ) { if ( !thisMethod.getDeclaringClass().isInstance( target ) ) { - throw new ClassCastException( target.getClass().getName() ); + throw new ClassCastException( + target.getClass().getName() + + " incompatible with " + + thisMethod.getDeclaringClass().getName() + ); } returnValue = thisMethod.invoke( target, args ); } else { - if ( !thisMethod.isAccessible() ) { - thisMethod.setAccessible( true ); - } + thisMethod.setAccessible( true ); returnValue = thisMethod.invoke( target, args ); } diff --git a/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java b/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java index a8a05315ed14..9adc2ad53fa2 100644 --- a/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java @@ -198,15 +198,6 @@ protected Output buildOutput() { hasExtendedReturns() ); } - // todo : temporary for tck testing... - System.out.println( - String.format( - "Building Return [isResultSet=%s, updateCount=%s, extendedReturn=%s", - isResultSet(), - getUpdateCount(), - hasExtendedReturns() - ) - ); if ( isResultSet() ) { return buildResultSetOutput( extractCurrentResults() ); diff --git a/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java b/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java index c16c9b04b858..239055e406e1 100644 --- a/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java @@ -33,7 +33,7 @@ import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.ServiceContributingIntegrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.secure.internal.DisabledJaccServiceImpl; import org.hibernate.secure.internal.JaccPreDeleteEventListener; import org.hibernate.secure.internal.JaccPreInsertEventListener; @@ -78,7 +78,7 @@ public void integrate( Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - doIntegration( configuration.getProperties(), configuration.getJaccPermissionDeclarations(), serviceRegistry ); + doIntegration( configuration.getProperties(), null, serviceRegistry ); } private void doIntegration( @@ -121,6 +121,7 @@ public void integrate( MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + // todo : need to stash the JACC permissions somewhere accessible from here... doIntegration( sessionFactory.getProperties(), null, serviceRegistry ); } diff --git a/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccPermissionDeclarations.java b/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccPermissionDeclarations.java index 571cba36a333..73ef8b4ab9a2 100644 --- a/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccPermissionDeclarations.java +++ b/hibernate-core/src/main/java/org/hibernate/secure/spi/JaccPermissionDeclarations.java @@ -24,6 +24,7 @@ package org.hibernate.secure.spi; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -37,6 +38,10 @@ public JaccPermissionDeclarations(String contextId) { this.contextId = contextId; } + public String getContextId() { + return contextId; + } + public void addPermissionDeclaration(GrantedPermission permissionDeclaration) { if ( permissionDeclarations == null ) { permissionDeclarations = new ArrayList(); @@ -44,7 +49,9 @@ public void addPermissionDeclaration(GrantedPermission permissionDeclaration) { permissionDeclarations.add( permissionDeclaration ); } - public Iterable getPermissionDeclarations() { - return permissionDeclarations; + public List getPermissionDeclarations() { + return permissionDeclarations == null + ? Collections.emptyList() + : permissionDeclarations; } } diff --git a/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java b/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java index 5f9d75668e33..699f108adfa3 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/service/ConfigLoader.java @@ -23,15 +23,19 @@ */ package org.hibernate.service; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.util.Properties; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.SourceType; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.ValueHolder; import org.hibernate.internal.util.config.ConfigurationException; import org.hibernate.service.internal.JaxbProcessor; @@ -66,7 +70,53 @@ public JaxbHibernateConfiguration loadConfigXmlResource(String cfgXmlResourceNam if ( stream == null ) { throw new ConfigurationException( "Could not locate cfg.xml resource [" + cfgXmlResourceName + "]" ); } - return jaxbProcessorHolder.getValue().unmarshal( stream, new Origin( SourceType.RESOURCE, cfgXmlResourceName ) ); + return unmarshall( stream, new Origin( SourceType.RESOURCE, cfgXmlResourceName ) ); + } + + private JaxbHibernateConfiguration unmarshall(InputStream stream, Origin origin) { + try { + return jaxbProcessorHolder.getValue().unmarshal( stream, origin ); + } + finally { + try { + stream.close(); + } + catch (IOException e) { + log.debug( "Unable to close config input stream : " + e.getMessage() ); + } + } + } + + public JaxbHibernateConfiguration loadConfigFile(File cfgXmlFile) { + final InputStream stream = toStream( cfgXmlFile ); + return unmarshall( stream, new Origin( SourceType.FILE, cfgXmlFile.getAbsolutePath() ) ); + } + + private InputStream toStream(File file) { + try { + return new FileInputStream( file ); + } + catch (FileNotFoundException e) { + throw new ConfigurationException( + "Could not open input stream from File [" + file.getAbsolutePath() + "]" + ); + } + } + + public JaxbHibernateConfiguration loadConfig(URL configFileUrl) { + final InputStream stream = toStream( configFileUrl ); + return unmarshall( stream, new Origin( SourceType.URL, configFileUrl.toExternalForm() ) ); + } + + private InputStream toStream(URL configFileUrl) { + try { + return configFileUrl.openStream(); + } + catch (IOException e) { + throw new ConfigurationException( + "Could not open input stream from config file url [" + configFileUrl.toExternalForm() + "]" + ); + } } public Properties loadProperties(String resourceName) { @@ -91,4 +141,27 @@ public Properties loadProperties(String resourceName) { } } } + + public Properties loadProperties(File propertyFile) { + final InputStream stream = toStream( propertyFile ); + try { + Properties properties = new Properties(); + properties.load( stream ); + return properties; + } + catch (IOException e) { + throw new ConfigurationException( "Unable to apply settings from properties file [" + propertyFile + "]", e ); + } + finally { + try { + stream.close(); + } + catch (IOException e) { + log.debug( + String.format( "Unable to close properties file [%s] stream", propertyFile ), + e + ); + } + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java b/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java index 9df6799c3cba..5a5c9060d964 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java +++ b/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java @@ -36,6 +36,7 @@ import org.hibernate.engine.jdbc.cursor.internal.RefCursorSupportInitiator; import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryInitiator; import org.hibernate.engine.jdbc.dialect.internal.DialectResolverInitiator; +import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator; import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator; import org.hibernate.engine.jndi.internal.JndiServiceInitiator; import org.hibernate.engine.transaction.internal.TransactionFactoryInitiator; @@ -47,6 +48,7 @@ import org.hibernate.persister.internal.PersisterFactoryInitiator; import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator; import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator; +import org.hibernate.tool.schema.internal.SchemaManagementToolInitiator; /** * Central definition of the standard set of service initiators defined by Hibernate. @@ -76,9 +78,12 @@ private static List buildStandardServiceInitiatorList( serviceInitiators.add( DialectResolverInitiator.INSTANCE ); serviceInitiators.add( DialectFactoryInitiator.INSTANCE ); serviceInitiators.add( BatchBuilderInitiator.INSTANCE ); + serviceInitiators.add( JdbcEnvironmentInitiator.INSTANCE ); serviceInitiators.add( JdbcServicesInitiator.INSTANCE ); serviceInitiators.add( RefCursorSupportInitiator.INSTANCE ); + serviceInitiators.add( SchemaManagementToolInitiator.INSTANCE ); + serviceInitiators.add( MutableIdentifierGeneratorFactoryInitiator.INSTANCE); serviceInitiators.add( JtaPlatformResolverInitiator.INSTANCE ); diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java index 0970dcb3aa57..23af9653ab11 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java @@ -24,9 +24,10 @@ package org.hibernate.service.internal; import java.lang.reflect.Method; +import java.util.HashSet; import java.util.List; import java.util.ListIterator; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Set; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.cfg.Environment; @@ -63,30 +64,56 @@ public abstract class AbstractServiceRegistryImpl private final ServiceRegistryImplementor parent; private final boolean allowCrawling; - private final ConcurrentHashMap serviceBindingMap = CollectionHelper.concurrentMap( 20 ); - private ConcurrentHashMap roleXref; + private final ConcurrentServiceBinding serviceBindingMap = new ConcurrentServiceBinding(); + private ConcurrentServiceBinding roleXref; // IMPL NOTE : the list used for ordered destruction. Cannot used map above because we need to // iterate it in reverse order which is only available through ListIterator // assume 20 services for initial sizing private final List serviceBindingList = CollectionHelper.arrayList( 20 ); + private boolean autoCloseRegistry; + private Set childRegistries; + @SuppressWarnings( {"UnusedDeclaration"}) protected AbstractServiceRegistryImpl() { this( (ServiceRegistryImplementor) null ); } + @SuppressWarnings( {"UnusedDeclaration"}) + protected AbstractServiceRegistryImpl(boolean autoCloseRegistry) { + this( (ServiceRegistryImplementor) null, autoCloseRegistry ); + } + protected AbstractServiceRegistryImpl(ServiceRegistryImplementor parent) { + this( parent, true ); + } + + protected AbstractServiceRegistryImpl( + ServiceRegistryImplementor parent, + boolean autoCloseRegistry) { this.parent = parent; this.allowCrawling = ConfigurationHelper.getBoolean( ALLOW_CRAWLING, Environment.getProperties(), true ); + + this.autoCloseRegistry = autoCloseRegistry; + this.parent.registerChild( this ); } public AbstractServiceRegistryImpl(BootstrapServiceRegistry bootstrapServiceRegistry) { + this( bootstrapServiceRegistry, true ); + } + + public AbstractServiceRegistryImpl( + BootstrapServiceRegistry bootstrapServiceRegistry, + boolean autoCloseRegistry) { if ( ! ServiceRegistryImplementor.class.isInstance( bootstrapServiceRegistry ) ) { throw new IllegalArgumentException( "ServiceRegistry parent needs to implement ServiceRegistryImplementor" ); } this.parent = (ServiceRegistryImplementor) bootstrapServiceRegistry; this.allowCrawling = ConfigurationHelper.getBoolean( ALLOW_CRAWLING, Environment.getProperties(), true ); + + this.autoCloseRegistry = autoCloseRegistry; + this.parent.registerChild( this ); } @SuppressWarnings({ "unchecked" }) @@ -134,8 +161,9 @@ protected ServiceBinding locateServiceBinding(Class se // look for a previously resolved alternate registration if ( roleXref != null ) { - if ( roleXref.containsKey( serviceRole ) ) { - return serviceBindingMap.get( roleXref.get( serviceRole ) ); + final Class alternative = roleXref.get( serviceRole ); + if ( alternative != null ) { + return serviceBindingMap.get( alternative ); } } @@ -161,7 +189,7 @@ protected ServiceBinding locateServiceBinding(Class se private void registerAlternate(Class alternate, Class target) { if ( roleXref == null ) { - roleXref = CollectionHelper.concurrentMap( 20 ); + roleXref = new ConcurrentServiceBinding(); } roleXref.put( alternate, target ); } @@ -309,18 +337,36 @@ public void startService(ServiceBinding serviceBinding) { } } + private boolean active = true; + + public boolean isActive() { + return active; + } + @Override @SuppressWarnings( {"unchecked"}) public void destroy() { - synchronized ( serviceBindingList ) { - ListIterator serviceBindingsIterator = serviceBindingList.listIterator( serviceBindingList.size() ); - while ( serviceBindingsIterator.hasPrevious() ) { - final ServiceBinding serviceBinding = serviceBindingsIterator.previous(); - serviceBinding.getLifecycleOwner().stopService( serviceBinding ); + if ( !active ) { + return; + } + + active = false; + try { + synchronized (serviceBindingList) { + ListIterator serviceBindingsIterator = serviceBindingList.listIterator( + serviceBindingList.size() + ); + while ( serviceBindingsIterator.hasPrevious() ) { + final ServiceBinding serviceBinding = serviceBindingsIterator.previous(); + serviceBinding.getLifecycleOwner().stopService( serviceBinding ); + } + serviceBindingList.clear(); } - serviceBindingList.clear(); + serviceBindingMap.clear(); + } + finally { + parent.deRegisterChild( this ); } - serviceBindingMap.clear(); } @Override @@ -335,4 +381,40 @@ public void stopService(ServiceBinding binding) { } } } + + @Override + public void registerChild(ServiceRegistryImplementor child) { + if ( childRegistries == null ) { + childRegistries = new HashSet(); + } + if ( !childRegistries.add( child ) ) { + log.warnf( + "Child ServiceRegistry [%s] was already registered; this will end badly later...", + child + ); + } + } + + @Override + public void deRegisterChild(ServiceRegistryImplementor child) { + if ( childRegistries == null ) { + throw new IllegalStateException( "No child ServiceRegistry registrations found" ); + } + childRegistries.remove( child ); + if ( childRegistries.isEmpty() ) { + if ( autoCloseRegistry ) { + log.debug( + "Implicitly destroying ServiceRegistry on de-registration " + + "of all child ServiceRegistries" + ); + destroy(); + } + else { + log.debug( + "Skipping implicitly destroying ServiceRegistry on de-registration " + + "of all child ServiceRegistries" + ); + } + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/ConcurrentServiceBinding.java b/hibernate-core/src/main/java/org/hibernate/service/internal/ConcurrentServiceBinding.java new file mode 100644 index 000000000000..aef9b5eae61b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/ConcurrentServiceBinding.java @@ -0,0 +1,221 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.service.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Since Service lookup is a very hot operation and essentially it's a read only + * data structure, to achieve threadsafety we can use immutability. + * For our use case we just need reference equality, and the expectation is that a limited + * number of elements will be contained in this custom collection (<32). + * So the following structure is functionally equivalent to an Identity based ConcurrentMap, + * but heavily tuned for reads, at cost of structural reorganization at writes. + * The implementation is a binary tree basing the comparison order on the identityHashCode + * of each key. + * + * @author Sanne Grinovero + */ +public class ConcurrentServiceBinding { + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static final Node EMPTY_LEAF = new Node( new Entry( 0, null, null ), null, null ); + + @SuppressWarnings("unchecked") + private volatile Node treeRoot = EMPTY_LEAF; + + @SuppressWarnings("unchecked") + public synchronized void clear() { + treeRoot = EMPTY_LEAF; + } + + public synchronized void put(final K key, final V value) { + final int code = hashKey( key ); + final Entry newEntry = new Entry( code, key, value ); + final ArrayList> list = convertToArrayList( treeRoot, key ); + list.add( newEntry ); + Collections.sort( list ); + final int size = list.size(); + @SuppressWarnings("unchecked") + Entry[] array = list.toArray( new Entry[size] ); + treeRoot = treeFromRange( array, 0, size ); + } + + private Node treeFromRange(final Entry[] array, final int minInclusive, final int maxExclusive) { + if ( minInclusive == maxExclusive ) { + return null; + } + //find the midpoint, rounding down to avoid the exclusion range: + int mid = ( minInclusive + maxExclusive ) / 2; + //shift to the right to make sure we won't have left children with the same hash: + while ( mid > minInclusive && array[mid].hash == array[mid-1].hash ) { + mid--; + } + return new Node( array[mid], treeFromRange( array, minInclusive, mid ), treeFromRange( array, mid + 1, maxExclusive ) ); + } + + public V get(final K key) { + final int hash = hashKey( key ); + final Node root = treeRoot; + return root.get( key, hash ); + } + + protected int hashKey(final K key) { + return System.identityHashCode( key ); + } + + public Iterable values() { + @SuppressWarnings("rawtypes") + ArrayList list = new ArrayList(); + treeRoot.collectAllValuesInto( list ); + return list; + } + + private final ArrayList> convertToArrayList(final Node treeRoot, K exceptKey) { + @SuppressWarnings("rawtypes") + ArrayList> list = new ArrayList(); + if ( treeRoot != EMPTY_LEAF ) { + treeRoot.collectAllEntriesInto( list, exceptKey ); + } + return list; + } + + private static final class Entry implements Comparable> { + + private final int hash; + private final K key; + private final V value; + + Entry(int keyHashCode, K key, V value) { + this.hash = keyHashCode; + this.key = key; + this.value = value; + } + + @Override + public int compareTo(Entry o) { + //Sorting by the identity hashcode + //Note: this class has a natural ordering that is inconsistent with equals. + return ( hash < o.hash ) ? -1 : ( (hash == o.hash) ? 0 : 1 ); + } + + @Override + public boolean equals(Object obj) { + //A ClassCastException is really not expected here, + //as it's an internal private class, + //so just let it happen as a form of assertion. + final Entry other = (Entry)obj; + //Reference equality on the key only! + return other.key == this.key; + } + + @Override + public String toString() { + return "<" + key + ", " + value + ">"; + } + } + + private static final class Node { + + private final Entry entry; + private final Node left; + private final Node right; + + Node(Entry entry, Node left, Node right) { + this.entry = entry; + this.left = left; + this.right = right; + } + + public V get(final K key, final int hash) { + if ( entry.key == key ) { + return entry.value; + } + //Note that same-hashcode childs need to be on the right + //as we don't test for equality, nor want to chase both + //branches: + else if ( hash < this.entry.hash ) { + return left == null ? null : left.get( key, hash ); + } + else { + return right == null ? null : right.get( key, hash ); + } + } + + public void collectAllEntriesInto(final List> list, final K exceptKey) { + if ( entry != null && exceptKey != entry.key ) { + list.add( entry ); + } + if ( left != null ) { + left.collectAllEntriesInto( list, exceptKey ); + } + if ( right != null ) { + right.collectAllEntriesInto( list, exceptKey ); + } + } + + public void collectAllValuesInto(final List list) { + if ( entry != null && entry.value != null ) { + list.add( entry.value ); + } + if ( left != null ) { + left.collectAllValuesInto( list ); + } + if ( right != null ) { + right.collectAllValuesInto( list ); + } + } + + /** + * Helper to visualize the tree via toString + */ + private void renderToStringBuilder(final StringBuilder sb, final int indent) { + sb.append( entry ); + appendIndented( sb, indent, "L-> ", left ); + appendIndented( sb, indent, "R-> ", right ); + } + + private void appendIndented(final StringBuilder sb, final int indent, final String label, Node node) { + if ( node == null ) { + return; + } + sb.append( "\n" ); + for ( int i = 0; i < indent; i++ ) { + sb.append( "\t" ); + } + sb.append( label ); + node.renderToStringBuilder( sb, indent + 1 ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + renderToStringBuilder( sb, 0 ); + return sb.toString(); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java b/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java index 898ede4efcb9..52cd8e0a046c 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/JaxbProcessor.java @@ -50,11 +50,11 @@ import javax.xml.validation.SchemaFactory; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.jaxb.Origin; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.config.ConfigurationException; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.XsdException; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.source.spi.XsdException; +import org.hibernate.xml.spi.Origin; import org.jboss.logging.Logger; diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java index ab121329409b..8d1c00ebfa43 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java @@ -25,7 +25,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java index 2f0dd5ae043a..61e985b87eb6 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java @@ -25,7 +25,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; import org.hibernate.service.spi.ServiceBinding; import org.hibernate.service.spi.ServiceInitiator; diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/ServiceRegistryImplementor.java b/hibernate-core/src/main/java/org/hibernate/service/spi/ServiceRegistryImplementor.java index d2a5e5904681..56cb45b58e9b 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/ServiceRegistryImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/ServiceRegistryImplementor.java @@ -46,4 +46,16 @@ public interface ServiceRegistryImplementor extends ServiceRegistry { * Release resources */ public void destroy(); + + /** + * When a registry is created with a parent, the parent is notified of the child + * via this callback. + */ + public void registerChild(ServiceRegistryImplementor child); + + /** + * When a registry is created with a parent, the parent is notified of the child + * via this callback. + */ + public void deRegisterChild(ServiceRegistryImplementor child); } diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java index 9e169360aae2..e6b2d1a82caa 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceInitiator.java @@ -25,7 +25,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; /** diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java index dbf86a1ab48a..628cc8f1a17e 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java @@ -25,7 +25,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.Service; import org.hibernate.service.internal.SessionFactoryServiceRegistryImpl; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Template.java b/hibernate-core/src/main/java/org/hibernate/sql/Template.java index 0303dc6b9a31..baca2b2fee55 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Template.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Template.java @@ -58,6 +58,7 @@ public final class Template { KEYWORDS.add("or"); KEYWORDS.add("not"); KEYWORDS.add("like"); + KEYWORDS.add("escape"); KEYWORDS.add("is"); KEYWORDS.add("in"); KEYWORDS.add("between"); diff --git a/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java b/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java index 067d479a59ca..2d21e7bdd683 100644 --- a/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsInitiator.java @@ -29,7 +29,7 @@ import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceInitiator; import org.hibernate.stat.spi.StatisticsFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/DatabaseMetadata.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/DatabaseMetadata.java index 6ed2fa913cea..1e7a833d174d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/DatabaseMetadata.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/DatabaseMetadata.java @@ -39,12 +39,13 @@ import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; -import org.hibernate.exception.spi.SQLExceptionConverter; +import org.hibernate.exception.internal.SQLExceptionTypeDelegate; +import org.hibernate.exception.internal.SQLStateConversionDelegate; +import org.hibernate.exception.internal.StandardSQLExceptionConverter; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.mapping.Table; - import org.jboss.logging.Logger; /** @@ -61,7 +62,7 @@ public class DatabaseMetadata { private final boolean extras; private DatabaseMetaData meta; - private SQLExceptionConverter sqlExceptionConverter; + private SqlExceptionHelper sqlExceptionHelper; private final String[] types; /** @@ -86,7 +87,14 @@ public DatabaseMetadata(Connection connection, Dialect dialect, Configuration co public DatabaseMetadata(Connection connection, Dialect dialect, Configuration config, boolean extras) throws SQLException { - sqlExceptionConverter = dialect.buildSQLExceptionConverter(); + // TODO: Duplicates JdbcEnvironmentImpl#buildSqlExceptionHelper + final StandardSQLExceptionConverter sqlExceptionConverter = new StandardSQLExceptionConverter(); + sqlExceptionConverter.addDelegate( dialect.buildSQLExceptionConversionDelegate() ); + sqlExceptionConverter.addDelegate( new SQLExceptionTypeDelegate( dialect ) ); + // todo : vary this based on extractedMetaDataSupport.getSqlStateType() + sqlExceptionConverter.addDelegate( new SQLStateConversionDelegate( dialect ) ); + sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter ); + meta = connection.getMetaData(); this.extras = extras; initSequences( connection, dialect ); @@ -153,8 +161,7 @@ else if ( (isQuoted && meta.storesLowerCaseQuotedIdentifiers()) } } catch (SQLException sqlException) { - throw new SqlExceptionHelper( sqlExceptionConverter ) - .convert( sqlException, "could not get table metadata: " + name ); + throw sqlExceptionHelper.convert( sqlException, "could not get table metadata: " + name ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java index 3130430c3d3f..dd6335b1da86 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExport.java @@ -25,7 +25,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -37,16 +36,19 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Properties; import org.hibernate.HibernateException; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.dialect.Dialect; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.internal.FormatStyle; @@ -55,13 +57,13 @@ import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ConfigHelper; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.ServiceRegistry; - +import org.hibernate.tool.schema.spi.SchemaManagementTool; import org.jboss.logging.Logger; /** @@ -72,7 +74,10 @@ * @author Steve Ebersole */ public class SchemaExport { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SchemaExport.class.getName()); + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + SchemaExport.class.getName() + ); private static final String DEFAULT_IMPORT_FILE = "/import.sql"; public static enum Type { @@ -96,124 +101,174 @@ public boolean doDrop() { private final String[] dropSQL; private final String[] createSQL; private final String importFiles; + + private final ClassLoaderService classLoaderService; private final List exceptions = new ArrayList(); private Formatter formatter; private ImportSqlCommandExtractor importSqlCommandExtractor = ImportSqlCommandExtractorInitiator.DEFAULT_EXTRACTOR; - private String outputFile; + private String outputFile = null; private String delimiter; - private boolean haltOnError; - - public SchemaExport(ServiceRegistry serviceRegistry, Configuration configuration) { - this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( - serviceRegistry.getService( ConnectionProvider.class ) - ); - this.sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger(); - this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); - this.sqlExceptionHelper = serviceRegistry.getService( JdbcServices.class ).getSqlExceptionHelper(); - - this.importFiles = ConfigurationHelper.getString( - AvailableSettings.HBM2DDL_IMPORT_FILES, - configuration.getProperties(), - DEFAULT_IMPORT_FILE - ); - - final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); - this.dropSQL = configuration.generateDropSchemaScript( dialect ); - this.createSQL = configuration.generateSchemaCreationScript( dialect ); - } - - public SchemaExport(MetadataImplementor metadata) { + private boolean haltOnError = false; + +// public SchemaExport(ServiceRegistry serviceRegistry, Configuration configuration) { +// this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( +// serviceRegistry.getService( ConnectionProvider.class ) +// ); +// this.sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger(); +// this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); +// this.sqlExceptionHelper = serviceRegistry.getService( JdbcServices.class ).getSqlExceptionHelper(); +// +// this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); +// +// this.importFiles = ConfigurationHelper.getString( +// AvailableSettings.HBM2DDL_IMPORT_FILES, +// configuration.getProperties(), +// DEFAULT_IMPORT_FILE +// ); +// +// final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); +// this.dropSQL = configuration.generateDropSchemaScript( dialect ); +// this.createSQL = configuration.generateSchemaCreationScript( dialect ); +// } + + public SchemaExport(MetadataImplementor metadata, Connection connection){ ServiceRegistry serviceRegistry = metadata.getServiceRegistry(); - this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( - serviceRegistry.getService( ConnectionProvider.class ) - ); - JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); + if ( connection != null ) { + this.connectionHelper = new SuppliedConnectionHelper( connection ); + } + else { + this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( + serviceRegistry.getService( ConnectionProvider.class ) + ); + } + JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); this.sqlStatementLogger = jdbcServices.getSqlStatementLogger(); this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); this.sqlExceptionHelper = jdbcServices.getSqlExceptionHelper(); + + this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + + final Map settings = serviceRegistry.getService( ConfigurationService.class ).getSettings(); this.importFiles = ConfigurationHelper.getString( AvailableSettings.HBM2DDL_IMPORT_FILES, - serviceRegistry.getService( ConfigurationService.class ).getSettings(), + settings, DEFAULT_IMPORT_FILE ); - final Dialect dialect = jdbcServices.getDialect(); - this.dropSQL = metadata.getDatabase().generateDropSchemaScript( dialect ); - this.createSQL = metadata.getDatabase().generateSchemaCreationScript( dialect ); - } + // uses the schema management tool service to generate the create/drop scripts + // longer term this class should instead just leverage the tool for its execution phase... - /** - * Create a schema exporter for the given Configuration - * - * @param configuration The configuration from which to build a schema export. - * @throws HibernateException Indicates problem preparing for schema export. - */ - public SchemaExport(Configuration configuration) { - this( configuration, configuration.getProperties() ); - } + SchemaManagementTool schemaManagementTool = serviceRegistry.getService( SchemaManagementTool.class ); + final List commands = new ArrayList(); + final org.hibernate.tool.schema.spi.Target target = new org.hibernate.tool.schema.spi.Target() { + @Override + public boolean acceptsImportScriptActions() { + return false; + } - /** - * Create a schema exporter for the given Configuration, with the given - * database connection properties. - * - * @param configuration The configuration from which to build a schema export. - * @param properties The properties from which to configure connectivity etc. - * @throws HibernateException Indicates problem preparing for schema export. - * - * @deprecated properties may be specified via the Configuration object - */ - @Deprecated - public SchemaExport(Configuration configuration, Properties properties) throws HibernateException { - final Dialect dialect = Dialect.getDialect( properties ); + @Override + public void prepare() { + commands.clear(); + } - Properties props = new Properties(); - props.putAll( dialect.getDefaultProperties() ); - props.putAll( properties ); - this.connectionHelper = new ManagedProviderConnectionHelper( props ); + @Override + public void accept(String command) { + commands.add( command ); + } - this.sqlStatementLogger = new SqlStatementLogger( false, true ); - this.formatter = FormatStyle.DDL.getFormatter(); - this.sqlExceptionHelper = new SqlExceptionHelper(); + @Override + public void release() { + } + }; - this.importFiles = ConfigurationHelper.getString( - AvailableSettings.HBM2DDL_IMPORT_FILES, - properties, - DEFAULT_IMPORT_FILE - ); + schemaManagementTool.getSchemaDropper( settings ).doDrop( metadata.getDatabase(), false, target ); + this.dropSQL = commands.toArray( new String[ commands.size() ] ); - this.dropSQL = configuration.generateDropSchemaScript( dialect ); - this.createSQL = configuration.generateSchemaCreationScript( dialect ); + schemaManagementTool.getSchemaCreator( settings ).doCreation( metadata.getDatabase(), false, target ); + this.createSQL = commands.toArray( new String[commands.size()] ); } - - /** - * Create a schema exporter for the given Configuration, using the supplied connection for connectivity. - * - * @param configuration The configuration to use. - * @param connection The JDBC connection to use. - * @throws HibernateException Indicates problem preparing for schema export. - */ - public SchemaExport(Configuration configuration, Connection connection) throws HibernateException { - this.connectionHelper = new SuppliedConnectionHelper( connection ); - - this.sqlStatementLogger = new SqlStatementLogger( false, true ); - this.formatter = FormatStyle.DDL.getFormatter(); - this.sqlExceptionHelper = new SqlExceptionHelper(); - - this.importFiles = ConfigurationHelper.getString( - AvailableSettings.HBM2DDL_IMPORT_FILES, - configuration.getProperties(), - DEFAULT_IMPORT_FILE - ); - - final Dialect dialect = Dialect.getDialect( configuration.getProperties() ); - this.dropSQL = configuration.generateDropSchemaScript( dialect ); - this.createSQL = configuration.generateSchemaCreationScript( dialect ); + public SchemaExport(MetadataImplementor metadata) { + this(metadata, null); } +// /** +// * Create a schema exporter for the given Configuration +// * +// * @param configuration The configuration from which to build a schema export. +// * +// * @throws HibernateException Indicates problem preparing for schema export. +// */ +// public SchemaExport(Configuration configuration) { +// this( configuration, configuration.getProperties() ); +// } + +// /** +// * Create a schema exporter for the given Configuration, with the given +// * database connection properties. +// * +// * @param configuration The configuration from which to build a schema export. +// * @param properties The properties from which to configure connectivity etc. +// * +// * @throws HibernateException Indicates problem preparing for schema export. +// * @deprecated properties may be specified via the Configuration object +// */ +// @Deprecated +// public SchemaExport(Configuration configuration, Properties properties) throws HibernateException { +// final Dialect dialect = Dialect.getDialect( properties ); +// +// Properties props = new Properties(); +// props.putAll( dialect.getDefaultProperties() ); +// props.putAll( properties ); +// this.connectionHelper = new ManagedProviderConnectionHelper( props ); +// +// this.sqlStatementLogger = new SqlStatementLogger( false, true ); +// this.formatter = FormatStyle.DDL.getFormatter(); +// this.sqlExceptionHelper = new SqlExceptionHelper(); +// +// this.classLoaderService = new ClassLoaderServiceImpl(); +// +// this.importFiles = ConfigurationHelper.getString( +// AvailableSettings.HBM2DDL_IMPORT_FILES, +// properties, +// DEFAULT_IMPORT_FILE +// ); +// +// this.dropSQL = configuration.generateDropSchemaScript( dialect ); +// this.createSQL = configuration.generateSchemaCreationScript( dialect ); +// } + +// /** +// * Create a schema exporter for the given Configuration, using the supplied connection for connectivity. +// * +// * @param configuration The configuration to use. +// * @param connection The JDBC connection to use. +// * +// * @throws HibernateException Indicates problem preparing for schema export. +// */ +// public SchemaExport(Configuration configuration, Connection connection) throws HibernateException { +// this.connectionHelper = new SuppliedConnectionHelper( connection ); +// +// this.sqlStatementLogger = new SqlStatementLogger( false, true ); +// this.formatter = FormatStyle.DDL.getFormatter(); +// this.sqlExceptionHelper = new SqlExceptionHelper(); +// +// this.classLoaderService = new ClassLoaderServiceImpl(); +// +// this.importFiles = ConfigurationHelper.getString( +// AvailableSettings.HBM2DDL_IMPORT_FILES, +// configuration.getProperties(), +// DEFAULT_IMPORT_FILE +// ); +// +// final Dialect dialect = Dialect.getDialect( configuration.getProperties() ); +// this.dropSQL = configuration.generateDropSchemaScript( dialect ); +// this.createSQL = configuration.generateSchemaCreationScript( dialect ); +// } + public SchemaExport( ConnectionHelper connectionHelper, String[] dropSql, @@ -224,6 +279,7 @@ public SchemaExport( this.importFiles = ""; this.sqlStatementLogger = new SqlStatementLogger( false, true ); this.sqlExceptionHelper = new SqlExceptionHelper(); + this.classLoaderService = new ClassLoaderServiceImpl(); this.formatter = FormatStyle.DDL.getFormatter(); } @@ -231,6 +287,7 @@ public SchemaExport( * For generating a export script file, this is the file which will be written. * * @param filename The name of the file to which to write the export script. + * * @return this */ public SchemaExport setOutputFile(String filename) { @@ -242,6 +299,7 @@ public SchemaExport setOutputFile(String filename) { * Set the end of statement delimiter * * @param delimiter The delimiter + * * @return this */ public SchemaExport setDelimiter(String delimiter) { @@ -253,6 +311,7 @@ public SchemaExport setDelimiter(String delimiter) { * Should we format the sql strings? * * @param format Should we format SQL strings + * * @return this */ public SchemaExport setFormat(boolean format) { @@ -264,6 +323,7 @@ public SchemaExport setFormat(boolean format) { * Set import.sql command extractor. By default {@link SingleLineSqlCommandExtractor} is used. * * @param importSqlCommandExtractor import.sql command extractor. + * * @return this */ public SchemaExport setImportSqlCommandExtractor(ImportSqlCommandExtractor importSqlCommandExtractor) { @@ -275,6 +335,7 @@ public SchemaExport setImportSqlCommandExtractor(ImportSqlCommandExtractor impor * Should we stop once an error occurs? * * @param haltOnError True if export should stop after error. + * * @return this */ public SchemaExport setHaltOnError(boolean haltOnError) { @@ -343,14 +404,19 @@ public void execute(Target output, Type type) { LOG.runningHbm2ddlSchemaExport(); final List importFileReaders = new ArrayList(); - for ( String currentFile : importFiles.split(",") ) { + for ( String currentFile : importFiles.split( "," ) ) { try { final String resourceName = currentFile.trim(); - InputStream stream = ConfigHelper.getResourceAsStream( resourceName ); - importFileReaders.add( new NamedReader( resourceName, stream ) ); + InputStream stream = classLoaderService.locateResourceStream( resourceName ); + if ( stream != null ) { + importFileReaders.add( new NamedReader( resourceName, stream ) ); + } + else { + LOG.debugf( "Import file not found: %s", currentFile ); + } } catch ( HibernateException e ) { - LOG.debugf("Import file not found: %s", currentFile); + LOG.debugf( "Import file not found: %s", currentFile ); } } @@ -373,14 +439,14 @@ public void execute(Target output, Type type) { } if ( type.doCreate() ) { perform( createSQL, exporters ); - if ( ! importFileReaders.isEmpty() ) { + if ( !importFileReaders.isEmpty() ) { for ( NamedReader namedReader : importFileReaders ) { importScript( namedReader, exporters ); } } } } - catch (Exception e) { + catch ( Exception e ) { exceptions.add( e ); LOG.schemaExportUnsuccessful( e ); } @@ -390,7 +456,7 @@ public void execute(Target output, Type type) { try { exporter.release(); } - catch (Exception ignore) { + catch ( Exception ignore ) { } } @@ -399,17 +465,17 @@ public void execute(Target output, Type type) { try { namedReader.getReader().close(); } - catch (Exception ignore) { + catch ( Exception ignore ) { } } - LOG.schemaExportComplete(); + LOG.schemaExportComplete(); } } private void perform(String[] sqlCommands, List exporters) { for ( String sqlCommand : sqlCommands ) { String formatted = formatter.format( sqlCommand ); - if ( delimiter != null ) { + if ( delimiter != null ) { formatted += delimiter; } sqlStatementLogger.logStatement( sqlCommand, formatter ); @@ -417,7 +483,7 @@ private void perform(String[] sqlCommands, List exporters) { try { exporter.export( formatted ); } - catch (Exception e) { + catch ( Exception e ) { if ( haltOnError ) { throw new HibernateException( "Error during DDL export", e ); } @@ -432,11 +498,11 @@ private void perform(String[] sqlCommands, List exporters) { private void importScript(NamedReader namedReader, List exporters) throws Exception { BufferedReader reader = new BufferedReader( namedReader.getReader() ); String[] statements = importSqlCommandExtractor.extractCommands( reader ); - if (statements != null) { + if ( statements != null ) { for ( String statement : statements ) { if ( statement != null ) { String trimmedSql = statement.trim(); - if ( trimmedSql.endsWith( ";" )) { + if ( trimmedSql.endsWith( ";" ) ) { trimmedSql = trimmedSql.substring( 0, statement.length() - 1 ); } if ( !StringHelper.isEmpty( trimmedSql ) ) { @@ -448,7 +514,13 @@ private void importScript(NamedReader namedReader, List exporters) thr } } catch ( Exception e ) { - throw new ImportScriptException( "Error during statement execution (file: '" + namedReader.getName() + "'): " + trimmedSql, e ); + if (haltOnError) { + throw new ImportScriptException( "Error during statement execution (file: '" + + namedReader.getName() + "'): " + trimmedSql, e ); + } + exceptions.add(e); + LOG.unsuccessful(trimmedSql); + LOG.error(e.getMessage()); } } } @@ -479,9 +551,13 @@ private void execute(boolean script, boolean export, Writer fileOutput, Statemen final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper(); String formatted = formatter.format( sql ); - if (delimiter != null) formatted += delimiter; - if (script) System.out.println(formatted); - LOG.debug(formatted); + if ( delimiter != null ) { + formatted += delimiter; + } + if ( script ) { + System.out.println( formatted ); + } + LOG.debug( formatted ); if ( outputFile != null ) { fileOutput.write( formatted + "\n" ); } @@ -490,12 +566,12 @@ private void execute(boolean script, boolean export, Writer fileOutput, Statemen statement.executeUpdate( sql ); try { SQLWarning warnings = statement.getWarnings(); - if ( warnings != null) { + if ( warnings != null ) { sqlExceptionHelper.logAndClearWarnings( connectionHelper.getConnection() ); } } - catch( SQLException sqle ) { - LOG.unableToLogSqlWarnings(sqle); + catch ( SQLException sqle ) { + LOG.unableToLogSqlWarnings( sqle ); } } @@ -509,7 +585,13 @@ private static StandardServiceRegistryImpl createServiceRegistry(Properties prop public static void main(String[] args) { try { - Configuration cfg = new Configuration(); + final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + final ClassLoaderService classLoaderService = bsr.getService( ClassLoaderService.class ); + + final MetadataSources metadataSources = new MetadataSources( bsr ); + final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); + + NamingStrategy namingStrategy = null; boolean script = true; boolean drop = false; @@ -518,7 +600,6 @@ public static void main(String[] args) { boolean export = true; String outFile = null; String importFile = DEFAULT_IMPORT_FILE; - String propFile = null; boolean format = false; String delim = null; @@ -546,7 +627,7 @@ else if ( args[i].startsWith( "--import=" ) ) { importFile = args[i].substring( 9 ); } else if ( args[i].startsWith( "--properties=" ) ) { - propFile = args[i].substring( 13 ); + ssrBuilder.loadProperties( new File( args[i].substring( 13 ) ) ); } else if ( args[i].equals( "--format" ) ) { format = true; @@ -555,67 +636,71 @@ else if ( args[i].startsWith( "--delimiter=" ) ) { delim = args[i].substring( 12 ); } else if ( args[i].startsWith( "--config=" ) ) { - cfg.configure( args[i].substring( 9 ) ); + ssrBuilder.configure( args[i].substring( 9 ) ); } else if ( args[i].startsWith( "--naming=" ) ) { - cfg.setNamingStrategy( - ( NamingStrategy ) ReflectHelper.classForName( args[i].substring( 9 ) ) - .newInstance() - ); + namingStrategy = (NamingStrategy) classLoaderService.classForName( args[i].substring( 9 ) ).newInstance(); } } else { String filename = args[i]; if ( filename.endsWith( ".jar" ) ) { - cfg.addJar( new File( filename ) ); + metadataSources.addJar( new File( filename ) ); } else { - cfg.addFile( filename ); + metadataSources.addFile( filename ); } } - } - if ( propFile != null ) { - Properties props = new Properties(); - props.putAll( cfg.getProperties() ); - props.load( new FileInputStream( propFile ) ); - cfg.setProperties( props ); + if ( importFile != null ) { + ssrBuilder.applySetting( AvailableSettings.HBM2DDL_IMPORT_FILES, importFile ); } - if (importFile != null) { - cfg.setProperty( AvailableSettings.HBM2DDL_IMPORT_FILES, importFile ); + final StandardServiceRegistryImpl ssr = (StandardServiceRegistryImpl) ssrBuilder.build(); + final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( ssr ); + if ( namingStrategy != null ) { + metadataBuilder.with( namingStrategy ); } - StandardServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); + final MetadataImplementor metadata = (MetadataImplementor) metadataBuilder.build(); + try { - SchemaExport se = new SchemaExport( serviceRegistry, cfg ) + SchemaExport se = new SchemaExport( metadata ) .setHaltOnError( halt ) .setOutputFile( outFile ) .setDelimiter( delim ) - .setImportSqlCommandExtractor( serviceRegistry.getService( ImportSqlCommandExtractor.class ) ); + .setImportSqlCommandExtractor( ssr.getService( ImportSqlCommandExtractor.class ) ); if ( format ) { se.setFormat( true ); } se.execute( script, export, drop, create ); } finally { - serviceRegistry.destroy(); + ssr.destroy(); } } catch ( Exception e ) { - LOG.unableToCreateSchema(e); + LOG.unableToCreateSchema( e ); e.printStackTrace(); } } /** - * Returns a List of all Exceptions which occured during the export. + * Returns a List of all Exceptions which occurred during the export. * - * @return A List containig the Exceptions occured during the export + * @return A List containing the Exceptions occurred during the export */ public List getExceptions() { return exceptions; } + + public String[] getCreateSQL() { + return createSQL; + } + + public String[] getDropSQL() { + return dropSQL; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExportTask.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExportTask.java index 86e61bedebda..e216df2b6177 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExportTask.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaExportTask.java @@ -25,19 +25,22 @@ package org.hibernate.tool.hbm2ddl; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import org.hibernate.HibernateException; -import org.hibernate.cfg.Configuration; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; @@ -167,7 +170,7 @@ public void setOutput(File outputFile) { @Override public void execute() throws BuildException { try { - getSchemaExport( getConfiguration() ).execute(!quiet, !text, drop, create); + buildSchemaExport().execute( !quiet, !text, drop, create ); } catch (HibernateException e) { throw new BuildException("Schema text failed: " + e.getMessage(), e); @@ -183,66 +186,64 @@ public void execute() throws BuildException { } } - private String[] getFiles() { - - List files = new LinkedList(); - for ( Iterator i = fileSets.iterator(); i.hasNext(); ) { - - FileSet fs = (FileSet) i.next(); - DirectoryScanner ds = fs.getDirectoryScanner( getProject() ); - - String[] dsFiles = ds.getIncludedFiles(); - for (int j = 0; j < dsFiles.length; j++) { - File f = new File(dsFiles[j]); - if ( !f.isFile() ) { - f = new File( ds.getBasedir(), dsFiles[j] ); - } - - files.add( f.getAbsolutePath() ); - } - } + private SchemaExport buildSchemaExport() throws Exception { + final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); - return ArrayHelper.toStringArray(files); - } + final MetadataSources metadataSources = new MetadataSources( bsr ); + final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); - private Configuration getConfiguration() throws Exception { - Configuration cfg = new Configuration(); - if (namingStrategy!=null) { - cfg.setNamingStrategy( - (NamingStrategy) ReflectHelper.classForName(namingStrategy).newInstance() - ); + if ( configurationFile != null ) { + ssrBuilder.configure( configurationFile ); } - if (configurationFile != null) { - cfg.configure( configurationFile ); + if ( propertiesFile != null ) { + ssrBuilder.loadProperties( propertiesFile ); } + ssrBuilder.applySettings( getProject().getProperties() ); - String[] files = getFiles(); - for (int i = 0; i < files.length; i++) { - String filename = files[i]; - if ( filename.endsWith(".jar") ) { - cfg.addJar( new File(filename) ); + for ( String fileName : getFiles() ) { + if ( fileName.endsWith(".jar") ) { + metadataSources.addJar( new File( fileName ) ); } else { - cfg.addFile(filename); + metadataSources.addFile( fileName ); } } - return cfg; - } - private SchemaExport getSchemaExport(Configuration cfg) throws HibernateException, IOException { - Properties properties = new Properties(); - properties.putAll( cfg.getProperties() ); - if (propertiesFile == null) { - properties.putAll( getProject().getProperties() ); - } - else { - properties.load( new FileInputStream(propertiesFile) ); + + final StandardServiceRegistryImpl ssr = (StandardServiceRegistryImpl) ssrBuilder.build(); + final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( ssr ); + + if ( namingStrategy != null ) { + final ClassLoaderService classLoaderService = bsr.getService( ClassLoaderService.class ); + final NamingStrategy namingStrategyInstance = (NamingStrategy) classLoaderService.classForName( namingStrategy ).newInstance(); + metadataBuilder.with( namingStrategyInstance ); } - cfg.setProperties(properties); - return new SchemaExport(cfg) - .setHaltOnError(haltOnError) + + return new SchemaExport( (MetadataImplementor) metadataBuilder.build() ) + .setHaltOnError( haltOnError ) .setOutputFile( outputFile.getPath() ) - .setDelimiter(delimiter); + .setDelimiter( delimiter ); + + } + + private String[] getFiles() { + List fileNames = new LinkedList(); + for ( Object fileSet : fileSets ) { + FileSet fs = (FileSet) fileSet; + DirectoryScanner ds = fs.getDirectoryScanner( getProject() ); + + String[] dsFiles = ds.getIncludedFiles(); + for ( int j = 0; j < dsFiles.length; j++ ) { + File f = new File( dsFiles[j] ); + if ( !f.isFile() ) { + f = new File( ds.getBasedir(), dsFiles[j] ); + } + + fileNames.add( f.getAbsolutePath() ); + } + } + + return ArrayHelper.toStringArray( fileNames ); } public void setNamingStrategy(String namingStrategy) { diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdate.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdate.java deleted file mode 100644 index 08b0db2cf8d6..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdate.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.tool.hbm2ddl; - -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.Writer; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.hibernate.HibernateException; -import org.hibernate.JDBCException; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.jdbc.internal.FormatStyle; -import org.hibernate.engine.jdbc.internal.Formatter; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; -import org.hibernate.engine.jdbc.spi.SqlStatementLogger; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.service.ServiceRegistry; - -import org.jboss.logging.Logger; - -/** - * A commandline tool to update a database schema. May also be called from inside an application. - * - * @author Christoph Sturm - * @author Steve Ebersole - */ -public class SchemaUpdate { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SchemaUpdate.class.getName()); - - private final Configuration configuration; - private final ConnectionHelper connectionHelper; - private final SqlStatementLogger sqlStatementLogger; - private final SqlExceptionHelper sqlExceptionHelper; - private final Dialect dialect; - - private final List exceptions = new ArrayList(); - - private Formatter formatter; - - private boolean haltOnError; - private boolean format = true; - private String outputFile; - private String delimiter; - - public SchemaUpdate(Configuration cfg) throws HibernateException { - this( cfg, cfg.getProperties() ); - } - - public SchemaUpdate(Configuration configuration, Properties properties) throws HibernateException { - this.configuration = configuration; - this.dialect = Dialect.getDialect( properties ); - - Properties props = new Properties(); - props.putAll( dialect.getDefaultProperties() ); - props.putAll( properties ); - this.connectionHelper = new ManagedProviderConnectionHelper( props ); - - this.sqlExceptionHelper = new SqlExceptionHelper(); - this.sqlStatementLogger = new SqlStatementLogger( false, true ); - this.formatter = FormatStyle.DDL.getFormatter(); - } - - public SchemaUpdate(ServiceRegistry serviceRegistry, Configuration cfg) throws HibernateException { - this.configuration = cfg; - - final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); - this.dialect = jdbcServices.getDialect(); - this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( jdbcServices.getConnectionProvider() ); - - this.sqlExceptionHelper = new SqlExceptionHelper(); - this.sqlStatementLogger = jdbcServices.getSqlStatementLogger(); - this.formatter = ( sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); - } - - private static StandardServiceRegistryImpl createServiceRegistry(Properties properties) { - Environment.verifyProperties( properties ); - ConfigurationHelper.resolvePlaceHolders( properties ); - return (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().applySettings( properties ).build(); - } - - public static void main(String[] args) { - try { - Configuration cfg = new Configuration(); - - boolean script = true; - // If true then execute db updates, otherwise just generate and display updates - boolean doUpdate = true; - String propFile = null; - - for ( int i = 0; i < args.length; i++ ) { - if ( args[i].startsWith( "--" ) ) { - if ( args[i].equals( "--quiet" ) ) { - script = false; - } - else if ( args[i].startsWith( "--properties=" ) ) { - propFile = args[i].substring( 13 ); - } - else if ( args[i].startsWith( "--config=" ) ) { - cfg.configure( args[i].substring( 9 ) ); - } - else if ( args[i].startsWith( "--text" ) ) { - doUpdate = false; - } - else if ( args[i].startsWith( "--naming=" ) ) { - cfg.setNamingStrategy( - ( NamingStrategy ) ReflectHelper.classForName( args[i].substring( 9 ) ).newInstance() - ); - } - } - else { - cfg.addFile( args[i] ); - } - - } - - if ( propFile != null ) { - Properties props = new Properties(); - props.putAll( cfg.getProperties() ); - props.load( new FileInputStream( propFile ) ); - cfg.setProperties( props ); - } - - StandardServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); - try { - new SchemaUpdate( serviceRegistry, cfg ).execute( script, doUpdate ); - } - finally { - serviceRegistry.destroy(); - } - } - catch ( Exception e ) { - LOG.unableToRunSchemaUpdate(e); - e.printStackTrace(); - } - } - - /** - * Execute the schema updates - * - * @param script print all DDL to the console - */ - public void execute(boolean script, boolean doUpdate) { - execute( Target.interpret( script, doUpdate ) ); - } - - public void execute(Target target) { - LOG.runningHbm2ddlSchemaUpdate(); - - Connection connection = null; - Statement stmt = null; - Writer outputFileWriter = null; - - exceptions.clear(); - - try { - DatabaseMetadata meta; - try { - LOG.fetchingDatabaseMetadata(); - connectionHelper.prepare( true ); - connection = connectionHelper.getConnection(); - meta = new DatabaseMetadata( connection, dialect, configuration ); - stmt = connection.createStatement(); - } - catch ( SQLException sqle ) { - exceptions.add( sqle ); - LOG.unableToGetDatabaseMetadata(sqle); - throw sqle; - } - - LOG.updatingSchema(); - - if ( outputFile != null ) { - LOG.writingGeneratedSchemaToFile( outputFile ); - outputFileWriter = new FileWriter( outputFile ); - } - - List scripts = configuration.generateSchemaUpdateScriptList( dialect, meta ); - for ( SchemaUpdateScript script : scripts ) { - String formatted = formatter.format( script.getScript() ); - try { - if ( delimiter != null ) { - formatted += delimiter; - } - if ( target.doScript() ) { - System.out.println( formatted ); - } - if ( outputFile != null ) { - outputFileWriter.write( formatted + "\n" ); - } - if ( target.doExport() ) { - LOG.debug( script.getScript() ); - stmt.executeUpdate( formatted ); - } - } - catch ( SQLException e ) { - if (!script.isQuiet()) { - if ( haltOnError ) { - throw new JDBCException( "Error during DDL export", e ); - } - exceptions.add( e ); - LOG.unsuccessful(script.getScript()); - LOG.error(e.getMessage()); - } - } - } - - LOG.schemaUpdateComplete(); - - } - catch ( Exception e ) { - exceptions.add( e ); - LOG.unableToCompleteSchemaUpdate(e); - } - finally { - - try { - if ( stmt != null ) { - stmt.close(); - } - connectionHelper.release(); - } - catch ( Exception e ) { - exceptions.add( e ); - LOG.unableToCloseConnection(e); - } - try { - if( outputFileWriter != null ) { - outputFileWriter.close(); - } - } - catch(Exception e) { - exceptions.add(e); - LOG.unableToCloseConnection(e); - } - } - } - - /** - * Returns a List of all Exceptions which occured during the export. - * - * @return A List containig the Exceptions occured during the export - */ - public List getExceptions() { - return exceptions; - } - - public void setHaltOnError(boolean haltOnError) { - this.haltOnError = haltOnError; - } - - public void setFormat(boolean format) { - this.formatter = ( format ? FormatStyle.DDL : FormatStyle.NONE ).getFormatter(); - } - - public void setOutputFile(String outputFile) { - this.outputFile = outputFile; - } - - public void setDelimiter(String delimiter) { - this.delimiter = delimiter; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdateTask.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdateTask.java index 91789969a42f..4d79803d3d2b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdateTask.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaUpdateTask.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * Copyright (c) 2008, 2014, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -20,24 +20,38 @@ * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA - * */ package org.hibernate.tool.hbm2ddl; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import org.hibernate.HibernateException; -import org.hibernate.cfg.Configuration; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.DatabaseInformationBuilder; +import org.hibernate.tool.schema.spi.SchemaManagementTool; +import org.hibernate.tool.schema.spi.SchemaMigrator; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; @@ -62,7 +76,6 @@ * </schemaupdate> * * - * @see SchemaUpdate * @author Rong C Ou, Gavin King */ public class SchemaUpdateTask extends MatchingTask { @@ -129,8 +142,7 @@ public void execute() throws BuildException { try { log("Running Hibernate Core SchemaUpdate."); log("This is an Ant task supporting only mapping files, if you want to use annotations see http://tools.hibernate.org."); - Configuration cfg = getConfiguration(); - getSchemaUpdate(cfg).execute(!quiet, !text); + doIt(); } catch (HibernateException e) { throw new BuildException("Schema text failed: " + e.getMessage(), e); @@ -146,6 +158,116 @@ public void execute() throws BuildException { } } + private void doIt() throws Exception { + final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + + final MetadataSources metadataSources = new MetadataSources( bsr ); + final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); + + if ( configurationFile != null ) { + ssrBuilder.configure( configurationFile ); + } + if ( propertiesFile != null ) { + ssrBuilder.loadProperties( propertiesFile ); + } + ssrBuilder.applySettings( getProject().getProperties() ); + + for ( String fileName : getFiles() ) { + if ( fileName.endsWith(".jar") ) { + metadataSources.addJar( new File( fileName ) ); + } + else { + metadataSources.addFile( fileName ); + } + } + + final StandardServiceRegistryImpl ssr = (StandardServiceRegistryImpl) ssrBuilder.build(); + + final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( ssr ); + if ( namingStrategy != null ) { + final ClassLoaderService classLoaderService = bsr.getService( ClassLoaderService.class ); + final NamingStrategy namingStrategyInstance = (NamingStrategy) classLoaderService.classForName( namingStrategy ).newInstance(); + metadataBuilder.with( namingStrategyInstance ); + } + final MetadataImplementor metadata = (MetadataImplementor) metadataBuilder.build(); + + final JdbcEnvironment jdbcEnvironment = ssr.getService( JdbcEnvironment.class ); + final ConnectionProvider connectionProvider = ssr.getService( ConnectionProvider.class ); + final JdbcConnectionAccess connectionAccess = new ConnectionProviderJdbcConnectionAccess( connectionProvider ); + final DatabaseInformation existing = new DatabaseInformationBuilder( jdbcEnvironment, connectionAccess ).build(); + + final org.hibernate.tool.schema.spi.Target target = new org.hibernate.tool.schema.spi.Target() { + private Statement stmnt; + + @Override + public boolean acceptsImportScriptActions() { + return false; + } + + @Override + public void prepare() { + try { + stmnt = connectionAccess.obtainConnection().createStatement(); + } + catch (SQLException e) { + throw new HibernateException( "Could not build JDBC Statement", e ); + } + } + + @Override + public void accept(String action) { + try { + stmnt.execute( action ); + } + catch (SQLException e) { + throw new HibernateException( "Could not execute command via JDBC", e ); + } + } + + @Override + public void release() { + try { + stmnt.close(); + } + catch (SQLException e) { + throw new HibernateException( "Could not release JDBC Statement", e ); + } + } + }; + + final SchemaMigrator schemaMigrator = ssr.getService( SchemaManagementTool.class ).getSchemaMigrator( Collections.emptyMap() ); + schemaMigrator.doMigration( + metadata.getDatabase(), + existing, + true, + Collections.singletonList( target ) + ); + + } + + private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { + private final ConnectionProvider connectionProvider; + + public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + } + + @Override + public Connection obtainConnection() throws SQLException { + return connectionProvider.getConnection(); + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + connectionProvider.closeConnection( connection ); + } + + @Override + public boolean supportsAggressiveRelease() { + return connectionProvider.supportsAggressiveRelease(); + } + } + private String[] getFiles() { List files = new LinkedList(); @@ -168,47 +290,6 @@ private String[] getFiles() { return ArrayHelper.toStringArray( files ); } - private Configuration getConfiguration() throws Exception { - Configuration cfg = new Configuration(); - if (namingStrategy!=null) { - cfg.setNamingStrategy( - (NamingStrategy) ReflectHelper.classForName( namingStrategy ).newInstance() - ); - } - if (configurationFile!=null) { - cfg.configure( configurationFile ); - } - - String[] files = getFiles(); - for (int i = 0; i < files.length; i++) { - String filename = files[i]; - if ( filename.endsWith(".jar") ) { - cfg.addJar( new File(filename) ); - } - else { - cfg.addFile(filename); - } - } - return cfg; - } - - private SchemaUpdate getSchemaUpdate(Configuration cfg) throws HibernateException, IOException { - Properties properties = new Properties(); - properties.putAll( cfg.getProperties() ); - if (propertiesFile == null) { - properties.putAll( getProject().getProperties() ); - } - else { - properties.load( new FileInputStream(propertiesFile) ); - } - cfg.setProperties(properties); - SchemaUpdate su = new SchemaUpdate(cfg); - su.setOutputFile( outputFile.getPath() ); - su.setDelimiter(delimiter); - su.setHaltOnError(haltOnError); - return su; - } - public void setNamingStrategy(String namingStrategy) { this.namingStrategy = namingStrategy; } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidator.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidator.java deleted file mode 100755 index 186f8dff904d..000000000000 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidator.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.tool.hbm2ddl; - -import java.io.FileInputStream; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Properties; - -import org.hibernate.HibernateException; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.service.ServiceRegistry; - -import org.jboss.logging.Logger; - -/** - * A commandline tool to update a database schema. May also be called from - * inside an application. - * - * @author Christoph Sturm - */ -public class SchemaValidator { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SchemaValidator.class.getName()); - - private ConnectionHelper connectionHelper; - private Configuration configuration; - private Dialect dialect; - - public SchemaValidator(Configuration cfg) throws HibernateException { - this( cfg, cfg.getProperties() ); - } - - public SchemaValidator(Configuration cfg, Properties connectionProperties) throws HibernateException { - this.configuration = cfg; - dialect = Dialect.getDialect( connectionProperties ); - Properties props = new Properties(); - props.putAll( dialect.getDefaultProperties() ); - props.putAll( connectionProperties ); - connectionHelper = new ManagedProviderConnectionHelper( props ); - } - - public SchemaValidator(ServiceRegistry serviceRegistry, Configuration cfg ) throws HibernateException { - this.configuration = cfg; - final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); - this.dialect = jdbcServices.getDialect(); - this.connectionHelper = new SuppliedConnectionProviderConnectionHelper( jdbcServices.getConnectionProvider() ); - } - - private static StandardServiceRegistryImpl createServiceRegistry(Properties properties) { - Environment.verifyProperties( properties ); - ConfigurationHelper.resolvePlaceHolders( properties ); - return (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().applySettings( properties ).build(); - } - - public static void main(String[] args) { - try { - Configuration cfg = new Configuration(); - - String propFile = null; - - for ( int i = 0; i < args.length; i++ ) { - if ( args[i].startsWith( "--" ) ) { - if ( args[i].startsWith( "--properties=" ) ) { - propFile = args[i].substring( 13 ); - } - else if ( args[i].startsWith( "--config=" ) ) { - cfg.configure( args[i].substring( 9 ) ); - } - else if ( args[i].startsWith( "--naming=" ) ) { - cfg.setNamingStrategy( - ( NamingStrategy ) ReflectHelper.classForName( args[i].substring( 9 ) ).newInstance() - ); - } - } - else { - cfg.addFile( args[i] ); - } - - } - - if ( propFile != null ) { - Properties props = new Properties(); - props.putAll( cfg.getProperties() ); - props.load( new FileInputStream( propFile ) ); - cfg.setProperties( props ); - } - - StandardServiceRegistryImpl serviceRegistry = createServiceRegistry( cfg.getProperties() ); - try { - new SchemaValidator( serviceRegistry, cfg ).validate(); - } - finally { - serviceRegistry.destroy(); - } - } - catch ( Exception e ) { - LOG.unableToRunSchemaUpdate(e); - e.printStackTrace(); - } - } - - /** - * Perform the validations. - */ - public void validate() { - - LOG.runningSchemaValidator(); - - Connection connection = null; - - try { - - DatabaseMetadata meta; - try { - LOG.fetchingDatabaseMetadata(); - connectionHelper.prepare( false ); - connection = connectionHelper.getConnection(); - meta = new DatabaseMetadata( connection, dialect, configuration, false ); - } - catch ( SQLException sqle ) { - LOG.unableToGetDatabaseMetadata(sqle); - throw sqle; - } - - configuration.validateSchema( dialect, meta ); - - } - catch ( SQLException e ) { - LOG.unableToCompleteSchemaValidation(e); - } - finally { - - try { - connectionHelper.release(); - } - catch ( Exception e ) { - LOG.unableToCloseConnection(e); - } - - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidatorTask.java b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidatorTask.java index ede861ed216d..906c0e734195 100755 --- a/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidatorTask.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/hbm2ddl/SchemaValidatorTask.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * Copyright (c) 2008, 2014, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -20,24 +20,37 @@ * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA - * */ package org.hibernate.tool.hbm2ddl; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Properties; import org.hibernate.HibernateException; -import org.hibernate.cfg.Configuration; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.NamingStrategy; -import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.DatabaseInformationBuilder; +import org.hibernate.tool.schema.spi.SchemaManagementTool; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; @@ -61,7 +74,6 @@ * </schemaupdate> * * - * @see SchemaValidator * @author Gavin King */ public class SchemaValidatorTask extends MatchingTask { @@ -102,8 +114,7 @@ public void setConfig(File configurationFile) { @Override public void execute() throws BuildException { try { - Configuration cfg = getConfiguration(); - getSchemaValidator(cfg).validate(); + doIt(); } catch (HibernateException e) { throw new BuildException("Schema text failed: " + e.getMessage(), e); @@ -119,6 +130,112 @@ public void execute() throws BuildException { } } + private void doIt() throws Exception { + final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + + final MetadataSources metadataSources = new MetadataSources( bsr ); + final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); + + if ( configurationFile != null ) { + ssrBuilder.configure( configurationFile ); + } + if ( propertiesFile != null ) { + ssrBuilder.loadProperties( propertiesFile ); + } + ssrBuilder.applySettings( getProject().getProperties() ); + + for ( String fileName : getFiles() ) { + if ( fileName.endsWith(".jar") ) { + metadataSources.addJar( new File( fileName ) ); + } + else { + metadataSources.addFile( fileName ); + } + } + + final StandardServiceRegistryImpl ssr = (StandardServiceRegistryImpl) ssrBuilder.build(); + + final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( ssr ); + if ( namingStrategy != null ) { + final ClassLoaderService classLoaderService = bsr.getService( ClassLoaderService.class ); + final NamingStrategy namingStrategyInstance = (NamingStrategy) classLoaderService.classForName( namingStrategy ).newInstance(); + metadataBuilder.with( namingStrategyInstance ); + } + final MetadataImplementor metadata = (MetadataImplementor) metadataBuilder.build(); + + final JdbcEnvironment jdbcEnvironment = ssr.getService( JdbcEnvironment.class ); + final ConnectionProvider connectionProvider = ssr.getService( ConnectionProvider.class ); + final JdbcConnectionAccess connectionAccess = new ConnectionProviderJdbcConnectionAccess( connectionProvider ); + final DatabaseInformation existing = new DatabaseInformationBuilder( jdbcEnvironment, connectionAccess ).build(); + + final org.hibernate.tool.schema.spi.Target target = new org.hibernate.tool.schema.spi.Target() { + private Statement stmnt; + + @Override + public boolean acceptsImportScriptActions() { + return false; + } + + @Override + public void prepare() { + try { + stmnt = connectionAccess.obtainConnection().createStatement(); + } + catch (SQLException e) { + throw new HibernateException( "Could not build JDBC Statement", e ); + } + } + + @Override + public void accept(String action) { + try { + stmnt.execute( action ); + } + catch (SQLException e) { + throw new HibernateException( "Could not execute command via JDBC", e ); + } + } + + @Override + public void release() { + try { + stmnt.close(); + } + catch (SQLException e) { + throw new HibernateException( "Could not release JDBC Statement", e ); + } + } + }; + + final org.hibernate.tool.schema.spi.SchemaValidator validator = ssr.getService( SchemaManagementTool.class ) + .getSchemaValidator( Collections.emptyMap() ); + + validator.doValidation( metadata.getDatabase(), existing ); + } + + private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess { + private final ConnectionProvider connectionProvider; + + public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + } + + @Override + public Connection obtainConnection() throws SQLException { + return connectionProvider.getConnection(); + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + connectionProvider.closeConnection( connection ); + } + + @Override + public boolean supportsAggressiveRelease() { + return connectionProvider.supportsAggressiveRelease(); + } + } + private String[] getFiles() { List files = new LinkedList(); @@ -141,43 +258,6 @@ private String[] getFiles() { return ArrayHelper.toStringArray( files ); } - private Configuration getConfiguration() throws Exception { - Configuration cfg = new Configuration(); - if (namingStrategy!=null) { - cfg.setNamingStrategy( - (NamingStrategy) ReflectHelper.classForName(namingStrategy).newInstance() - ); - } - if (configurationFile!=null) { - cfg.configure( configurationFile ); - } - - String[] files = getFiles(); - for (int i = 0; i < files.length; i++) { - String filename = files[i]; - if ( filename.endsWith(".jar") ) { - cfg.addJar( new File(filename) ); - } - else { - cfg.addFile(filename); - } - } - return cfg; - } - - private SchemaValidator getSchemaValidator(Configuration cfg) throws HibernateException, IOException { - Properties properties = new Properties(); - properties.putAll( cfg.getProperties() ); - if (propertiesFile == null) { - properties.putAll( getProject().getProperties() ); - } - else { - properties.load( new FileInputStream(propertiesFile) ); - } - cfg.setProperties(properties); - return new SchemaValidator(cfg); - } - public void setNamingStrategy(String namingStrategy) { this.namingStrategy = namingStrategy; } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java new file mode 100644 index 000000000000..e4013a73f6ce --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ColumnInformationImpl.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * JDBC column metadata + * + * @author Christoph Sturm + * @author Steve Ebersole + */ +public class ColumnInformationImpl implements ColumnInformation { + private final TableInformation containingTableInformation; + private final Identifier columnIdentifier; + + private final int typeCode; + private final String typeName; + private final int columnSize; + private final int decimalDigits; + private final TruthValue nullable; + + public ColumnInformationImpl( + TableInformation containingTableInformation, + Identifier columnIdentifier, + int typeCode, + String typeName, + int columnSize, + int decimalDigits, + TruthValue nullable) { + this.containingTableInformation = containingTableInformation; + this.columnIdentifier = columnIdentifier; + this.typeCode = typeCode; + this.typeName = typeName; + this.columnSize = columnSize; + this.decimalDigits = decimalDigits; + this.nullable = nullable; + } + + @Override + public TableInformation getContainingTableInformation() { + return containingTableInformation; + } + + @Override + public Identifier getColumnIdentifier() { + return columnIdentifier; + } + + @Override + public int getTypeCode() { + return typeCode; + } + + @Override + public String getTypeName() { + return typeName; + } + + @Override + public int getColumnSize() { + return columnSize; + } + + @Override + public int getDecimalDigits() { + return decimalDigits; + } + + @Override + public TruthValue getNullable() { + return nullable; + } + + public String toString() { + return "ColumnInformation(" + columnIdentifier + ')'; + } + +} + + + + + + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java new file mode 100644 index 000000000000..b36c451260c7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationImpl.java @@ -0,0 +1,77 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * @author Steve Ebersole + */ +public class DatabaseInformationImpl implements DatabaseInformation, ExtractionContext.RegisteredObjectAccess { + private final Map tables = new HashMap(); + private final Map sequences = new HashMap(); + + public DatabaseInformationImpl() { + } + + // DatabaseInformation implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public TableInformation getTableInformation(ObjectName tableName) { + return locateRegisteredTableInformation( tableName ); + } + + @Override + public SequenceInformation getSequenceInformation(ObjectName sequenceName) { + return locateRegisteredSequenceInformation( sequenceName ); + } + + + // RegisteredObjectAccess implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public TableInformation locateRegisteredTableInformation(ObjectName tableName) { + return tables.get( tableName ); + } + + public void registerTableInformation(TableInformation tableInformation) { + tables.put( tableInformation.getName(), tableInformation ); + } + + @Override + public SequenceInformation locateRegisteredSequenceInformation(ObjectName sequenceName) { + return sequences.get( sequenceName ); + } + + public void registerSequenceInformation(SequenceInformation sequenceInformation) { + sequences.put( sequenceInformation.getSequenceName(), sequenceInformation ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java new file mode 100644 index 000000000000..a8f96851a9a0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ExtractionContextImpl.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; + +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; + +/** + * @author Steve Ebersole + */ +public class ExtractionContextImpl implements ExtractionContext { + private final JdbcEnvironment jdbcEnvironment; + private final JdbcConnectionAccess jdbcConnectionAccess; + private final RegisteredObjectAccess registeredTableAccess; + + private Connection jdbcConnection; + private DatabaseMetaData jdbcDatabaseMetaData; + + public ExtractionContextImpl( + JdbcEnvironment jdbcEnvironment, + JdbcConnectionAccess jdbcConnectionAccess, + RegisteredObjectAccess registeredTableAccess) { + this.jdbcEnvironment = jdbcEnvironment; + this.jdbcConnectionAccess = jdbcConnectionAccess; + this.registeredTableAccess = registeredTableAccess; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; + } + + @Override + public Connection getJdbcConnection() { + if ( jdbcConnection == null ) { + try { + jdbcConnection = jdbcConnectionAccess.obtainConnection(); + } + catch (SQLException e) { + throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to obtain JDBC Connection" ); + } + } + return jdbcConnection; + } + + @Override + public DatabaseMetaData getJdbcDatabaseMetaData() { + if ( jdbcDatabaseMetaData == null ) { + try { + jdbcDatabaseMetaData = getJdbcConnection().getMetaData(); + } + catch (SQLException e) { + throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to obtain JDBC DatabaseMetaData" ); + } + } + return jdbcDatabaseMetaData; + } + + @Override + public RegisteredObjectAccess getRegisteredObjectAccess() { + return registeredTableAccess; + } + + public void cleanup() { + if ( jdbcDatabaseMetaData != null ) { + jdbcDatabaseMetaData = null; + } + + if ( jdbcConnection != null ) { + try { + jdbcConnectionAccess.releaseConnection( jdbcConnection ); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java new file mode 100644 index 000000000000..a07d53a2b094 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/ForeignKeyInformationImpl.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; + +/** + * @author Steve Ebersole + */ +public class ForeignKeyInformationImpl implements ForeignKeyInformation { + private final Identifier fkIdentifier; + private final List columnMappingList; + + public ForeignKeyInformationImpl( + Identifier fkIdentifier, + List columnMappingList) { + this.fkIdentifier = fkIdentifier; + this.columnMappingList = columnMappingList; + } + + @Override + public Identifier getForeignKeyIdentifier() { + return fkIdentifier; + } + + @Override + public Iterable getColumnReferenceMappings() { + return columnMappingList; + } + + public static class ColumnReferenceMappingImpl implements ColumnReferenceMapping { + private final ColumnInformation referencing; + private final ColumnInformation referenced; + + public ColumnReferenceMappingImpl(ColumnInformation referencing, ColumnInformation referenced) { + this.referencing = referencing; + this.referenced = referenced; + } + + @Override + public ColumnInformation getReferencingColumnMetadata() { + return referencing; + } + + @Override + public ColumnInformation getReferencedColumnMetadata() { + return referenced; + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java new file mode 100644 index 000000000000..b995cd0c43d7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/IndexInformationImpl.java @@ -0,0 +1,83 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.IndexInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; + +/** + * @author Steve Ebersole + */ +public class IndexInformationImpl implements IndexInformation { + private final Identifier indexIdentifier; + private final List columnList; + + public IndexInformationImpl(Identifier indexIdentifier, List columnList) { + this.indexIdentifier = indexIdentifier; + this.columnList = columnList; + } + + @Override + public Identifier getIndexIdentifier() { + return indexIdentifier; + } + + @Override + public List getIndexedColumns() { + return columnList; + } + + public static Builder builder(Identifier indexIdentifier) { + return new Builder( indexIdentifier ); + } + + public static class Builder { + private final Identifier indexIdentifier; + private final List columnList = new ArrayList(); + + public Builder(Identifier indexIdentifier) { + this.indexIdentifier = indexIdentifier; + } + + public Builder addColumn(ColumnInformation columnInformation) { + columnList.add( columnInformation ); + return this; + } + + public IndexInformationImpl build() { + if ( columnList.isEmpty() ) { + throw new SchemaManagementException( + "Attempt to resolve JDBC metadata failed to find columns for index [" + indexIdentifier.getText() + "]" + ); + } + return new IndexInformationImpl( indexIdentifier, Collections.unmodifiableList( columnList ) ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java new file mode 100644 index 000000000000..8148cf9b94a2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/PrimaryKeyInformationImpl.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation; + +/** + * @author Steve Ebersole + */ +public class PrimaryKeyInformationImpl implements PrimaryKeyInformation { + private final Identifier identifier; + private final Iterable columns; + + public PrimaryKeyInformationImpl(Identifier identifier, Iterable columns) { + this.identifier = identifier; + this.columns = columns; + } + + @Override + public Identifier getPrimaryKeyIdentifier() { + return identifier; + } + + @Override + public Iterable getColumns() { + return columns; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java new file mode 100644 index 000000000000..254c12ffb70a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; + +/** + * For now we only collect sequence name. If all databases support it, would really like to see INCREMENT here as well. + * + * @author Steve Ebersole + */ +public class SequenceInformationImpl implements SequenceInformation { + private final ObjectName sequenceName; + private final int incrementSize; + + public SequenceInformationImpl(ObjectName sequenceName, int incrementSize) { + this.sequenceName = sequenceName; + this.incrementSize = incrementSize; + } + + @Override + public ObjectName getSequenceName() { + return sequenceName; + } + + @Override + public int getIncrementSize() { + return incrementSize; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java new file mode 100644 index 000000000000..2d9bb58aee2d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/StandardJdbcDatabaseMetaDataExtractor.java @@ -0,0 +1,429 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.hibernate.JDBCException; +import org.hibernate.TruthValue; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.internal.util.compare.EqualsHelper; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.IndexInformation; +import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation; +import org.hibernate.tool.schema.extract.spi.SchemaExtractionException; +import org.hibernate.tool.schema.extract.spi.SchemaMetaDataExtractor; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; + +/** + * Implementation of the SchemaMetaDataExtractor contract which uses the standard JDBC {@link java.sql.DatabaseMetaData} + * API for extraction. + * + * @author Steve Ebersole + */ +public class StandardJdbcDatabaseMetaDataExtractor implements SchemaMetaDataExtractor { + private final String[] tableTypes; + + private final ExtractionContext extractionContext; + + public StandardJdbcDatabaseMetaDataExtractor(ExtractionContext extractionContext) { + this.extractionContext = extractionContext; + + ConfigurationService configService = extractionContext.getJdbcEnvironment().getServiceRegistry() + .getService( ConfigurationService.class ); + if (ConfigurationHelper.getBoolean( AvailableSettings.ENABLE_SYNONYMS, configService.getSettings(), false ) ) { + tableTypes = new String[] { "TABLE", "VIEW", "SYNONYM" }; + } + else { + tableTypes = new String[] { "TABLE", "VIEW" }; + } + } + + protected IdentifierHelper identifierHelper() { + return extractionContext.getJdbcEnvironment().getIdentifierHelper(); + } + + protected JDBCException convertSQLException(SQLException sqlException, String message) { + return extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( sqlException, message ); + } + + @Override + public Iterable getTables(String catalogFilter, String schemaFilter) { + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables( + catalogFilter, + schemaFilter, + null, + tableTypes + ); + + final List results = new ArrayList(); + + try { + while ( resultSet.next() ) { + final Identifier catalogIdentifier = identifierHelper().fromMetaDataCatalogName( + resultSet.getString( + "TABLE_CAT" + ) + ); + final Identifier schemaIdentifier = identifierHelper().fromMetaDataSchemaName( + resultSet.getString( + "TABLE_SCHEM" + ) + ); + final Identifier tableIdentifier = identifierHelper().fromMetaDataObjectName( + resultSet.getString( + "TABLE_NAME" + ) + ); + final ObjectName tableName = new ObjectName( catalogIdentifier, schemaIdentifier, tableIdentifier ); + TableInformation tableInformation = new TableInformationImpl( + this, + tableName, + isPhysicalTableType( resultSet.getString( "TABLE_TYPE" ) ), + resultSet.getString( "REMARKS" ) + ); + results.add( tableInformation ); + } + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + + return results; + } + catch (SQLException sqlException) { + throw convertSQLException( sqlException, "Error accessing table metadata" ); + } + } + + protected boolean isPhysicalTableType(String tableType) { + return "TABLE".equalsIgnoreCase( tableType ); + } + + @Override + public Iterable getColumns(TableInformation tableInformation) { + final List results = new ArrayList(); + + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ), + "%" + ); + + try { + while ( resultSet.next() ) { + final String columnName = resultSet.getString( "COLUMN_NAME" ); + if ( columnName == null ) { + continue; + } + + results.add( + new ColumnInformationImpl( + tableInformation, + Identifier.toIdentifier( columnName ), + resultSet.getInt( "DATA_TYPE" ), + new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(), + resultSet.getInt( "COLUMN_SIZE" ), + resultSet.getInt("DECIMAL_DIGITS"), + interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) ) + ) + ); + } + } + finally { + resultSet.close(); + } + } + catch (SQLException e) { + throw convertSQLException( e, "Error accessing column metadata: " + tableInformation.getName().toString() ); + } + + return results; + } + + private TruthValue interpretTruthValue(String nullable) { + if ( "yes".equalsIgnoreCase( nullable ) ) { + return TruthValue.TRUE; + } + else if ( "no".equalsIgnoreCase( nullable ) ) { + return TruthValue.FALSE; + } + return TruthValue.UNKNOWN; + } + + @Override + public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation) { + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getPrimaryKeys( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ) + ); + + final List pkColumns = new ArrayList(); + boolean firstPass = true; + Identifier pkIdentifier = null; + + try { + while ( resultSet.next() ) { + final String currentPkName = resultSet.getString( "PK_NAME" ); + final Identifier currentPkIdentifier = currentPkName == null + ? null + : identifierHelper().fromMetaDataObjectName( currentPkName ); + if ( firstPass ) { + pkIdentifier = currentPkIdentifier; + firstPass = false; + } + else { + if ( !EqualsHelper.equals( pkIdentifier, currentPkIdentifier ) ) { + throw new SchemaExtractionException( + String.format( + "Encountered primary keys differing name on table %s", + tableInformation.getName().toText() + ) + ); + } + } + + final int columnPosition = resultSet.getInt( "KEY_SEQ" ); + final String columnName = resultSet.getString( "COLUMN_NAME" ); + + final Identifier columnIdentifier = identifierHelper().fromMetaDataObjectName( columnName ); + final ColumnInformation column = tableInformation.getColumn( columnIdentifier ); + pkColumns.add( columnPosition-1, column ); + } + } + finally { + resultSet.close(); + } + + if ( firstPass ) { + // we did not find any results (no pk) + return null; + } + else { + // validate column list is properly contiguous + for ( int i = 0; i < pkColumns.size(); i++ ) { + if ( pkColumns.get( i ) == null ) { + throw new SchemaExtractionException( "Primary Key information was missing for KEY_SEQ = " + ( i+1) ); + } + } + + // build the return + return new PrimaryKeyInformationImpl( pkIdentifier, pkColumns ); + } + } + catch (SQLException e) { + throw convertSQLException( e, "Error while reading primary key meta data for " + tableInformation.getName().toText() ); + } + } + + @Override + public Iterable getIndexes(TableInformation tableInformation) { + final Map builders = new HashMap(); + + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getIndexInfo( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ), + false, // DO NOT limit to just unique + true // DO require up-to-date results + ); + + try { + while ( resultSet.next() ) { + if ( resultSet.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic ) { + continue; + } + + final Identifier indexIdentifier = Identifier.toIdentifier( resultSet.getString( "INDEX_NAME" ) ); + IndexInformationImpl.Builder builder = builders.get( indexIdentifier ); + if ( builder == null ) { + builder = IndexInformationImpl.builder( indexIdentifier ); + builders.put( indexIdentifier, builder ); + } + + final Identifier columnIdentifier = Identifier.toIdentifier( resultSet.getString( "COLUMN_NAME" ) ); + final ColumnInformation columnInformation = tableInformation.getColumn( columnIdentifier ); + if ( columnInformation == null ) { + throw new SchemaManagementException( + "Could not locate column information using identifier [" + columnIdentifier.getText() + "]" + ); + } + builder.addColumn( columnInformation ); + } + } + finally { + resultSet.close(); + } + } + catch (SQLException e) { + throw convertSQLException( + e, + "Error accessing index information: " + tableInformation.getName().toString() + ); + } + + final List indexes = new ArrayList(); + for ( IndexInformationImpl.Builder builder : builders.values() ) { + IndexInformationImpl index = builder.build(); + indexes.add( index ); + } + return indexes; + } + + @Override + public Iterable getForeignKeys(TableInformation tableInformation) { + final Map fkBuilders = new HashMap(); + + try { + ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getImportedKeys( + identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ) + ); + + // todo : need to account for getCrossReference() as well... + + try { + while ( resultSet.next() ) { + // IMPL NOTE : The builder is mainly used to collect the column reference mappings + final Identifier fkIdentifier = Identifier.toIdentifier( resultSet.getString( "FK_NAME" ) ); + ForeignKeyBuilder fkBuilder = fkBuilders.get( fkIdentifier ); + if ( fkBuilder == null ) { + fkBuilder = generateForeignKeyBuilder( fkIdentifier ); + fkBuilders.put( fkIdentifier, fkBuilder ); + } + + final ObjectName incomingPkTableName = extractKeyTableName( resultSet, "PK" ); + + final TableInformation pkTableInformation = extractionContext.getRegisteredObjectAccess() + .locateRegisteredTableInformation( incomingPkTableName ); + + if ( pkTableInformation == null ) { + // the assumption here is that we have not seen this table already based on fully-qualified name + // during previous step of building all table metadata so most likely this is + // not a match based solely on schema/catalog and that another row in this result set + // should match. + continue; + } + + final Identifier fkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "FKCOLUMN_NAME" ) ); + final Identifier pkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "PKCOLUMN_NAME" ) ); + + fkBuilder.addColumnMapping( + tableInformation.getColumn( fkColumnIdentifier ), + pkTableInformation.getColumn( pkColumnIdentifier ) + ); + } + } + finally { + resultSet.close(); + } + } + catch (SQLException e) { + throw convertSQLException( + e, + "Error accessing column metadata: " + tableInformation.getName().toString() + ); + } + + final List fks = new ArrayList(); + for ( ForeignKeyBuilder fkBuilder : fkBuilders.values() ) { + ForeignKeyInformation fk = fkBuilder.build(); + fks.add( fk ); + } + return fks; + } + + private ForeignKeyBuilder generateForeignKeyBuilder(Identifier fkIdentifier) { + return new ForeignKeyBuilderImpl( fkIdentifier ); + } + + protected static interface ForeignKeyBuilder { + public ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced); + + public ForeignKeyInformation build(); + } + + protected static class ForeignKeyBuilderImpl implements ForeignKeyBuilder { + private final Identifier fkIdentifier; + private final List columnMappingList = new ArrayList(); + + public ForeignKeyBuilderImpl(Identifier fkIdentifier) { + this.fkIdentifier = fkIdentifier; + } + + @Override + public ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced) { + columnMappingList.add( new ForeignKeyInformationImpl.ColumnReferenceMappingImpl( referencing, referenced ) ); + return this; + } + + @Override + public ForeignKeyInformationImpl build() { + if ( columnMappingList.isEmpty() ) { + throw new SchemaManagementException( + "Attempt to resolve foreign key metadata from JDBC metadata failed to find " + + "column mappings for foreign key named [" + fkIdentifier.getText() + "]" + ); + } + return new ForeignKeyInformationImpl( fkIdentifier, columnMappingList ); + } + } + + private ObjectName extractKeyTableName(ResultSet resultSet, String prefix) throws SQLException { + final String incomingCatalogName = resultSet.getString( prefix + "TABLE_SCHEM" ); + final String incomingSchemaName = resultSet.getString( prefix + "TABLE_CATALOG" ); + final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" ); + + return new ObjectName( + Identifier.toIdentifier( incomingCatalogName ), Identifier.toIdentifier( incomingSchemaName ), + Identifier.toIdentifier( incomingTableName ) + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java new file mode 100644 index 000000000000..933f94c2edc8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java @@ -0,0 +1,163 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.IndexInformation; +import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation; +import org.hibernate.tool.schema.extract.spi.SchemaMetaDataExtractor; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * Provides access to information about existing schema objects (tables, sequences etc) of existing database. + * + * @author Christoph Sturm + * @author Max Rydahl Andersen + * @author Steve Ebersole + */ +public class TableInformationImpl implements TableInformation { + private final SchemaMetaDataExtractor metaDataExtractor; + private final ObjectName tableName; + private final boolean physicalTable; + private final String comment; + + private Map columns; + private PrimaryKeyInformation primaryKey; + private Map foreignKeys; + private Map indexes; + + private boolean wasPrimaryKeyLoaded = false; // to avoid multiple db reads since primary key can be null. + + public TableInformationImpl( + SchemaMetaDataExtractor metaDataExtractor, + ObjectName tableName, + boolean physicalTable, + String comment) { + this.metaDataExtractor = metaDataExtractor; + this.tableName = tableName; + this.physicalTable = physicalTable; + this.comment = comment; + } + + @Override + public ObjectName getName() { + return tableName; + } + + @Override + public boolean isPhysicalTable() { + return physicalTable; + } + + @Override + public String getComment() { + return comment; + } + + @Override + public Iterable getColumns() { + return columns().values(); + } + + protected Map columns() { + if ( this.columns == null ) { + final Map columnMap = new HashMap(); + final Iterable columnInformationItr = metaDataExtractor.getColumns( this ); + for ( ColumnInformation columnInformation : columnInformationItr ) { + columnMap.put( columnInformation.getColumnIdentifier(), columnInformation ); + } + this.columns = columnMap; + } + return this.columns; + } + + @Override + public ColumnInformation getColumn(Identifier columnIdentifier) { + return columns().get( columnIdentifier ); + } + + @Override + public PrimaryKeyInformation getPrimaryKey() { + if ( ! wasPrimaryKeyLoaded ) { + primaryKey = metaDataExtractor.getPrimaryKey( this ); + wasPrimaryKeyLoaded = true; + } + return primaryKey; + } + + @Override + public Iterable getForeignKeys() { + return foreignKeys().values(); + } + + protected Map foreignKeys() { + if ( foreignKeys == null ) { + final Map fkMap = new HashMap(); + final Iterable fks = metaDataExtractor.getForeignKeys( this ); + for ( ForeignKeyInformation fk : fks ) { + fkMap.put( fk.getForeignKeyIdentifier(), fk ); + } + this.foreignKeys = fkMap; + } + return foreignKeys; + } + + @Override + public ForeignKeyInformation getForeignKey(Identifier fkIdentifier) { + return foreignKeys().get( fkIdentifier ); + } + + @Override + public Iterable getIndexes() { + return indexes().values(); + } + + protected Map indexes() { + if ( indexes == null ) { + final Map indexMap = new HashMap(); + final Iterable indexes = metaDataExtractor.getIndexes( this ); + for ( IndexInformation index : indexes ) { + indexMap.put( index.getIndexIdentifier(), index ); + } + this.indexes = indexMap; + } + return indexes; + } + + @Override + public IndexInformation getIndex(Identifier indexName) { + return indexes().get( indexName ); + } + + @Override + public String toString() { + return "TableInformationImpl(" + tableName.toString() + ')'; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java new file mode 100644 index 000000000000..2a6d5b3ed0f1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TemporarySequenceInformationExtractor.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; + +/** + * Temporary implementation that works for H2. + * + * @author Steve Ebersole + */ +public class TemporarySequenceInformationExtractor implements SequenceInformationExtractor { + @Override + public Iterable extractMetadata(ExtractionContext extractionContext) throws SQLException { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + final Statement statement = extractionContext.getJdbcConnection().createStatement(); + try { + ResultSet resultSet = statement.executeQuery( + "select SEQUENCE_CATALOG, SEQUENCE_SCHEMA, SEQUENCE_NAME, INCREMENT " + + "from information_schema.sequences" + ); + try { + final List sequenceInformationList = new ArrayList(); + while ( resultSet.next() ) { + sequenceInformationList.add( + new SequenceInformationImpl( + new ObjectName( + identifierHelper.fromMetaDataCatalogName( + resultSet.getString( "SEQUENCE_CATALOG" ) + ), + identifierHelper.fromMetaDataSchemaName( + resultSet.getString( "SEQUENCE_SCHEMA" ) + ), + identifierHelper.fromMetaDataCatalogName( + resultSet.getString( "SEQUENCE_NAME" ) + ) + ), + resultSet.getInt( "INCREMENT" ) + ) + ); + } + return sequenceInformationList; + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + } + finally { + try { + statement.close(); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/package-info.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/package-info.java new file mode 100644 index 000000000000..cb7d093f2353 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/package-info.java @@ -0,0 +1,28 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract; + +/** + * Defines a model of schema information extracted from the database through JDBC. + */ diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java new file mode 100644 index 000000000000..a2cf37da0f7c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ColumnInformation.java @@ -0,0 +1,92 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.TruthValue; +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Provides access to information about existing table columns + * + * @author Christoph Sturm + * @author Steve Ebersole + */ +public interface ColumnInformation { + /** + * Access to the containing table. + * + * @return The containing table information + */ + public TableInformation getContainingTableInformation(); + + /** + * The simple (not qualified) column name. + * + * @return The column simple identifier. + */ + public Identifier getColumnIdentifier(); + + /** + * Is the column nullable. The database is allowed to report unknown, hence the use of TruthValue + * + * @return nullability. + */ + public TruthValue getNullable(); + + /** + * The JDBC type-code. + * + * @return JDBC type-code + */ + public int getTypeCode(); + + /** + * The database specific type name. + * + * @return Type name + */ + public String getTypeName(); + + // todo : wrap these in org.hibernate.metamodel.spi.relational.Size ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /** + * The column size (length). + * + * @return The column length + */ + public int getColumnSize(); + + /** + * The precision, for numeric types + * + * @return The numeric precision + */ + public int getDecimalDigits(); +} + + + + + + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java new file mode 100644 index 000000000000..0691964e551e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformation.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Provides access to information about existing schema objects (tables, sequences etc) of existing database. + * + * @author Christoph Sturm + * @author Teodor Danciu + * @author Steve Ebersole + */ +public interface DatabaseInformation { + /** + * Obtain reference to the named TableInformation + * + * @param tableName The qualified table name + * + * @return The table information. May return {@code null} if not found. + */ + public TableInformation getTableInformation(ObjectName tableName); + + /** + * Obtain reference to the named SequenceInformation + * + * @param sequenceName The qualified sequence name + * + * @return The sequence information. May return {@code null} if not found. + */ + public SequenceInformation getSequenceInformation(ObjectName sequenceName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java new file mode 100644 index 000000000000..c89f85f6f995 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/DatabaseInformationBuilder.java @@ -0,0 +1,148 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.hibernate.dialect.H2Dialect; +import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl; +import org.hibernate.tool.schema.extract.internal.ExtractionContextImpl; +import org.hibernate.tool.schema.extract.internal.StandardJdbcDatabaseMetaDataExtractor; +import org.hibernate.tool.schema.extract.internal.TemporarySequenceInformationExtractor; + +/** + * Acts as the entry point into building {@link DatabaseInformation} instances. The correlation is 1-to-1 between + * DatabaseInformationBuilder and DatabaseInformation, meaning a given DatabaseInformationBuilder should only be used + * to build a single DatabaseInformation instance. + * + * @author Steve Ebersole + */ +public class DatabaseInformationBuilder { + private final DatabaseInformationImpl databaseInformation; + private final ExtractionContext extractionContext; + + private final SchemaMetaDataExtractor metaDataExtractor; + + public DatabaseInformationBuilder(JdbcEnvironment jdbcEnvironment, final Connection jdbcConnection) { + this( + jdbcEnvironment, + new JdbcConnectionAccess() { + @Override + public Connection obtainConnection() throws SQLException { + return jdbcConnection; + } + + @Override + public void releaseConnection(Connection connection) throws SQLException { + // nothing to do, we don't "own" the connection + } + + @Override + public boolean supportsAggressiveRelease() { + return false; + } + } + ); + } + + public DatabaseInformationBuilder(JdbcEnvironment jdbcEnvironment, JdbcConnectionAccess jdbcConnectionAccess) { + this.databaseInformation = new DatabaseInformationImpl(); + this.extractionContext = new ExtractionContextImpl( jdbcEnvironment, jdbcConnectionAccess, databaseInformation ); + + // todo : make this pluggable... + metaDataExtractor = new StandardJdbcDatabaseMetaDataExtractor( extractionContext ); + } + + public DatabaseInformationBuilder prepareAll() { + return prepare( SchemaMetaDataExtractor.ALL_CATALOGS_FILTER, SchemaMetaDataExtractor.ALL_SCHEMAS_FILTER ); + } + + public DatabaseInformationBuilder prepareCatalogAndSchema(Schema.Name schemaName) { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + return prepare( + identifierHelper.toMetaDataCatalogName( schemaName.getCatalog() ), + identifierHelper.toMetaDataSchemaName( schemaName.getSchema() ) + ); + } + + public DatabaseInformationBuilder prepareCatalog(Identifier catalog) { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + return prepare( + identifierHelper.toMetaDataCatalogName( catalog ), + SchemaMetaDataExtractor.ALL_SCHEMAS_FILTER + ); + } + + public DatabaseInformationBuilder prepareSchema(Identifier schema) { + final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); + return prepare( + SchemaMetaDataExtractor.ALL_CATALOGS_FILTER, + identifierHelper.toMetaDataSchemaName( schema ) + ); + } + + private DatabaseInformationBuilder prepare(String catalog, String schema) { + // todo : apply filtering + + for ( TableInformation tableInformation : metaDataExtractor.getTables( catalog, schema ) ) { + databaseInformation.registerTableInformation( tableInformation ); + } + + final Iterable sequences = extractSequences(); + if ( sequences != null ) { + for ( SequenceInformation sequenceInformation : sequences ) { + databaseInformation.registerSequenceInformation( sequenceInformation ); + } + } + + return this; + } + + private Iterable extractSequences() { + if (!extractionContext.getJdbcEnvironment().getDialect().getClass().isAssignableFrom( H2Dialect.class )) { + // TODO: the temporary impl below is for H2 only + return null; + } + + // todo : temporary impl!!! + final TemporarySequenceInformationExtractor seqExtractor = new TemporarySequenceInformationExtractor(); + try { + return seqExtractor.extractMetadata( extractionContext ); + } + catch (SQLException e) { + throw extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( e, "Unable to access sequence information" ); + } + } + + public DatabaseInformation build() { + return databaseInformation; + } +} + diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java new file mode 100644 index 000000000000..0e437b7d9375 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Defines a context for performing extraction including providing access to information about ongoing extraction as + * well as to delegates needed in performing extraction. + * + * @author Steve Ebersole + */ +public interface ExtractionContext { + public JdbcEnvironment getJdbcEnvironment(); + public Connection getJdbcConnection(); + public DatabaseMetaData getJdbcDatabaseMetaData(); + + public static interface RegisteredObjectAccess { + public TableInformation locateRegisteredTableInformation(ObjectName tableName); + public SequenceInformation locateRegisteredSequenceInformation(ObjectName sequenceName); + } + + public RegisteredObjectAccess getRegisteredObjectAccess(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java new file mode 100644 index 000000000000..92e076e00438 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ForeignKeyInformation.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * @author Steve Ebersole + */ +public interface ForeignKeyInformation { + /** + * Obtain the identifier for this FK. + * + * @return The FK identifier. + */ + public Identifier getForeignKeyIdentifier(); + + /** + * Get the column mappings that define the reference. Returned in sequential order. + * + * @return The sequential column reference mappings. + */ + public Iterable getColumnReferenceMappings(); + + public static interface ColumnReferenceMapping { + /** + * Obtain the information about the referencing column (the source column, which points to + * the referenced column). + * + * @return The referencing column. + */ + public ColumnInformation getReferencingColumnMetadata(); + + /** + * Obtain the information about the referenced column (the target side). + * + * @return The referenced column + */ + public ColumnInformation getReferencedColumnMetadata(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java new file mode 100644 index 000000000000..c804047daf8b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/IndexInformation.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Provides access to information about existing index in the database + * + * @author Christoph Sturm + * @author Steve Ebersole + */ +public interface IndexInformation { + /** + * Obtain the identifier for this index. + * + * @return The index identifier. + */ + public Identifier getIndexIdentifier(); + + /** + * Obtain the columns indexed under this index. Returned in sequential order. + * + * @return The columns + */ + public List getIndexedColumns(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java new file mode 100644 index 000000000000..e7b7ceaa944e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/PrimaryKeyInformation.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; + +/** + * Provides access to information about existing primary key for a table + * + * @author Steve Ebersole + */ +public interface PrimaryKeyInformation { + /** + * Obtain the identifier for this PK. + * + * @return The PK identifier. + */ + public Identifier getPrimaryKeyIdentifier(); + + /** + * Obtain the columns making up the primary key. Returned in sequential order. + * + * @return The columns + */ + public Iterable getColumns(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java new file mode 100644 index 000000000000..20ffba88e0d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaExtractionException.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.HibernateException; + +/** + * @author Steve Ebersole + */ +public class SchemaExtractionException extends HibernateException { + public SchemaExtractionException(String message) { + super( message ); + } + + public SchemaExtractionException(String message, Throwable root) { + super( message, root ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java new file mode 100644 index 000000000000..1f0da1969510 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SchemaMetaDataExtractor.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.tool.schema.extract.internal.TableInformationImpl; + +/** + * Contract for extracting information about objects in the database schema(s). To an extent, the contract largely + * mirrors parts of the JDBC {@link java.sql.DatabaseMetaData} contract. THe intention is to insulate callers + * from {@link java.sql.DatabaseMetaData} since on many databases there are better ways to get information from + * the meta schema. + * + * NOTE : Concepts here taken largely from the {@code MetaDataDialect} class Hibernate Tools. + * + * @author Steve Ebersole + */ +public interface SchemaMetaDataExtractor { + public static final String ALL_CATALOGS_FILTER = null; + public static final String SANS_CATALOG_FILTER = ""; + + public static final String ALL_SCHEMAS_FILTER = null; + public static final String SANS_SCHEMA_FILTER = ""; + + /** + * Return information about all matching tables + * + * @param catalogFilter Filter to be applied for the catalog to which tables belong. Can be either the + * name of the catalog to match or one of 2 special values:

      + *
    1. + * {@code null} ({@link #ALL_CATALOGS_FILTER}) - Indicates that tables from all catalogs should be returned + *
    2. + *
    3. + * {@code ""} (empty String) ({@link #SANS_CATALOG_FILTER}) - Indicates that only tables without a catalog + * should be returned + *
    4. + *
    + * @param schemaFilter Filter to be applied for the schema to which tables belong. Can be either the + * name of the schema to match or one of 2 special values:
      + *
    1. + * {@code null} ({@link #ALL_SCHEMAS_FILTER}) - Indicates that tables from all schemas should be returned + *
    2. + *
    3. + * {@code ""} (empty String) ({@link #SANS_SCHEMA_FILTER}) - Indicates that only tables without a schema + * should be returned + *
    4. + *
    + * + * @return iterator with map elements that has "TABLE_NAME", "TABLE_SCHEMA", "TABLE_CAT", "TABLE_TYPE" keys. + */ + public Iterable getTables(String catalogFilter, String schemaFilter); + + /** + * Return information about columns for the given table. Typically called from the TableInformation itself + * as part of on-demand initialization of its state. + * + * @param tableInformation The table for which to locate columns + * + * @return The extracted column information + */ + public Iterable getColumns(TableInformation tableInformation); + + /** + * Extract information about the given table's primary key. + * + * @param tableInformation The table for which to locate primary key information, + * + * @return The extracted primary key information + */ + public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation); + + /** + * Extract information about indexes defined against the given table. Typically called from the TableInformation + * itself as part of on-demand initialization of its state. + * + * @param tableInformation The table for which to locate indexes + * + * @return The extracted index information + */ + public Iterable getIndexes(TableInformation tableInformation); + + /** + * Extract information about foreign keys defined on the given table (targeting or point-at other tables). + * Typically called from the TableInformation itself as part of on-demand initialization of its state. + * + * @param tableInformation The table for which to locate foreign-keys + * + * @return The extracted foreign-key information + */ + public Iterable getForeignKeys(TableInformation tableInformation); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java new file mode 100644 index 000000000000..56b329aa45dc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Access to information about existing sequences. + * + * @author Steve Ebersole + */ +public interface SequenceInformation { + /** + * The qualified sequence name. + * + * @return The sequence name + */ + public ObjectName getSequenceName(); + + /** + * Retrieve the extracted increment-size defined for the sequence. + * + * @return The extracted increment size; use a negative number to indicate the increment could not be extracted. + */ + public int getIncrementSize(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java new file mode 100644 index 000000000000..f63edd124311 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformationExtractor.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import java.sql.SQLException; + +/** + * Because JDBC (at least up to an including Java 7, JDBC 4) still does not have support for obtaining information + * about sequences from DatabaseMetaData. + * + * @author Steve Ebersole + */ +public interface SequenceInformationExtractor { + /** + * Get the information about sequences. + * + * @param extractionContext Access to resources needed to perform the extraction + * + * @return The extracted information about existing sequences. + * + * @throws SQLException Don't bother handling SQLExceptions (unless you want to), we will deal with them in the + * caller. + */ + public Iterable extractMetadata(ExtractionContext extractionContext) throws SQLException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java new file mode 100644 index 000000000000..3146abc67b80 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/TableInformation.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.extract.spi; + +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.ObjectName; + +/** + * Provides access to information about existing tables in the database + * + * @author Christoph Sturm + * @author Max Rydahl Andersen + * @author Steve Ebersole + */ +public interface TableInformation { + /** + * Get the qualified name of the table. + * + * @return The qualified table name + */ + public ObjectName getName(); + + /** + * Does this information describe a physical table as opposed to a view, etc? + * + * @return {@code true} if this is a physical table; {@code false} otherwise. + */ + public boolean isPhysicalTable(); + + /** + * Get the comments/remarks defined for the table. + * + * @return The table comments + */ + public String getComment(); + + /** + * Get an iterable over all of the table's columns. + * + * @return All of the table's columns + */ + public Iterable getColumns(); + + /** + * Retrieve the named ColumnInformation + * + * @param columnIdentifier The column identifier (simple name) + * + * @return The matching column information. May return {@code null} + */ + public ColumnInformation getColumn(Identifier columnIdentifier); + + /** + * Retrieve information about the table's primary key, if one is defined (aka, may return {@code null}). + * + * @return The primary key information, or {@code null} if the table did not define a primary key. + */ + public PrimaryKeyInformation getPrimaryKey(); + + /** + * Obtain an iterable over all the table's defined foreign keys. + * + * @return The iterable. + */ + public Iterable getForeignKeys(); + + /** + * Retrieve the named ForeignKeyInformation + * + * @param keyName The foreign key identifier (simple name) + * + * @return The matching foreign key information. May return {@code null} + */ + public ForeignKeyInformation getForeignKey(Identifier keyName); + + /** + * Obtain an iterable over all the table's defined indexes. + * + * @return The iterable. + */ + public Iterable getIndexes(); + + /** + * Obtain an iterable over all the table's defined indexes + */ + public IndexInformation getIndex(Identifier indexName); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java new file mode 100644 index 000000000000..fef39ec96c39 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.Map; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.spi.ServiceRegistryAwareService; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.tool.schema.spi.SchemaCreator; +import org.hibernate.tool.schema.spi.SchemaDropper; +import org.hibernate.tool.schema.spi.SchemaManagementTool; +import org.hibernate.tool.schema.spi.SchemaMigrator; +import org.hibernate.tool.schema.spi.SchemaValidator; + +/** + * The standard Hibernate implementation for performing schema management. + * + * @author Steve Ebersole + */ +public class HibernateSchemaManagementTool implements SchemaManagementTool, ServiceRegistryAwareService { + + private ServiceRegistry serviceRegistry; + + @Override + public SchemaCreator getSchemaCreator(Map options) { + return new SchemaCreatorImpl(); + } + + @Override + public SchemaDropper getSchemaDropper(Map options) { + return new SchemaDropperImpl(); + } + + @Override + public SchemaMigrator getSchemaMigrator(Map options) { + return new SchemaMigratorImpl(); + } + + @Override + public SchemaValidator getSchemaValidator(Map options) { + final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect(); + return new SchemaValidatorImpl(dialect); + } + + @Override + public void injectServices(ServiceRegistryImplementor serviceRegistry) { + this.serviceRegistry = serviceRegistry; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java new file mode 100644 index 000000000000..cd6ad33482af --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java @@ -0,0 +1,164 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Exportable; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.InitCommand; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.SchemaCreator; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.Target; + +/** + * This is functionally nothing more than the creation script from the older SchemaExport class (plus some + * additional stuff in the script). + * + * @author Steve Ebersole + */ +public class SchemaCreatorImpl implements SchemaCreator { + + @Override + public void doCreation(Database database, boolean createSchemas, List targets) throws SchemaManagementException { + doCreation( database, createSchemas, targets.toArray( new Target[ targets.size() ] ) ); + } + + @Override + public void doCreation(Database database, boolean createSchemas, Target... targets) + throws SchemaManagementException { + final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment(); + final Dialect dialect = jdbcEnvironment.getDialect(); + + for ( Target target : targets ) { + target.prepare(); + } + + final Set exportIdentifiers = new HashSet( 50 ); + + // first, create each schema + for ( Schema schema : database.getSchemas() ) { + if ( createSchemas ) { + applySqlStrings( targets, dialect.getCreateSchemaCommand( schema.getName().getSchema().getText( dialect ) ) ); + } + } + + // next, create all "before table" auxiliary objects + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlCreateStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); + } + } + + // then, create all schema objects: tables, sequences, constraints, etc + for ( Schema schema : database.getSchemas() ) { + for ( Sequence sequence : schema.getSequences() ) { + checkExportIdentifier( sequence, exportIdentifiers ); + applySqlStrings( targets, dialect.getSequenceExporter().getSqlCreateStrings( sequence, jdbcEnvironment ) ); + } + + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + checkExportIdentifier( table, exportIdentifiers ); + applySqlStrings( targets, dialect.getTableExporter().getSqlCreateStrings( table, jdbcEnvironment ) ); + + } + + for ( Table table : schema.getTables() ) { + for ( ForeignKey foreignKey : table.getForeignKeys() ) { + // only add the foreign key if its source and target are both physical tables + // and if the target table does not have any denormalized tables. + if ( Table.class.isInstance( foreignKey.getTable() ) && + Table.class.isInstance( foreignKey.getTargetTable() ) ) { + Table sourceTable = Table.class.cast( foreignKey.getTable() ); + Table targetTable = Table.class.cast( foreignKey.getTargetTable() ); + if ( sourceTable.isPhysicalTable() && + targetTable.isPhysicalTable() && + !targetTable.hasDenormalizedTables() ) { + checkExportIdentifier( foreignKey, exportIdentifiers ); + applySqlStrings( targets, dialect.getForeignKeyExporter().getSqlCreateStrings( foreignKey, jdbcEnvironment ) ); + } + } + } + } + + applySqlStrings( targets, dialect.applyConstraints( schema.getTables(), jdbcEnvironment ) ); + } + + // next, create all "after table" auxiliary objects + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && !auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlCreateStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); + } + } + + // and finally add all init commands + for ( InitCommand initCommand : database.getInitCommands() ) { + applySqlStrings( targets, initCommand.getInitCommands() ); + } + + for ( Target target : targets ) { + target.release(); + } + } + + private static void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { + final String exportIdentifier = exportable.getExportIdentifier(); + if ( exportIdentifiers.contains( exportIdentifier ) ) { + throw new SchemaManagementException( "SQL strings added more than once for: " + exportIdentifier ); + } + exportIdentifiers.add( exportIdentifier ); + } + + private static void applySqlStrings(Target[] targets, String... sqlStrings) { + if ( sqlStrings == null ) { + return; + } + + for ( Target target : targets ) { + for ( String sqlString : sqlStrings ) { + target.accept( sqlString ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java new file mode 100644 index 000000000000..7181616e639f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java @@ -0,0 +1,163 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Exportable; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.SchemaDropper; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.Target; + +/** + * This is functionally nothing more than the creation script from the older SchemaExport class (plus some + * additional stuff in the script). + * + * @author Steve Ebersole + */ +public class SchemaDropperImpl implements SchemaDropper { + + @Override + public void doDrop(Database database, boolean dropSchemas, List targets) throws SchemaManagementException { + doDrop( database, dropSchemas, targets.toArray( new Target[ targets.size() ] ) ); + } + + @Override + public void doDrop(Database database, boolean dropSchemas, Target... targets) throws SchemaManagementException { + final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment(); + final Dialect dialect = jdbcEnvironment.getDialect(); + + for ( Target target : targets ) { + target.prepare(); + } + + final Set exportIdentifiers = new HashSet( 50 ); + + // NOTE : init commands are irrelevant for dropping... + + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && ! auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlDropStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); + } + } + + for ( Schema schema : database.getSchemas() ) { + // we need to drop all constraints/indexes prior to dropping the tables + + applySqlStrings( targets, dialect.dropConstraints( schema.getTables(), jdbcEnvironment ) ); + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + if ( dialect.dropConstraints() ) { + for ( ForeignKey foreignKey : table.getForeignKeys() ) { + // only add the foreign key if its source and target are both physical tables + // and if the target table does not have any denormalized tables. + if ( Table.class.isInstance( foreignKey.getTable() ) && + Table.class.isInstance( foreignKey.getTargetTable() ) ) { + Table sourceTable = Table.class.cast( foreignKey.getTable() ); + Table targetTable = Table.class.cast( foreignKey.getTargetTable() ); + if ( sourceTable.isPhysicalTable() && + targetTable.isPhysicalTable() && + !targetTable.hasDenormalizedTables() ) { + checkExportIdentifier( foreignKey, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getForeignKeyExporter().getSqlDropStrings( foreignKey, jdbcEnvironment ) + ); + } + } + } + } + } + + // now it's safe to drop the tables + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + checkExportIdentifier( table, exportIdentifiers ); + applySqlStrings( targets, dialect.getTableExporter().getSqlDropStrings( table, jdbcEnvironment ) ); + } + + for ( Sequence sequence : schema.getSequences() ) { + checkExportIdentifier( sequence, exportIdentifiers ); + applySqlStrings( targets, dialect.getSequenceExporter().getSqlDropStrings( sequence, jdbcEnvironment ) ); + } + } + + for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : database.getAuxiliaryDatabaseObjects() ) { + if ( auxiliaryDatabaseObject.appliesToDialect( dialect ) && ! auxiliaryDatabaseObject.beforeTablesOnCreation() ) { + checkExportIdentifier( auxiliaryDatabaseObject, exportIdentifiers ); + applySqlStrings( + targets, + dialect.getAuxiliaryDatabaseObjectExporter().getSqlDropStrings( auxiliaryDatabaseObject, jdbcEnvironment ) + ); } + } + + for ( Schema schema : database.getSchemas() ) { + if ( dropSchemas ) { + applySqlStrings( targets, dialect.getDropSchemaCommand( schema.getName().getSchema().getText( dialect ) ) ); + } + } + + for ( Target target : targets ) { + target.release(); + } + } + + private static void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { + final String exportIdentifier = exportable.getExportIdentifier(); + if ( exportIdentifiers.contains( exportIdentifier ) ) { + throw new SchemaManagementException( "SQL strings added more than once for: " + exportIdentifier ); + } + exportIdentifiers.add( exportIdentifier ); + } + + private static void applySqlStrings(Target[] targets, String... sqlStrings) { + if ( sqlStrings == null ) { + return; + } + + for ( Target target : targets ) { + for ( String sqlString : sqlStrings ) { + target.accept( sqlString ); + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java new file mode 100644 index 000000000000..7c5ae9e25e2c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.Map; + +import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.tool.schema.spi.SchemaManagementTool; + +/** + * @author Steve Ebersole + */ +public class SchemaManagementToolInitiator implements StandardServiceInitiator { + public static final SchemaManagementToolInitiator INSTANCE = new SchemaManagementToolInitiator(); + + public SchemaManagementTool initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + final Object setting = configurationValues.get( AvailableSettings.SCHEMA_MANAGEMENT_TOOL ); + SchemaManagementTool tool = registry.getService( StrategySelector.class ).resolveStrategy( SchemaManagementTool.class, setting ); + if ( tool == null ) { + tool = new HibernateSchemaManagementTool(); + } + + return tool; + } + + @Override + public Class getServiceInitiated() { + return SchemaManagementTool.class; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java new file mode 100644 index 000000000000..60e93efc8808 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaMigratorImpl.java @@ -0,0 +1,189 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Exportable; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.SchemaMigrator; +import org.hibernate.tool.schema.spi.Target; + + +/** + * @author Steve Ebersole + */ +public class SchemaMigratorImpl implements SchemaMigrator { + @Override + public void doMigration( + Database database, + DatabaseInformation existingDatabase, + boolean createSchemas, + List targets) throws SchemaManagementException { + + for ( Target target : targets ) { + target.prepare(); + } + + doMigrationToTargets( database, existingDatabase, createSchemas, targets ); + + for ( Target target : targets ) { + target.release(); + } + } + + + protected void doMigrationToTargets( + Database database, + DatabaseInformation existingDatabase, + boolean createSchemas, + List targets) { + + final Set exportIdentifiers = new HashSet( 50 ); + + for ( Schema schema : database.getSchemas() ) { + if ( createSchemas ) { + // todo : add dialect method for getting a CREATE SCHEMA command and use it here + } + + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + checkExportIdentifier( table, exportIdentifiers ); + final TableInformation tableInformation = existingDatabase.getTableInformation( table.getTableName() ); + if ( tableInformation == null ) { + createTable( table, database.getJdbcEnvironment(), targets ); + } + else { + migrateTable( table, tableInformation, targets, database.getJdbcEnvironment() ); + } + + // todo : handle org.hibernate.mapping.Table.sqlCommentStrings + } + + for ( Table table : schema.getTables() ) { + final TableInformation tableInformation = existingDatabase.getTableInformation( table.getTableName() ); + if ( tableInformation == null ) { + // big problem... + throw new SchemaManagementException( "BIG PROBLEM" ); + } + + for ( Index index : table.getIndexes() ) { + // todo : + } + + if ( !database.getJdbcEnvironment().getDialect().hasAlterTable() ) { + continue; + } + + for ( ForeignKey foreignKey : table.getForeignKeys() ) { + final ForeignKeyInformation foreignKeyInformation = findMatchingForeignKey( foreignKey, tableInformation ); + // todo : .. implement + } + } + + for ( Sequence sequence : schema.getSequences() ) { + checkExportIdentifier( sequence, exportIdentifiers ); + final SequenceInformation sequenceInformation = existingDatabase.getSequenceInformation( sequence.getName() ); + if ( sequenceInformation != null ) { + // nothing we really can do... + continue; + } + + applySqlStrings( + database.getJdbcEnvironment().getDialect().getSequenceExporter().getSqlCreateStrings( + sequence, + database.getJdbcEnvironment() + ), + targets + ); + } + } + } + + private ForeignKeyInformation findMatchingForeignKey(ForeignKey foreignKey, TableInformation tableInformation) { + throw new NotYetImplementedException(); + } + + private void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { + final String exportIdentifier = exportable.getExportIdentifier(); + if ( exportIdentifiers.contains( exportIdentifier ) ) { + throw new SchemaManagementException( + String.format( + "Export identifier [%s] encountered more than once", + exportIdentifier + ) + ); + } + exportIdentifiers.add( exportIdentifier ); + } + + private void createTable(Table table, JdbcEnvironment jdbcEnvironment, List targets) { + applySqlStrings( + jdbcEnvironment.getDialect().getTableExporter().getSqlCreateStrings( table, jdbcEnvironment ), + targets + ); + } + + private static void applySqlStrings(String[] sqlStrings, List targets) { + if ( sqlStrings == null ) { + return; + } + + for ( Target target : targets ) { + for ( String sqlString : sqlStrings ) { + target.accept( sqlString ); + } + } + } + + + protected void migrateTable( + Table table, + TableInformation tableInformation, + List targets, + JdbcEnvironment jdbcEnvironment) { + applySqlStrings( + table.sqlAlterStrings( tableInformation, jdbcEnvironment ), + targets + ); + + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java new file mode 100644 index 000000000000..bb07edac6ce3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaValidatorImpl.java @@ -0,0 +1,146 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.tool.schema.extract.spi.ColumnInformation; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.hibernate.tool.schema.spi.SchemaValidator; + +/** + * @author Steve Ebersole + */ +public class SchemaValidatorImpl implements SchemaValidator { + + private final Dialect dialect; + + public SchemaValidatorImpl(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public void doValidation(Database database, DatabaseInformation databaseInformation) { + for ( Schema schema : database.getSchemas() ) { + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } + final TableInformation tableInformation = databaseInformation.getTableInformation( + table.getTableName() + ); + validateTable( table, tableInformation ); + } + } + + for ( Schema schema : database.getSchemas() ) { + for ( Sequence sequence : schema.getSequences() ) { + final SequenceInformation sequenceInformation = databaseInformation.getSequenceInformation( + sequence.getName() + ); + validateSequence( sequence, sequenceInformation ); + } + } + } + + protected void validateTable(Table table, TableInformation tableInformation) { + if ( tableInformation == null ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: missing table [%s]", + table.getTableName().toText() + ) + ); + } + + for ( Value value : table.values() ) { + if ( Column.class.isInstance( value ) ) { + final Column column = (Column) value; + final ColumnInformation columnInformation = tableInformation.getColumn( column.getColumnName() ); + if ( columnInformation == null ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: missing column [%s] in table [%s]", + column.getColumnName().getText(), + table.getTableName().toText() + ) + ); + } + + validateColumnType( table, column, columnInformation ); + } + } + } + + protected void validateColumnType(Table table, Column column, ColumnInformation columnInformation) { + // this is the old Hibernate check... + final boolean typesMatch = column.getJdbcDataType().getTypeCode() == columnInformation.getTypeCode() + || column.getSqlTypeString(dialect).toLowerCase().startsWith( columnInformation.getTypeName().toLowerCase() ); + if ( !typesMatch ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: wrong column type encountered in column [%s] in table [%s]; found [%s], but expecting [%s]", + column.getColumnName().getText(), + table.getTableName().toText(), + columnInformation.getTypeName().toLowerCase(), + column.getSqlType().toLowerCase() + ) + ); + } + + // but I think a better check involves checks against type code and then the type code family, not + // just the type name. + // + // See org.hibernate.type.descriptor.sql.JdbcTypeFamilyInformation + + } + + protected void validateSequence(Sequence sequence, SequenceInformation sequenceInformation) { + if ( sequenceInformation == null ) { + throw new SchemaManagementException( + String.format( "Schema-validation: missing sequence [%s]", sequence.getName().toText() ) + ); + } + + if ( sequenceInformation.getIncrementSize() > 0 + && sequence.getIncrementSize() != sequenceInformation.getIncrementSize() ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: sequence [%s] defined inconsistent increment-size; found [%s] but expecting [%s]", + sequence.getName().toText(), + sequenceInformation.getIncrementSize(), + sequence.getIncrementSize() + ) + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java new file mode 100644 index 000000000000..90954b38a31b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardAuxiliaryDatabaseObjectExporter.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.AuxiliaryDatabaseObject; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardAuxiliaryDatabaseObjectExporter implements Exporter { + private final Dialect dialect; + + public StandardAuxiliaryDatabaseObjectExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(AuxiliaryDatabaseObject object, JdbcEnvironment jdbcEnvironment) { + return object.sqlCreateStrings( dialect ); + } + + @Override + public String[] getSqlDropStrings(AuxiliaryDatabaseObject object, JdbcEnvironment jdbcEnvironment) { + return object.sqlDropStrings( dialect ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java new file mode 100644 index 000000000000..f04d67109839 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardForeignKeyExporter implements Exporter { + private final Dialect dialect; + + public StandardForeignKeyExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(ForeignKey foreignKey, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.hasAlterTable() ) { + return NO_COMMANDS; + } + + if ( ! foreignKey.createConstraint() ) { + return NO_COMMANDS; + } + + final int numberOfColumns = foreignKey.getColumnSpan(); + final String[] columnNames = new String[ numberOfColumns ]; + final String[] targetColumnNames = new String[ numberOfColumns ]; + + int position = 0; + for ( ForeignKey.ColumnMapping columnMapping : foreignKey.getColumnMappings() ) { + columnNames[position] = columnMapping.getSourceColumn().getColumnName().getText( dialect ); + targetColumnNames[position] = columnMapping.getTargetColumn().getColumnName().getText( dialect ); + position++; + } + + + final String sourceTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) foreignKey.getSourceTable() ).getTableName() + ); + final String targetTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ((Table) foreignKey.getTargetTable()).getTableName() + ); + + final StringBuilder buffer = new StringBuilder( "alter table " ) + .append( sourceTableName ) + .append( + dialect.getAddForeignKeyConstraintString( + foreignKey.getName().getText( dialect ), + columnNames, + targetTableName, + targetColumnNames, + foreignKey.referencesPrimaryKey() + ) + ); + + // TODO: If a dialect does not support cascade-delete, can it support other actions? (HHH-6428) + // For now, assume not. + if ( dialect.supportsCascadeDelete() ) { + if ( foreignKey.getDeleteRule() != ForeignKey.ReferentialAction.NO_ACTION ) { + buffer.append( " on delete " ).append( foreignKey.getDeleteRule().getActionString() ); + } + if ( foreignKey.getUpdateRule() != ForeignKey.ReferentialAction.NO_ACTION ) { + buffer.append( " on update " ).append( foreignKey.getUpdateRule().getActionString() ); + } + } + + return new String[] { buffer.toString() }; + } + + @Override + public String[] getSqlDropStrings(ForeignKey foreignKey, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.hasAlterTable() ) { + return NO_COMMANDS; + } + + if ( ! foreignKey.createConstraint() ) { + return NO_COMMANDS; + } + + final String sourceTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) foreignKey.getSourceTable() ).getTableName() + ); + return new String[] { + "alter table " + sourceTableName + dialect.getDropForeignKeyString() + foreignKey.getName().getText( dialect ) + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java new file mode 100644 index 000000000000..f41110a7085e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java @@ -0,0 +1,83 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardIndexExporter implements Exporter { + private final Dialect dialect; + + public StandardIndexExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Index index, JdbcEnvironment jdbcEnvironment) { + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) index.getTable() ).getTableName() + ); + StringBuilder buf = new StringBuilder() + .append( "create index " ) + .append( dialect.qualifyIndexName() + ? index.getName().getText( dialect ) : index.getName().getUnqualifiedText( dialect ) ) + .append( " on " ) + .append( tableName ) + .append( " (" ); + + boolean first = true; + for ( Column column : index.getColumns() ) { + if ( first ) { + first = false; + } + else { + buf.append( ", " ); + } + buf.append( ( column.getColumnName().getText( dialect ) ) ); + } + buf.append( ")" ); + return new String[] { buf.toString() }; + } + + @Override + public String[] getSqlDropStrings(Index index, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) index.getTable() ).getTableName() + ); + return new String[] { + "drop index " + index.getName().getQualifiedText( tableName, dialect ) + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java new file mode 100644 index 000000000000..6a74b5e25428 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardSequenceExporter.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Sequence; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardSequenceExporter implements Exporter { + private final Dialect dialect; + + public StandardSequenceExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Sequence sequence, JdbcEnvironment jdbcEnvironment) { + return dialect.getCreateSequenceStrings( + jdbcEnvironment.getQualifiedObjectNameSupport().formatName( sequence.getName() ), + sequence.getInitialValue(), + sequence.getIncrementSize() + ); + } + + @Override + public String[] getSqlDropStrings(Sequence sequence, JdbcEnvironment jdbcEnvironment) { + return dialect.getDropSequenceStrings( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( sequence.getName() ) ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java new file mode 100644 index 000000000000..963aacc1594d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java @@ -0,0 +1,177 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.CheckConstraint; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * @author Steve Ebersole + */ +public class StandardTableExporter implements Exporter
    { + protected final Dialect dialect; + + public StandardTableExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Table table, JdbcEnvironment jdbcEnvironment) { + boolean hasPrimaryKey = table.getPrimaryKey().getColumns().iterator().hasNext(); + StringBuilder buf = + new StringBuilder(tableCreateString( hasPrimaryKey )) + .append( ' ' ) + .append( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( table.getTableName() ) ) + .append( " (" ); + + + boolean isPrimaryKeyIdentity = + hasPrimaryKey && + table.getPrimaryKey().getColumnSpan() == 1 && + table.getPrimaryKey().getColumns().get( 0 ).isIdentity(); + + // Try to find out the name of the primary key in case the dialect needs it to create an identity + String pkColName = null; + if ( hasPrimaryKey ) { + Column pkColumn = table.getPrimaryKey().getColumns().iterator().next(); + pkColName = pkColumn.getColumnName().getText( dialect ); + } + + boolean isFirst = true; + for ( Column col : table.sortedColumns() ) { + if ( isFirst ) { + isFirst = false; + } + else { + buf.append( ", " ); + } + String colName = col.getColumnName().getText( dialect ); + + buf.append( colName ).append( ' ' ); + + if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) { + // to support dialects that have their own identity data type + if ( dialect.hasDataTypeInIdentityColumn() ) { + buf.append( col.getSqlTypeString( dialect ) ); + } + buf.append( ' ' ) + .append( dialect.getIdentityColumnString( col.getJdbcDataType().getTypeCode() ) ); + } + else { + buf.append( col.getSqlTypeString( dialect ) ); + + String defaultValue = col.getDefaultValue(); + if ( defaultValue != null ) { + buf.append( " default " ).append( defaultValue ); + } + + if ( col.isNullable() ) { + buf.append( dialect.getNullColumnString() ); + } + else { + buf.append( " not null" ); + } + + } + + if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) { + buf.append( " check (" ) + .append( col.getCheckCondition() ) + .append( ")" ); + } + + String columnComment = col.getComment(); + if ( columnComment != null ) { + buf.append( dialect.getColumnComment( columnComment ) ); + } + } + if ( hasPrimaryKey ) { + buf.append( ", " ) + .append( table.getPrimaryKey().sqlConstraintStringInCreateTable( dialect ) ); + } + + applyTableCheck( table, buf ); + + buf.append( ')' ); + applyTableTypeString( buf ); + + List sqlStrings = new ArrayList(); + sqlStrings.add( buf.toString() ); + + applyComments( table, sqlStrings ); + + return sqlStrings.toArray( new String[ sqlStrings.size() ] ); + } + + protected void applyComments(Table table, List sqlStrings) { + for ( String comment : table.getComments() ) { + if ( comment != null ) { + sqlStrings.add( dialect.getTableComment( comment ) ); + } + } + } + + protected void applyTableTypeString(StringBuilder buf) { + buf.append( dialect.getTableTypeString() ); + } + + protected void applyTableCheck(Table table, StringBuilder buf) { + if ( dialect.supportsTableCheck() ) { + for ( CheckConstraint checkConstraint : table.getCheckConstraints() ) { + buf.append( ", check (" ) + .append( checkConstraint ) + .append( ')' ); + } + } + } + + protected String tableCreateString(boolean hasPrimaryKey) { + return hasPrimaryKey ? dialect.getCreateTableString() : dialect.getCreateMultisetTableString(); + + } + + @Override + public String[] getSqlDropStrings(Table table, JdbcEnvironment jdbcEnvironment) { + StringBuilder buf = new StringBuilder( "drop table " ); + if ( dialect.supportsIfExistsBeforeTableName() ) { + buf.append( "if exists " ); + } + + buf.append( jdbcEnvironment.getQualifiedObjectNameSupport().formatName( table.getTableName() ) ) + .append( dialect.getCascadeConstraintsString() ); + + if ( dialect.supportsIfExistsAfterTableName() ) { + buf.append( " if exists" ); + } + + return new String[] { buf.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardUniqueKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardUniqueKeyExporter.java new file mode 100644 index 000000000000..33f66bafa4ad --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardUniqueKeyExporter.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + +import java.util.Iterator; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.spi.Exporter; + +/** + * Unique constraint Exporter. Note that it's parameterized for Constraint, rather than UniqueKey. This is + * to allow Dialects to decide whether or not to create unique constraints for unique indexes. + * + * @author Brett Meyer + */ +public class StandardUniqueKeyExporter implements Exporter { + private final Dialect dialect; + + public StandardUniqueKeyExporter(Dialect dialect) { + this.dialect = dialect; + } + + @Override + public String[] getSqlCreateStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.hasAlterTable() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) constraint.getTable() ).getTableName() + ); + StringBuilder sb = new StringBuilder() + .append( "alter table " ) + .append( tableName ) + .append( " add constraint " ) + .append( constraint.getName().getText( dialect ) ) + .append( " unique ( " ); + + final Iterator columnIterator = constraint.getColumns().iterator(); + while ( columnIterator.hasNext() ) { + Column column = (Column) columnIterator.next(); + sb.append( column.getColumnName().getText( dialect ) ); + if ( columnIterator.hasNext() ) { + sb.append( ", " ); + } + } + sb.append( ")" ); + return new String[] { sb.toString() }; + } + + @Override + public String[] getSqlDropStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) constraint.getTable() ).getTableName() + ); + final StringBuilder sb = new StringBuilder( "alter table " ); + sb.append( tableName ); + sb.append(" drop constraint " ); + if ( dialect.supportsIfExistsBeforeConstraintName() ) { + sb.append( "if exists " ); + } + sb.append( constraint.getName().getText( dialect ) ); + if ( dialect.supportsIfExistsAfterConstraintName() ) { + sb.append( " if exists" ); + } + return new String[] { sb.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java new file mode 100644 index 000000000000..532c822261f6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java @@ -0,0 +1,100 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.internal; + + +import java.util.List; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +/** + * @author Strong Liu + */ +public class TemporaryTableExporter extends StandardTableExporter { + + public TemporaryTableExporter(Dialect dialect) { + super(dialect); + } + + @Override + public String[] getSqlCreateStrings(Table exportable, JdbcEnvironment jdbcEnvironment) { + if ( dialect.supportsTemporaryTables() ) { + String temperaryTableName = generateTableName( dialect, exportable ); + Table table = new Table( + exportable.getSchema(), + Identifier.toIdentifier( temperaryTableName ), + Identifier.toIdentifier( temperaryTableName ) + ); + for ( final Column column : exportable.getPrimaryKey().getColumns() ) { + Column clone = table.createColumn( column.getColumnName() ); + clone.setCheckCondition( column.getCheckCondition() ); + clone.setIdentity( column.isIdentity() ); + clone.setSize( column.getSize() ); + clone.setSqlType( column.getSqlType() ); + clone.setJdbcDataType( column.getJdbcDataType() ); + clone.setNullable( column.isNullable() ); + clone.setComment( column.getComment() ); + clone.setDefaultValue( column.getDefaultValue() ); + clone.setReadFragment( column.getReadFragment() ); + clone.setWriteFragment( column.getWriteFragment() ); + } + return super.getSqlCreateStrings( table, jdbcEnvironment ); + } + return null; + } + + @Override + protected String tableCreateString(boolean hasPrimaryKey) { + return dialect.getCreateTemporaryTableString(); + } + + @Override + protected void applyTableCheck(Table table, StringBuilder buf) { + // N/A + } + + @Override + protected void applyComments(Table table, List sqlStrings) { + // N/A + } + + @Override + protected void applyTableTypeString(StringBuilder buf) { + buf.append( " " ).append( dialect.getCreateTemporaryTablePostfix() ); + } + + @Override + public String[] getSqlDropStrings(Table exportable, JdbcEnvironment jdbcEnvironment) { + return null; + } + + public static String generateTableName(final Dialect dialect, final TableSpecification primaryTable) { + return dialect.generateTemporaryTableName( primaryTable.getLogicalName().getText() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java new file mode 100644 index 000000000000..12d72e9f2c5b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/package-info.java @@ -0,0 +1 @@ +package org.hibernate.tool.schema; \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java new file mode 100644 index 000000000000..10408f392ec0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Exporter.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Exportable; + +/** + * Defines a contract for exporting of database objects (tables, sequences, etc) for use in SQL {@code CREATE} and + * {@code DROP} scripts + * + * @author Steve Ebersole + */ +public interface Exporter { + public static final String[] NO_COMMANDS = new String[0]; + + /** + * Get the commands needed for creation. + * + * @return The commands needed for creation scripting. + */ + public String[] getSqlCreateStrings(T exportable, JdbcEnvironment jdbcEnvironment); + + /** + * Get the commands needed for dropping. + * + * @return The commands needed for drop scripting. + */ + public String[] getSqlDropStrings(T exportable, JdbcEnvironment jdbcEnvironment); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java new file mode 100644 index 000000000000..4ee9713996c9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaCreator.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Database; + +/** + * Service delegate for handling schema creation. + * + * @author Steve Ebersole + */ +public interface SchemaCreator { + /** + * Perform the creation to the specified targets + * + * @param database The Hibernate relational model to create + * @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})? + * @param targets The targets for creation + * + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doCreation(Database database, boolean createSchemas, Target... targets) throws SchemaManagementException; + + /** + * Perform the creation to the specified targets + * + * + * @param database The Hibernate relational model to create + * @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})? + * + * @param targets The targets for creation + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doCreation(Database database, boolean createSchemas, List targets) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java new file mode 100644 index 000000000000..1b5305fb3614 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaDropper.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Database; + +/** + * Service delegate for handling schema dropping. + * + * @author Steve Ebersole + */ +public interface SchemaDropper { + /** + * Perform the drop to the specified targets + * + * @param database The Hibernate relational model to drop + * @param dropSchemas Should the schema(s) actually be dropped also ({@code DROP SCHEMA})? + * @param targets The targets for drop + * + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doDrop(Database database, boolean dropSchemas, Target... targets) throws SchemaManagementException; + + /** + * Perform the drop to the specified targets + * + * @param database The Hibernate relational model to drop + * @param dropSchemas Should the schema(s) actually be dropped also ({@code DROP SCHEMA})? + * @param targets The targets for drop + * + * @throws SchemaManagementException Indicates a problem processing the creation + */ + public void doDrop(Database database, boolean dropSchemas, List targets) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementException.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementException.java new file mode 100644 index 000000000000..3798b13d8494 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementException.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import org.hibernate.HibernateException; + +/** + * Indicates a problem in performing schema management. + * + * @author Steve Ebersole + */ +public class SchemaManagementException extends HibernateException { + public SchemaManagementException(String message) { + super( message ); + } + + public SchemaManagementException(String message, Throwable root) { + super( message, root ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java new file mode 100644 index 000000000000..2bda8df22684 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementTool.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.Map; + +import org.hibernate.service.Service; + +/** + * Contract for schema management tool integration. + * + * @author Steve Ebersole + */ +public interface SchemaManagementTool extends Service { + public SchemaCreator getSchemaCreator(Map options); + public SchemaDropper getSchemaDropper(Map options); + public SchemaMigrator getSchemaMigrator(Map options); + public SchemaValidator getSchemaValidator(Map options); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java new file mode 100644 index 000000000000..dc34db162d56 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaMigrator.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import java.util.List; + +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; + +/** + * Service delegate for handling schema migration. + * + * @author Steve Ebersole + */ +public interface SchemaMigrator { + /** + * Perform a migration to the specified targets. + * + * @param database The current Hibernate relational model + * @param existingDatabase Access to the information about the existing database. + * @param createSchemas Should the schema(s) actually be created as well ({@code CREATE SCHEMA})? + * @param targets The migration targets + * + * @throws SchemaManagementException + */ + public void doMigration( + Database database, + DatabaseInformation existingDatabase, + boolean createSchemas, + List targets) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaValidator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaValidator.java new file mode 100644 index 000000000000..fb45ce754aee --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaValidator.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +import org.hibernate.metamodel.spi.relational.Database; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; + +/** + * Service delegate for handling schema validations + * + * @author Steve Ebersole + */ +public interface SchemaValidator { + /** + * Handle schema validation requests + * + * @param database The current Hibernate relational model + * @param databaseInformation Access to the existing database information. + * + * @throws SchemaManagementException + */ + public void doValidation(Database database, DatabaseInformation databaseInformation) throws SchemaManagementException; +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java new file mode 100644 index 000000000000..b351653c9067 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/Target.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.tool.schema.spi; + +/** + * Describes the target of schema management actions. Typically this would be a stream/writer or the database + * Connection + * + * @author Steve Ebersole + */ +public interface Target { + /** + * Does this target accept actions coming from an import script? If {@code false}, actions are not + * sent to this target's {@link #accept(String)} method + * + * @return {@code true} if import script actions should be sent to this target; {@code false} if they should not. + */ + public boolean acceptsImportScriptActions(); + + /** + * Prepare for accepting actions + * + * @throws SchemaManagementException If there is a problem preparing the target. + */ + public void prepare(); + + /** + * Accept a management action. For stream/writer-based targets, this would indicate to write the action; for + * JDBC based targets, it would indicate to execute the action + * + * @param action The action to perform. + * + * @throws SchemaManagementException If there is a problem accepting the action. + */ + public void accept(String action); + + /** + * Release the target after all actions have been processed. + * + * @throws SchemaManagementException If there is a problem releasing the target. + */ + public void release(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java b/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java index 2b3b7ad8a241..a541fca848a6 100755 --- a/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/DynamicMapInstantiator.java @@ -31,7 +31,7 @@ import java.util.Set; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; public class DynamicMapInstantiator implements Instantiator { @@ -57,10 +57,10 @@ public DynamicMapInstantiator(PersistentClass mappingInfo) { } public DynamicMapInstantiator(EntityBinding mappingInfo) { - this.entityName = mappingInfo.getEntity().getName(); + this.entityName = mappingInfo.getEntityName(); isInstanceEntityNames.add( entityName ); for ( EntityBinding subEntityBinding : mappingInfo.getPostOrderSubEntityBindingClosure() ) { - isInstanceEntityNames.add( subEntityBinding.getEntity().getName() ); + isInstanceEntityNames.add( subEntityBinding.getEntityName() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java b/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java index 7ebf894a05a7..07c3df2e72a3 100755 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java @@ -30,12 +30,14 @@ import org.hibernate.InstantiationException; import org.hibernate.PropertyNotFoundException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.bytecode.spi.ReflectionOptimizer; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.service.ServiceRegistry; import org.jboss.logging.Logger; @@ -54,8 +56,22 @@ public class PojoInstantiator implements Instantiator, Serializable { private final Class proxyInterface; private final boolean isAbstract; - public PojoInstantiator(Component component, ReflectionOptimizer.InstantiationOptimizer optimizer) { - this.mappedClass = component.getComponentClass(); + public PojoInstantiator( + ServiceRegistry serviceRegistry, + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + ReflectionOptimizer.InstantiationOptimizer optimizer) { + if ( isIdentifierMapper ) { + final EntityIdentifier entityIdentifier = + embeddableBinding.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + this.mappedClass = entityIdentifier.getLookupClassBinding().getIdClassType(); + } + else { + final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class ); + this.mappedClass = cls.classForName( + embeddableBinding.getAttributeContainer().getDescriptor().getName().toString() + ); + } this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); this.optimizer = optimizer; @@ -71,27 +87,22 @@ public PojoInstantiator(Component component, ReflectionOptimizer.InstantiationOp } } - public PojoInstantiator(PersistentClass persistentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) { - this.mappedClass = persistentClass.getMappedClass(); + public PojoInstantiator( + ServiceRegistry serviceRegistry, + EntityBinding entityBinding, + ReflectionOptimizer.InstantiationOptimizer optimizer) { + final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class ); + this.mappedClass = cls.classForName( entityBinding.getEntity().getDescriptor().getName().toString() ); this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); - this.proxyInterface = persistentClass.getProxyInterface(); - this.embeddedIdentifier = persistentClass.hasEmbeddedIdentifier(); - this.optimizer = optimizer; - - try { - constructor = ReflectHelper.getDefaultConstructor( mappedClass ); + if ( entityBinding.getProxyInterfaceType() == null ) { + this.proxyInterface = null; } - catch ( PropertyNotFoundException pnfe ) { - LOG.noDefaultConstructor(mappedClass.getName()); - constructor = null; + else { + this.proxyInterface = cls.classForName( + entityBinding.getProxyInterfaceType().getName().toString() + ); } - } - - public PojoInstantiator(EntityBinding entityBinding, ReflectionOptimizer.InstantiationOptimizer optimizer) { - this.mappedClass = entityBinding.getEntity().getClassReference(); - this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); - this.proxyInterface = entityBinding.getProxyInterfaceType().getValue(); - this.embeddedIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded(); + this.embeddedIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().isNonAggregatedComposite(); this.optimizer = optimizer; try { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java index c9b5d50990fb..06d25486d572 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java @@ -28,34 +28,38 @@ import org.hibernate.EntityMode; import org.hibernate.FetchMode; import org.hibernate.HibernateException; -import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.engine.internal.UnsavedValueFactory; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.IdentifierValue; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.VersionValue; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.id.IdentifierGenerator; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AbstractPluralAttributeBinding; -import org.hibernate.metamodel.binding.AssociationAttributeBinding; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SimpleValueBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.Cascadeable; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.Fetchable; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; +import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.tuple.entity.EntityBasedAssociationAttribute; import org.hibernate.tuple.entity.EntityBasedBasicAttribute; import org.hibernate.tuple.entity.EntityBasedCompositionAttribute; import org.hibernate.tuple.entity.VersionProperty; import org.hibernate.type.AssociationType; +import org.hibernate.type.ComponentType; import org.hibernate.type.CompositeType; import org.hibernate.type.Type; import org.hibernate.type.VersionType; @@ -117,48 +121,78 @@ public static IdentifierProperty buildIdentifierAttribute( * Generates an IdentifierProperty representation of the for a given entity mapping. * * @param mappedEntity The mapping definition of the entity. - * @param generator The identifier value generator to use for this identifier. + * @param generator The identifier value generator to use for this identifier + * @param sessionFactory The session factory. * @return The appropriate IdentifierProperty definition. + * + * TODO: remove session factory parameter. */ public static IdentifierProperty buildIdentifierProperty( EntityBinding mappedEntity, - IdentifierGenerator generator) { + IdentifierGenerator generator, + SessionFactoryImplementor sessionFactory) { - final BasicAttributeBinding property = mappedEntity.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + final SingularAttributeBinding attributeBinding = + mappedEntity.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); // TODO: the following will cause an NPE with "virtual" IDs; how should they be set? // (steve) virtual attributes will still be attributes, they will simply be marked as virtual. - // see org.hibernate.metamodel.domain.AbstractAttributeContainer.locateOrCreateVirtualAttribute() - - final String mappedUnsavedValue = property.getUnsavedValue(); - final Type type = property.getHibernateTypeDescriptor().getResolvedTypeMapping(); + // see org.hibernate.metamodel.spi.domain.AbstractAttributeContainer.locateOrCreateVirtualAttribute() + + final String mappedUnsavedValue = mappedEntity.getHierarchyDetails().getEntityIdentifier().getUnsavedValue(); + + if ( mappedEntity.getHierarchyDetails().getEntityIdentifier().getNature() + == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) { + // the "attribute" will need to be virtual since there is no single + // attribute identifying the identifier + final ComponentType type = sessionFactory.getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( + sessionFactory.getServiceRegistry(), + ( (EmbeddedAttributeBinding) attributeBinding ).getEmbeddableBinding(), + true, + mappedEntity.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().definedIdClass() + ) + ); - IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue( - mappedUnsavedValue, - getGetter( property ), - type, - getConstructor( mappedEntity ) + final IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue( + mappedUnsavedValue, + getGetter( attributeBinding, sessionFactory ), + type, + getConstructor( + mappedEntity, + sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ) + ) ); - if ( property == null ) { - // this is a virtual id property... return new IdentifierProperty( - type, - mappedEntity.getHierarchyDetails().getEntityIdentifier().isEmbedded(), - mappedEntity.getHierarchyDetails().getEntityIdentifier().isIdentifierMapper(), + type, + true, + mappedEntity.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().definedIdClass(), unsavedValue, generator - ); + ); } else { + final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + + final IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue( + mappedUnsavedValue, + getGetter( attributeBinding, sessionFactory ), + type, + getConstructor( + mappedEntity, + sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ) + ) + ); + return new IdentifierProperty( - property.getAttribute().getName(), + attributeBinding.getAttribute().getName(), null, type, - mappedEntity.getHierarchyDetails().getEntityIdentifier().isEmbedded(), + false, unsavedValue, generator - ); + ); } } @@ -211,15 +245,53 @@ public static VersionProperty buildVersionProperty( * Generates a VersionProperty representation for an entity mapping given its * version mapping Property. * - * @param property The version mapping Property. * @param lazyAvailable Is property lazy loading currently available. * @return The appropriate VersionProperty definition. */ public static VersionProperty buildVersionProperty( EntityPersister persister, - BasicAttributeBinding property, + SessionFactoryImplementor sessionFactory, + int attributeNumber, + EntityBinding entityBinding, boolean lazyAvailable) { - throw new NotYetImplementedException(); + final BasicAttributeBinding property = entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding(); + final String mappedUnsavedValue = entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue(); + final VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue( + mappedUnsavedValue, + getGetter( property, sessionFactory ), + (VersionType) property.getHibernateTypeDescriptor().getResolvedTypeMapping(), + getConstructor( + (EntityBinding) property.getContainer(), + sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ) + ) + ); + + boolean lazy = lazyAvailable && property.isLazy(); + + final CascadeStyle cascadeStyle = property.isCascadeable() + ? ( (Cascadeable) property ).getCascadeStyle() + : CascadeStyles.NONE; + + // TODO: set value generation strategy properly + return new VersionProperty( + persister, + sessionFactory, + attributeNumber, + property.getAttribute().getName(), + property.getHibernateTypeDescriptor().getResolvedTypeMapping(), + new BaselineAttributeInformation.Builder() + .setLazy( lazy ) + .setInsertable( true ) + .setUpdateable( true ) + .setValueGenerationStrategy( null ) + .setNullable( property.isNullable() || property.isOptional() ) + .setDirtyCheckable( !lazy ) + .setVersionable( property.isIncludedInOptimisticLocking() ) + .setCascadeStyle( cascadeStyle ) + .createInformation(), + + unsavedValue + ); } public static enum NonIdentifierAttributeNature { @@ -326,6 +398,112 @@ public static NonIdentifierAttribute buildEntityBasedAttribute( } } + public static NonIdentifierAttribute buildEntityBasedAttribute( + EntityPersister persister, + SessionFactoryImplementor sessionFactory, + int attributeNumber, + AttributeBinding property, + boolean lazyAvailable) { + final Type type = property.getHibernateTypeDescriptor().getResolvedTypeMapping(); + if ( type == null ) { + throw new HibernateException( "Could not resolve Type for attribute : " + property.getAttributeRole().getFullPath() ); + } + final NonIdentifierAttributeNature nature = decode( type ); + final boolean alwaysDirtyCheck = type.isAssociationType() && + ( (AssociationType) type ).isAlwaysDirtyChecked(); + final String name = property.getAttribute().getName(); + final BaselineAttributeInformation.Builder builder = new BaselineAttributeInformation.Builder(); + final FetchMode fetchMode = Fetchable.class.isInstance( property ) + ? ( (Fetchable) property ).getFetchMode() + : FetchMode.DEFAULT; + builder.setFetchMode( fetchMode ).setVersionable( property.isIncludedInOptimisticLocking() ) + .setLazy( lazyAvailable && property.isLazy() ); + if ( property.getAttribute().isSingular() ) { + //basic, association, composite + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) property; + final CascadeStyle cascadeStyle = singularAttributeBinding.isCascadeable() + ? ( (Cascadeable) singularAttributeBinding ).getCascadeStyle() + : CascadeStyles.NONE; + + // TODO: set value generation strategy properly + builder.setInsertable( singularAttributeBinding.isIncludedInInsert() ) + .setUpdateable( singularAttributeBinding.isIncludedInUpdate() ) + .setValueGenerationStrategy( null ) + .setNullable( singularAttributeBinding.isNullable() || singularAttributeBinding.isOptional() ) + .setDirtyCheckable( + alwaysDirtyCheck || singularAttributeBinding.isIncludedInUpdate() + ) + .setCascadeStyle( cascadeStyle ); + switch ( nature ) { + case BASIC: { + return new EntityBasedBasicAttribute( + persister, + sessionFactory, + attributeNumber, + name, + type, + builder.createInformation() + ); + } + case COMPOSITE: { + return new EntityBasedCompositionAttribute( + persister, + sessionFactory, + attributeNumber, + name, + (CompositeType) type, + builder.createInformation() + ); + } + case ENTITY: + case ANY: { + return new EntityBasedAssociationAttribute( + persister, + sessionFactory, + attributeNumber, + name, + (AssociationType) type, + builder.createInformation() + ); + } + default: { + throw new HibernateException( "Internal error" ); + } + } + } + else { + final AbstractPluralAttributeBinding pluralAttributeBinding = (AbstractPluralAttributeBinding) property; + final CascadeStyle cascadeStyle; + if ( pluralAttributeBinding.isCascadeable() ) { + final Cascadeable elementBinding = + (Cascadeable) pluralAttributeBinding.getPluralAttributeElementBinding(); + cascadeStyle = elementBinding.getCascadeStyle(); + } + else { + cascadeStyle = CascadeStyles.NONE; + } + + // TODO: set value generation strategy properly + builder.setInsertable( pluralAttributeBinding.getPluralAttributeKeyBinding().isInsertable() ) + .setUpdateable( pluralAttributeBinding.getPluralAttributeKeyBinding().isUpdatable() ) + .setValueGenerationStrategy( null ) + .setNullable( true ) + .setDirtyCheckable( + alwaysDirtyCheck || pluralAttributeBinding.getPluralAttributeKeyBinding() + .isUpdatable() + ) + .setCascadeStyle( cascadeStyle ); + return new EntityBasedAssociationAttribute( + persister, + sessionFactory, + attributeNumber, + name, + (AssociationType) type, + builder.createInformation() + ); + } + } + private static NonIdentifierAttributeNature decode(Type type) { if ( type.isAssociationType() ) { AssociationType associationType = (AssociationType) type; @@ -390,6 +568,10 @@ public static StandardProperty buildStandardProperty(AttributeBinding property, final Type type = property.getHibernateTypeDescriptor().getResolvedTypeMapping(); + if ( type == null ) { + throw new HibernateException( "Unable to determine attribute type : " + property.getAttributeRole().getFullPath() ); + } + // we need to dirty check collections, since they can cause an owner // version number increment @@ -401,22 +583,23 @@ public static StandardProperty buildStandardProperty(AttributeBinding property, if ( property.getAttribute().isSingular() ) { final SingularAttributeBinding singularAttributeBinding = ( SingularAttributeBinding ) property; - final CascadeStyle cascadeStyle = singularAttributeBinding.isAssociation() - ? ( (AssociationAttributeBinding) singularAttributeBinding ).getCascadeStyle() + final CascadeStyle cascadeStyle = singularAttributeBinding.isCascadeable() + ? ( (Cascadeable) singularAttributeBinding ).getCascadeStyle() : CascadeStyles.NONE; final FetchMode fetchMode = singularAttributeBinding.isAssociation() - ? ( (AssociationAttributeBinding) singularAttributeBinding ).getFetchMode() + ? ( (Fetchable) singularAttributeBinding ).getFetchMode() : FetchMode.DEFAULT; + // TODO: set value generation strategy properly return new StandardProperty( singularAttributeBinding.getAttribute().getName(), type, lazyAvailable && singularAttributeBinding.isLazy(), - true, // insertable - true, // updatable + singularAttributeBinding.isIncludedInInsert(), // insertable + singularAttributeBinding.isIncludedInUpdate(), // updatable null, - singularAttributeBinding.isNullable(), - alwaysDirtyCheck || areAllValuesIncludedInUpdate( singularAttributeBinding ), + singularAttributeBinding.isNullable() || singularAttributeBinding.isOptional(), + alwaysDirtyCheck || singularAttributeBinding.isIncludedInUpdate(), singularAttributeBinding.isIncludedInOptimisticLocking(), cascadeStyle, fetchMode @@ -424,42 +607,34 @@ public static StandardProperty buildStandardProperty(AttributeBinding property, } else { final AbstractPluralAttributeBinding pluralAttributeBinding = (AbstractPluralAttributeBinding) property; - final CascadeStyle cascadeStyle = pluralAttributeBinding.isAssociation() - ? pluralAttributeBinding.getCascadeStyle() - : CascadeStyles.NONE; + final CascadeStyle cascadeStyle; + if ( pluralAttributeBinding.isCascadeable() ) { + final Cascadeable elementBinding = + (Cascadeable) pluralAttributeBinding.getPluralAttributeElementBinding(); + cascadeStyle = elementBinding.getCascadeStyle(); + } + else { + cascadeStyle = CascadeStyles.NONE; + } final FetchMode fetchMode = pluralAttributeBinding.isAssociation() ? pluralAttributeBinding.getFetchMode() : FetchMode.DEFAULT; + // TODO: set value generation strategy properly return new StandardProperty( pluralAttributeBinding.getAttribute().getName(), type, lazyAvailable && pluralAttributeBinding.isLazy(), - // TODO: fix this when HHH-6356 is fixed; for now assume AbstractPluralAttributeBinding is updatable and insertable - true, // pluralAttributeBinding.isInsertable(), - true, //pluralAttributeBinding.isUpdatable(), + pluralAttributeBinding.getPluralAttributeKeyBinding().isInsertable(), + pluralAttributeBinding.getPluralAttributeKeyBinding().isUpdatable(), null, - false, // nullable - not sure what that means for a collection - // TODO: fix this when HHH-6356 is fixed; for now assume AbstractPluralAttributeBinding is updatable and insertable - //alwaysDirtyCheck || pluralAttributeBinding.isUpdatable(), - true, + true, // plural attributes are nullable + alwaysDirtyCheck || pluralAttributeBinding.getPluralAttributeKeyBinding().isUpdatable(), pluralAttributeBinding.isIncludedInOptimisticLocking(), cascadeStyle, fetchMode - ); - } - } - - private static boolean areAllValuesIncludedInUpdate(SingularAttributeBinding attributeBinding) { - if ( attributeBinding.hasDerivedValue() ) { - return false; - } - for ( SimpleValueBinding valueBinding : attributeBinding.getSimpleValueBindings() ) { - if ( ! valueBinding.isIncludeInUpdate() ) { - return false; - } + ); } - return true; } private static Constructor getConstructor(PersistentClass persistentClass) { @@ -475,13 +650,17 @@ private static Constructor getConstructor(PersistentClass persistentClass) { } } - private static Constructor getConstructor(EntityBinding entityBinding) { + private static Constructor getConstructor(EntityBinding entityBinding, ClassLoaderService cls) { if ( entityBinding == null || entityBinding.getEntity() == null ) { return null; } try { - return ReflectHelper.getDefaultConstructor( entityBinding.getEntity().getClassReference() ); + return ReflectHelper.getDefaultConstructor( + cls.classForName( + entityBinding.getEntity().getDescriptor().getName().toString() + ) + ); } catch( Throwable t ) { return null; @@ -497,14 +676,20 @@ private static Getter getGetter(Property mappingProperty) { return pa.getGetter( mappingProperty.getPersistentClass().getMappedClass(), mappingProperty.getName() ); } - private static Getter getGetter(AttributeBinding mappingProperty) { - if ( mappingProperty == null || mappingProperty.getContainer().getClassReference() == null ) { + private static Getter getGetter(AttributeBinding mappingProperty, SessionFactoryImplementor sessionFactory) { + final EntityMode entityMode = + mappingProperty.getContainer().seekEntityBinding().getHierarchyDetails().getEntityMode(); + if ( mappingProperty == null || entityMode != EntityMode.POJO ) { return null; } - PropertyAccessor pa = PropertyAccessorFactory.getPropertyAccessor( mappingProperty, EntityMode.POJO ); + final PropertyAccessor pa = PropertyAccessorFactory.getPropertyAccessor( mappingProperty, EntityMode.POJO ); + final ClassLoaderService cls = sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ); + final Class clazz = cls.classForName( + mappingProperty.getContainer().getAttributeContainer().getDescriptor().getName().toString() + ); return pa.getGetter( - mappingProperty.getContainer().getClassReference(), + clazz, mappingProperty.getAttribute().getName() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java index 14158a7b2550..ce211402d638 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java @@ -23,15 +23,17 @@ * */ package org.hibernate.tuple.component; + import java.lang.reflect.Method; -import java.util.Iterator; import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; /** @@ -41,37 +43,96 @@ * @author Steve Ebersole */ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { - protected final Getter[] getters; - protected final Setter[] setters; - protected final int propertySpan; - protected final Instantiator instantiator; - protected final boolean hasCustomAccessors; - - protected abstract Instantiator buildInstantiator(Component component); - protected abstract Getter buildGetter(Component component, Property prop); - protected abstract Setter buildSetter(Component component, Property prop); - - protected AbstractComponentTuplizer(Component component) { - propertySpan = component.getPropertySpan(); + private final ServiceRegistry serviceRegistry; + + private final Getter[] getters; + private final Setter[] setters; + private final int propertySpan; + private final Instantiator instantiator; + private final boolean hasCustomAccessors; + + protected AbstractComponentTuplizer( + ServiceRegistry serviceRegistry, + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper) { + // TODO: Get rid of the need for isIdentifierMapper arg. + // Instead the EmbeddedAttributeBinding should be wrapped (e.g., by a proxy) + // so it can provide the information needed to create getters and setters + // for an identifier mapper. + + this.serviceRegistry = serviceRegistry; + + propertySpan = embeddableBinding.attributeBindingSpan(); getters = new Getter[propertySpan]; setters = new Setter[propertySpan]; - Iterator iter = component.getPropertyIterator(); - boolean foundCustomAccessor=false; + boolean foundCustomAccessor = false; + int i = 0; - while ( iter.hasNext() ) { - Property prop = ( Property ) iter.next(); - getters[i] = buildGetter( component, prop ); - setters[i] = buildSetter( component, prop ); - if ( !prop.isBasicPropertyAccessor() ) { + for ( AttributeBinding attributeBinding : embeddableBinding.attributeBindings() ) { + getters[i] = buildGetter( embeddableBinding, isIdentifierMapper, attributeBinding ); + setters[i] = buildSetter( embeddableBinding, isIdentifierMapper, attributeBinding ); + if ( !attributeBinding.isBasicPropertyAccessor() ) { foundCustomAccessor = true; } i++; } hasCustomAccessors = foundCustomAccessor; - instantiator = buildInstantiator( component ); + instantiator = buildInstantiator( embeddableBinding, isIdentifierMapper ); + } + + protected ServiceRegistry serviceRegistry() { + return serviceRegistry; + } + + protected Getter[] getters() { + return getters; + } + + protected Setter[] setters() { + return setters; + } + + protected int propertySpan() { + return propertySpan; } + protected Instantiator instantiator() { + return instantiator; + } + + protected boolean hasCustomAccessors() { + return hasCustomAccessors; + } + + private ClassLoaderService classLoaderService; + + protected Class classForName(String name) { + if ( classLoaderService == null ) { + classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + } + + return classLoaderService.classForName( name ); + } + + protected abstract Instantiator buildInstantiator( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper + ); + + protected abstract Getter buildGetter( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + AttributeBinding attributeBinding + ); + + protected abstract Setter buildSetter( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + AttributeBinding attributeBinding + ); + + public Object getPropertyValue(Object component, int i) throws HibernateException { return getters[i].get( component ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java index 8b40ca7df9c7..2681c49b2f20 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java @@ -122,7 +122,7 @@ public AttributeDefinition next() { ) ); } - else if ( aType.getForeignKeyDirection() == ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) { + else if ( aType.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT ) { final String lhsTableName; final String[] lhsColumnNames; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java index aab4c71c0870..979af15ef624 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java @@ -26,13 +26,13 @@ import java.io.Serializable; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import org.hibernate.EntityMode; import org.hibernate.HibernateException; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.PropertyFactory; import org.hibernate.tuple.StandardProperty; @@ -42,10 +42,6 @@ * @author Steve Ebersole */ public class ComponentMetamodel implements Serializable { - - // TODO : will need reference to session factory to fully complete HHH-1907 - -// private final SessionFactoryImplementor sessionFactory; private final String role; private final boolean isKey; private final StandardProperty[] properties; @@ -57,31 +53,37 @@ public class ComponentMetamodel implements Serializable { private final int propertySpan; private final Map propertyIndexes = new HashMap(); -// public ComponentMetamodel(Component component, SessionFactoryImplementor sessionFactory) { - public ComponentMetamodel(Component component) { -// this.sessionFactory = sessionFactory; - this.role = component.getRoleName(); - this.isKey = component.isKey(); - propertySpan = component.getPropertySpan(); + public ComponentMetamodel( + ServiceRegistry serviceRegistry, + EmbeddableBinding component, + boolean isIdentifierAttributeBinding, + boolean isIdentifierMapper) { + this.isKey = isIdentifierAttributeBinding; + this.role = component.getPathBase().getFullPath(); + propertySpan = component.attributeBindingSpan(); properties = new StandardProperty[propertySpan]; - Iterator itr = component.getPropertyIterator(); int i = 0; - while ( itr.hasNext() ) { - Property property = ( Property ) itr.next(); - properties[i] = PropertyFactory.buildStandardProperty( property, false ); - propertyIndexes.put( property.getName(), i ); + for ( AttributeBinding attributeBinding : component.attributeBindings() ) { + properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, false ); + propertyIndexes.put( attributeBinding.getAttribute().getName(), i ); i++; } - entityMode = component.hasPojoRepresentation() ? EntityMode.POJO : EntityMode.MAP; + entityMode = component.seekEntityBinding().getHierarchyDetails().getEntityMode(); // todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel final ComponentTuplizerFactory componentTuplizerFactory = new ComponentTuplizerFactory(); - final String tuplizerClassName = component.getTuplizerImplClassName( entityMode ); - this.componentTuplizer = tuplizerClassName == null ? componentTuplizerFactory.constructDefaultTuplizer( - entityMode, - component - ) : componentTuplizerFactory.constructTuplizer( tuplizerClassName, component ); + final Class tuplizerClass = component.getCustomTuplizerClass(); + if ( tuplizerClass == null ) { + componentTuplizer = componentTuplizerFactory.constructDefaultTuplizer( + entityMode, serviceRegistry, component, isIdentifierMapper + ); + } + else { + componentTuplizer = componentTuplizerFactory.constructTuplizer( + tuplizerClass, serviceRegistry, component, isIdentifierMapper + ); + } } public boolean isKey() { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java index 9a117622a2a1..8262a7ef345b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizer.java @@ -33,9 +33,12 @@ * Defines further responsibilities regarding tuplization based on * a mapped components. *

    - * ComponentTuplizer implementations should have the following constructor signature: - * (org.hibernate.mapping.Component) - * + * ComponentTuplizer implementations should have the following constructor with the following arguments:
      + *
    1. {@link org.hibernate.service.ServiceRegistry}
    2. + *
    3. {@link org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding}
    4. + *
    5. boolean (whether the composite is a mapped identifier)
    6. + *
    + * * @author Gavin King * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java index c912708b3ae6..2947f4d9d5ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java @@ -25,13 +25,12 @@ import java.io.Serializable; import java.lang.reflect.Constructor; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.mapping.Component; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.service.ServiceRegistry; /** * A registry allowing users to define the default {@link ComponentTuplizer} class to use per {@link EntityMode}. @@ -39,25 +38,11 @@ * @author Steve Ebersole */ public class ComponentTuplizerFactory implements Serializable { - private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class }; - - private Map> defaultImplClassByMode = buildBaseMapping(); - - /** - * Method allowing registration of the tuplizer class to use as default for a particular entity-mode. - * - * @param entityMode The entity-mode for which to register the tuplizer class - * @param tuplizerClass The class to use as the default tuplizer for the given entity-mode. - */ - @SuppressWarnings({ "UnusedDeclaration" }) - public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) { - assert isComponentTuplizerImplementor( tuplizerClass ) - : "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + ComponentTuplizer.class.getName(); - assert hasProperConstructor( tuplizerClass ) - : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; - - defaultImplClassByMode.put( entityMode, tuplizerClass ); - } + private static final Class[] COMPONENT_TUP_CTOR_SIG_NEW = new Class[] { + ServiceRegistry.class, + EmbeddableBinding.class, + boolean.class + }; /** * Construct an instance of the given tuplizer class. @@ -71,16 +56,30 @@ assert hasProperConstructor( tuplizerClass ) * {@link Constructor#newInstance} call fails. */ @SuppressWarnings({ "unchecked" }) - public ComponentTuplizer constructTuplizer(String tuplizerClassName, Component metadata) { + public ComponentTuplizer constructTuplizer( + ServiceRegistry serviceRegistry, + String tuplizerClassName, + EmbeddableBinding metadata, + boolean isIdentifierMapper) { try { - Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName ); - return constructTuplizer( tuplizerClass, metadata ); + final Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName ); + assert isComponentTuplizerImplementor( tuplizerClass ) : "Specified ComponentTuplizer class does not implement ComponentTuplizer"; + + return constructTuplizer( tuplizerClass, serviceRegistry, metadata, isIdentifierMapper ); } catch ( ClassNotFoundException e ) { throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" ); } } + private boolean isComponentTuplizerImplementor(Class tuplizerClass) { + return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class ); + } + + private boolean hasProperConstructor(Class tuplizerClass) { + return getProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG_NEW ) != null; + } + /** * Construct an instance of the given tuplizer class. * @@ -91,11 +90,19 @@ public ComponentTuplizer constructTuplizer(String tuplizerClassName, Component m * * @throws HibernateException if the {@link java.lang.reflect.Constructor#newInstance} call fails. */ - public ComponentTuplizer constructTuplizer(Class tuplizerClass, Component metadata) { - Constructor constructor = getProperConstructor( tuplizerClass ); - assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; + public ComponentTuplizer constructTuplizer( + Class tuplizerClass, + ServiceRegistry serviceRegistry, + EmbeddableBinding metadata, + boolean isIdentifierMapper) { + final Constructor constructor = getProperConstructor( + tuplizerClass, + COMPONENT_TUP_CTOR_SIG_NEW + ); + assert hasProperConstructor( tuplizerClass ) : "Specified ComponentTuplizer class [" + tuplizerClass + "] did not have proper constructor"; + try { - return constructor.newInstance( metadata ); + return constructor.newInstance( serviceRegistry, metadata, isIdentifierMapper ); } catch ( Throwable t ) { throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t ); @@ -113,36 +120,40 @@ public ComponentTuplizer constructTuplizer(Class tu * @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from * {@link #constructTuplizer} too. */ - public ComponentTuplizer constructDefaultTuplizer(EntityMode entityMode, Component metadata) { - Class tuplizerClass = defaultImplClassByMode.get( entityMode ); - if ( tuplizerClass == null ) { - throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" ); - } - - return constructTuplizer( tuplizerClass, metadata ); - } - - private boolean isComponentTuplizerImplementor(Class tuplizerClass) { - return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class ); + public ComponentTuplizer constructDefaultTuplizer( + EntityMode entityMode, + ServiceRegistry serviceRegistry, + EmbeddableBinding metadata, + boolean isIdentifierMapper) { + final Class tuplizerClass = determineTuplizerClass( entityMode ); + return constructTuplizer( tuplizerClass, serviceRegistry, metadata, isIdentifierMapper ); } - @SuppressWarnings({ "unchecked" }) - private boolean hasProperConstructor(Class tuplizerClass) { - return getProperConstructor( tuplizerClass ) != null; + private Class determineTuplizerClass(EntityMode entityMode) { + switch ( entityMode ) { + case MAP: { + return DynamicMapComponentTuplizer.class; + } + case POJO: { + return PojoComponentTuplizer.class; + } + default: { + throw new IllegalArgumentException( "Unknown EntityMode : " + entityMode ); + } + } } - private Constructor getProperConstructor(Class clazz) { + private Constructor getProperConstructor( + Class clazz, + Class[] clazzConstructorSignature) { Constructor constructor = null; try { - constructor = clazz.getDeclaredConstructor( COMPONENT_TUP_CTOR_SIG ); - if ( ! ReflectHelper.isPublic( constructor ) ) { - try { - // found a constructor, but it was not publicly accessible so try to request accessibility - constructor.setAccessible( true ); - } - catch ( SecurityException e ) { - constructor = null; - } + constructor = clazz.getDeclaredConstructor( clazzConstructorSignature ); + try { + constructor.setAccessible( true ); + } + catch ( SecurityException e ) { + constructor = null; } } catch ( NoSuchMethodException ignore ) { @@ -150,11 +161,4 @@ private Constructor getProperConstructor(Class> buildBaseMapping() { - Map> map = new ConcurrentHashMap>(); - map.put( EntityMode.POJO, PojoComponentTuplizer.class ); - map.put( EntityMode.MAP, DynamicMapComponentTuplizer.class ); - return map; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java index c26b346e026c..595a72fdef73 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java @@ -25,12 +25,13 @@ package org.hibernate.tuple.component; import java.util.Map; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.DynamicMapInstantiator; import org.hibernate.tuple.Instantiator; @@ -41,29 +42,43 @@ * @author Steve Ebersole */ public class DynamicMapComponentTuplizer extends AbstractComponentTuplizer { + public DynamicMapComponentTuplizer( + ServiceRegistry serviceRegistry, + EmbeddableBinding component, + boolean isIdentifierMapper) { + super( serviceRegistry, component, isIdentifierMapper ); + } + @Override public Class getMappedClass() { return Map.class; } - protected Instantiator buildInstantiator(Component component) { - return new DynamicMapInstantiator(); - } - - public DynamicMapComponentTuplizer(Component component) { - super(component); + private PropertyAccessor buildPropertyAccessor() { + return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); } - private PropertyAccessor buildPropertyAccessor(Property property) { - return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); + @Override + protected Instantiator buildInstantiator( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper) { + return new DynamicMapInstantiator(); } - protected Getter buildGetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getGetter( null, prop.getName() ); + @Override + protected Getter buildGetter( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + return buildPropertyAccessor().getGetter( null, attributeBinding.getAttribute().getName() ); } - protected Setter buildSetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getSetter( null, prop.getName() ); + @Override + protected Setter buildSetter( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + return buildPropertyAccessor().getSetter( null, attributeBinding.getAttribute().getName() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java index a9b0d5a9cfac..d7d4c573b446 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java @@ -23,23 +23,29 @@ * */ package org.hibernate.tuple.component; + import java.io.Serializable; import java.lang.reflect.Method; import org.hibernate.AssertionFailure; +import org.hibernate.EntityMode; import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.bytecode.spi.BasicProxyFactory; import org.hibernate.bytecode.spi.ReflectionOptimizer; import org.hibernate.cfg.Environment; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.PojoInstantiator; @@ -55,21 +61,36 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { private final Getter parentGetter; private final Setter parentSetter; - public PojoComponentTuplizer(Component component) { - super( component ); + public PojoComponentTuplizer( + ServiceRegistry serviceRegistry, + EmbeddableBinding component, + boolean isIdentifierMapper) { + super( serviceRegistry, component, isIdentifierMapper ); + + final EntityIdentifier entityIdentifier = + component.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); - this.componentClass = component.getComponentClass(); + if ( isIdentifierMapper ) { + this.componentClass = entityIdentifier.getLookupClassBinding().getIdClassType(); + } + else { + final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class ); + this.componentClass = cls.classForName( + component.getAttributeContainer().getDescriptor().getName().toString() + ); + } - String[] getterNames = new String[propertySpan]; - String[] setterNames = new String[propertySpan]; - Class[] propTypes = new Class[propertySpan]; - for ( int i = 0; i < propertySpan; i++ ) { - getterNames[i] = getters[i].getMethodName(); - setterNames[i] = setters[i].getMethodName(); - propTypes[i] = getters[i].getReturnType(); + String[] getterNames = new String[ propertySpan() ]; + String[] setterNames = new String[ propertySpan() ]; + Class[] propTypes = new Class[ propertySpan() ]; + for ( int i = 0; i < propertySpan(); i++ ) { + getterNames[i] = getters()[i].getMethodName(); + setterNames[i] = setters()[i].getMethodName(); + propTypes[i] = getters()[i].getReturnType(); } - final String parentPropertyName = component.getParentProperty(); + final String parentPropertyName = + component.getParentReference() == null ? null : component.getParentReference().getName(); if ( parentPropertyName == null ) { parentSetter = null; parentGetter = null; @@ -80,7 +101,7 @@ public PojoComponentTuplizer(Component component) { parentGetter = pa.getGetter( componentClass, parentPropertyName ); } - if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) { + if ( hasCustomAccessors() || !Environment.useReflectionOptimizer() ) { optimizer = null; } else { @@ -98,7 +119,7 @@ public Class getMappedClass() { public Object[] getPropertyValues(Object component) throws HibernateException { if ( component == BackrefPropertyAccessor.UNKNOWN ) { - return new Object[propertySpan]; + return new Object[propertySpan()]; } else if ( optimizer != null && optimizer.getAccessOptimizer() != null ) { return optimizer.getAccessOptimizer().getPropertyValues( component ); @@ -126,8 +147,8 @@ public boolean hasParentProperty() { } public boolean isMethodOf(Method method) { - for ( int i = 0; i < propertySpan; i++ ) { - final Method getterMethod = getters[i].getMethod(); + for ( int i = 0; i < propertySpan(); i++ ) { + final Method getterMethod = getters()[i].getMethod(); if ( getterMethod != null && getterMethod.equals( method ) ) { return true; } @@ -139,24 +160,103 @@ public void setParent(Object component, Object parent, SessionFactoryImplementor parentSetter.set( component, parent, factory ); } - protected Instantiator buildInstantiator(Component component) { - if ( component.isEmbedded() && ReflectHelper.isAbstractClass( component.getComponentClass() ) ) { - return new ProxiedInstantiator( component ); + @Override + protected Instantiator buildInstantiator( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper) { + final Class clazz = classForName( + embeddableBinding.getAttributeContainer().getDescriptor().getName().toString() + ); + + if ( !embeddableBinding.isAggregated() && ReflectHelper.isAbstractClass( clazz ) ) { + return new ProxiedInstantiator( clazz ); } + if ( optimizer == null ) { - return new PojoInstantiator( component, null ); + return new PojoInstantiator( + serviceRegistry(), + embeddableBinding, + isIdentifierMapper, + null + ); + } + else { + return new PojoInstantiator( + serviceRegistry(), + embeddableBinding, + isIdentifierMapper, + optimizer.getInstantiationOptimizer() + ); + } + } + + @Override + protected Getter buildGetter( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + // TODO: when compositeAttributeBinding is wrapped for an identifier mapper + // there will be no need for PropertyFactory.getIdentifierMapperGetter() + // and PropertyFactory.getIdentifierMapperSetter + if ( isIdentifierMapper ) { + // HACK ALERT: when isIdentifierMapper is true, the entity identifier + // must be completely bound when this method is called. + final EntityIdentifier entityIdentifier = + embeddableBinding.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + return getGetter( + entityIdentifier.getLookupClassBinding().getIdClassType(), + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( entityIdentifier.getLookupClassBinding().getAccessStrategy() ) + ); } else { - return new PojoInstantiator( component, optimizer.getInstantiationOptimizer() ); + final ClassLoaderService cls = serviceRegistry().getService( ClassLoaderService.class ); + final Class clazz = cls.classForName( + embeddableBinding.getAttributeContainer().getDescriptor().getName().toString() + ); + return getGetter( + clazz, + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( attributeBinding, EntityMode.POJO ) + ); } } - protected Getter buildGetter(Component component, Property prop) { - return prop.getGetter( component.getComponentClass() ); + @Override + protected Setter buildSetter( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper, + AttributeBinding attributeBinding) { + if ( isIdentifierMapper ) { + // HACK ALERT: when isIdentifierMapper is true, the entity identifier + // must be completely bound when this method is called. + final EntityIdentifier entityIdentifier = + embeddableBinding.seekEntityBinding().getHierarchyDetails().getEntityIdentifier(); + return getSetter( + entityIdentifier.getLookupClassBinding().getIdClassType(), + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( entityIdentifier.getLookupClassBinding().getAccessStrategy() ) + ); + + } + else { + final Class clazz = classForName( + embeddableBinding.getAttributeContainer().getDescriptor().getName().toString() + ); + return getSetter( + clazz, + attributeBinding.getAttribute().getName(), + PropertyAccessorFactory.getPropertyAccessor( attributeBinding, EntityMode.POJO ) + ); + } + } + + private Getter getGetter(Class clazz, String name, PropertyAccessor propertyAccessor) { + return propertyAccessor.getGetter( clazz, name ); } - protected Setter buildSetter(Component component, Property prop) { - return prop.getSetter( component.getComponentClass() ); + private Setter getSetter(Class clazz, String name, PropertyAccessor propertyAccessor) { + return propertyAccessor.getSetter(clazz, name); } private static class ProxiedInstantiator implements Instantiator { @@ -164,7 +264,11 @@ private static class ProxiedInstantiator implements Instantiator { private final BasicProxyFactory factory; public ProxiedInstantiator(Component component) { - proxiedClass = component.getComponentClass(); + this( component.getComponentClass() ); + } + + private ProxiedInstantiator(Class proxiedClass) { + this.proxiedClass = proxiedClass; if ( proxiedClass.isInterface() ) { factory = Environment.getBytecodeProvider() .getProxyFactoryFactory() @@ -177,6 +281,7 @@ public ProxiedInstantiator(Component component) { } } + public Object instantiate(Serializable id) { throw new AssertionFailure( "ProxiedInstantiator can only be used to instantiate component" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java index 55546ccd941d..8813ebaaa5b3 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java @@ -24,13 +24,13 @@ package org.hibernate.tuple.entity; import java.io.Serializable; -import java.util.Iterator; import java.util.Map; import java.util.Set; import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; @@ -43,17 +43,17 @@ import org.hibernate.event.spi.PersistEvent; import org.hibernate.event.spi.PersistEventListener; import org.hibernate.id.Assigned; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.loader.PropertyPath; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.ProxyFactory; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.NonIdentifierAttribute; import org.hibernate.type.ComponentType; @@ -61,8 +61,6 @@ import org.hibernate.type.EntityType; import org.hibernate.type.Type; -import org.jboss.logging.Logger; - /** * Support for tuplizers relating to entities. @@ -71,14 +69,9 @@ * @author Gavin King */ public abstract class AbstractEntityTuplizer implements EntityTuplizer { + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractEntityTuplizer.class ); - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - AbstractEntityTuplizer.class.getName() - ); - - //TODO: currently keeps Getters and Setters (instead of PropertyAccessors) because of the way getGetter() and getSetter() are implemented currently; yuck! - + private final ServiceRegistry serviceRegistry; private final EntityMetamodel entityMetamodel; private final Getter idGetter; @@ -92,94 +85,19 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { private final ProxyFactory proxyFactory; private final CompositeType identifierMapperType; - public Type getIdentifierMapperType() { - return identifierMapperType; - } - - /** - * Build an appropriate Getter for the given property. - * - * @param mappedProperty The property to be accessed via the built Getter. - * @param mappedEntity The entity information regarding the mapped entity owning this property. - * @return An appropriate Getter instance. - */ - protected abstract Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity); - - /** - * Build an appropriate Setter for the given property. - * - * @param mappedProperty The property to be accessed via the built Setter. - * @param mappedEntity The entity information regarding the mapped entity owning this property. - * @return An appropriate Setter instance. - */ - protected abstract Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity); - - /** - * Build an appropriate Instantiator for the given mapped entity. - * - * @param mappingInfo The mapping information regarding the mapped entity. - * @return An appropriate Instantiator instance. - */ - protected abstract Instantiator buildInstantiator(PersistentClass mappingInfo); - - /** - * Build an appropriate ProxyFactory for the given mapped entity. - * - * @param mappingInfo The mapping information regarding the mapped entity. - * @param idGetter The constructed Getter relating to the entity's id property. - * @param idSetter The constructed Setter relating to the entity's id property. - * @return An appropriate ProxyFactory instance. - */ - protected abstract ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter); - - /** - * Build an appropriate Getter for the given property. - * - * - * @param mappedProperty The property to be accessed via the built Getter. - * @return An appropriate Getter instance. - */ - protected abstract Getter buildPropertyGetter(AttributeBinding mappedProperty); - - /** - * Build an appropriate Setter for the given property. - * - * - * @param mappedProperty The property to be accessed via the built Setter. - * @return An appropriate Setter instance. - */ - protected abstract Setter buildPropertySetter(AttributeBinding mappedProperty); - - /** - * Build an appropriate Instantiator for the given mapped entity. - * - * @param mappingInfo The mapping information regarding the mapped entity. - * @return An appropriate Instantiator instance. - */ - protected abstract Instantiator buildInstantiator(EntityBinding mappingInfo); - - /** - * Build an appropriate ProxyFactory for the given mapped entity. - * - * @param mappingInfo The mapping information regarding the mapped entity. - * @param idGetter The constructed Getter relating to the entity's id property. - * @param idSetter The constructed Setter relating to the entity's id property. - * @return An appropriate ProxyFactory instance. - */ - protected abstract ProxyFactory buildProxyFactory(EntityBinding mappingInfo, Getter idGetter, Setter idSetter); - /** * Constructs a new AbstractEntityTuplizer instance. * * @param entityMetamodel The "interpreted" information relating to the mapped entity. * @param mappingInfo The parsed "raw" mapping data relating to the given entity. */ - public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) { + public AbstractEntityTuplizer(ServiceRegistry serviceRegistry, EntityMetamodel entityMetamodel, EntityBinding mappingInfo) { + this.serviceRegistry = serviceRegistry; this.entityMetamodel = entityMetamodel; if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { - idGetter = buildPropertyGetter( mappingInfo.getIdentifierProperty(), mappingInfo ); - idSetter = buildPropertySetter( mappingInfo.getIdentifierProperty(), mappingInfo ); + idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); } else { idGetter = null; @@ -188,29 +106,27 @@ public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass m propertySpan = entityMetamodel.getPropertySpan(); - getters = new Getter[propertySpan]; - setters = new Setter[propertySpan]; + getters = new Getter[ propertySpan ]; + setters = new Setter[ propertySpan ]; - Iterator itr = mappingInfo.getPropertyClosureIterator(); - boolean foundCustomAccessor=false; - int i=0; - while ( itr.hasNext() ) { + boolean foundCustomAccessor = false; + int i = 0; + for ( AttributeBinding property : mappingInfo.getNonIdAttributeBindingClosure() ) { //TODO: redesign how PropertyAccessors are acquired... - Property property = (Property) itr.next(); - getters[i] = buildPropertyGetter(property, mappingInfo); - setters[i] = buildPropertySetter(property, mappingInfo); - if ( !property.isBasicPropertyAccessor() ) { + getters[ i ] = buildPropertyGetter( property ); + setters[ i ] = buildPropertySetter( property ); + if ( ! property.isBasicPropertyAccessor() ) { foundCustomAccessor = true; } i++; } hasCustomAccessors = foundCustomAccessor; - instantiator = buildInstantiator( mappingInfo ); + instantiator = buildInstantiator( mappingInfo ); if ( entityMetamodel.isLazy() ) { proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter ); - if (proxyFactory == null) { + if ( proxyFactory == null ) { entityMetamodel.setLazy( false ); } } @@ -218,88 +134,81 @@ public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass m proxyFactory = null; } - Component mapper = mappingInfo.getIdentifierMapper(); - if ( mapper == null ) { + final EntityIdentifier entityIdentifier = mappingInfo.getHierarchyDetails().getEntityIdentifier(); + if ( !entityIdentifier.isIdentifierMapper() ) { identifierMapperType = null; mappedIdentifierValueMarshaller = null; } else { - identifierMapperType = (CompositeType) mapper.getType(); + identifierMapperType = (CompositeType) entityMetamodel.getIdentifierProperty().getType(); + + // TODO: this only deals with normal IdClass; still need to deal with MapsId mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller( - (ComponentType) entityMetamodel.getIdentifierProperty().getType(), - (ComponentType) identifierMapperType + (ComponentType) identifierMapperType, + (ComponentType) mappingInfo + .getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping() ); } } - /** - * Constructs a new AbstractEntityTuplizer instance. - * - * @param entityMetamodel The "interpreted" information relating to the mapped entity. - * @param mappingInfo The parsed "raw" mapping data relating to the given entity. - */ - public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappingInfo) { - this.entityMetamodel = entityMetamodel; + private ClassLoaderService classLoaderService; - if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { - idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - } - else { - idGetter = null; - idSetter = null; + protected Class classForName(String name) { + if ( classLoaderService == null ) { + classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); } - propertySpan = entityMetamodel.getPropertySpan(); + return classLoaderService.classForName( name ); + } - getters = new Getter[ propertySpan ]; - setters = new Setter[ propertySpan ]; - boolean foundCustomAccessor = false; - int i = 0; - for ( AttributeBinding property : mappingInfo.getAttributeBindingClosure() ) { - if ( property == mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { - continue; // ID binding processed above - } + protected ServiceRegistry serviceRegistry() { + return serviceRegistry; + } - //TODO: redesign how PropertyAccessors are acquired... - getters[ i ] = buildPropertyGetter( property ); - setters[ i ] = buildPropertySetter( property ); - if ( ! property.isBasicPropertyAccessor() ) { - foundCustomAccessor = true; - } - i++; - } - hasCustomAccessors = foundCustomAccessor; + public Type getIdentifierMapperType() { + return identifierMapperType; + } - instantiator = buildInstantiator( mappingInfo ); + /** + * Build an appropriate Getter for the given property. + * + * + * @param mappedProperty The property to be accessed via the built Getter. + * @return An appropriate Getter instance. + */ + protected abstract Getter buildPropertyGetter(AttributeBinding mappedProperty); - if ( entityMetamodel.isLazy() ) { - proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter ); - if ( proxyFactory == null ) { - entityMetamodel.setLazy( false ); - } - } - else { - proxyFactory = null; - } + /** + * Build an appropriate Setter for the given property. + * + * + * @param mappedProperty The property to be accessed via the built Setter. + * @return An appropriate Setter instance. + */ + protected abstract Setter buildPropertySetter(AttributeBinding mappedProperty); + /** + * Build an appropriate Instantiator for the given mapped entity. + * + * @param mappingInfo The mapping information regarding the mapped entity. + * @return An appropriate Instantiator instance. + */ + protected abstract Instantiator buildInstantiator(EntityBinding mappingInfo); - // TODO: Fix this when components are working (HHH-6173) - //Component mapper = mappingInfo.getEntityIdentifier().getIdentifierMapper(); - Component mapper = null; - if ( mapper == null ) { - identifierMapperType = null; - mappedIdentifierValueMarshaller = null; - } - else { - identifierMapperType = ( CompositeType ) mapper.getType(); - mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller( - ( ComponentType ) entityMetamodel.getIdentifierProperty().getType(), - ( ComponentType ) identifierMapperType - ); - } - } + /** + * Build an appropriate ProxyFactory for the given mapped entity. + * + * @param mappingInfo The mapping information regarding the mapped entity. + * @param idGetter The constructed Getter relating to the entity's id property. + * @param idSetter The constructed Setter relating to the entity's id property. + * @return An appropriate ProxyFactory instance. + */ + protected abstract ProxyFactory buildProxyFactory(EntityBinding mappingInfo, Getter idGetter, Setter idSetter); /** Retreives the defined entity-name for the tuplized entity. * @@ -327,7 +236,10 @@ public Serializable getIdentifier(Object entity) throws HibernateException { @Override public Serializable getIdentifier(Object entity, SessionImplementor session) { final Object id; - if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { + if ( identifierMapperType != null ) { + id = mappedIdentifierValueMarshaller.getIdentifier( entity, getEntityMode(), session ); + } + else if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { id = entity; } else if ( HibernateProxy.class.isInstance( entity ) ) { @@ -335,12 +247,7 @@ else if ( HibernateProxy.class.isInstance( entity ) ) { } else { if ( idGetter == null ) { - if (identifierMapperType==null) { - throw new HibernateException( "The class has no identifier property: " + getEntityName() ); - } - else { - id = mappedIdentifierValueMarshaller.getIdentifier( entity, getEntityMode(), session ); - } + throw new HibernateException( "The class has no identifier property: " + getEntityName() ); } else { id = idGetter.get( entity ); @@ -371,7 +278,10 @@ public void setIdentifier(Object entity, Serializable id) throws HibernateExcept @Override public void setIdentifier(Object entity, Serializable id, SessionImplementor session) { - if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { + if ( identifierMapperType != null && identifierMapperType.getReturnedClass().isInstance( id ) ) { + mappedIdentifierValueMarshaller.setIdentifier( entity, id, getEntityMode(), session ); + } + else if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { if ( entity != id ) { CompositeType copier = (CompositeType) entityMetamodel.getIdentifierProperty().getType(); copier.setPropertyValues( entity, copier.getPropertyValues( id, getEntityMode() ), getEntityMode() ); @@ -380,8 +290,11 @@ public void setIdentifier(Object entity, Serializable id, SessionImplementor ses else if ( idSetter != null ) { idSetter.set( entity, id, getFactory() ); } - else if ( identifierMapperType != null ) { - mappedIdentifierValueMarshaller.setIdentifier( entity, id, getEntityMode(), session ); + else { + throw new IllegalArgumentException( + "Could not determine how to set given value [" + id + + "] as identifier value for entity [" + getEntityName() + "]" + ); } } @@ -677,7 +590,7 @@ protected Object getComponentValue(ComponentType type, Object component, String ? propertyPath.substring( 0, loc ) : propertyPath; final int index = findSubPropertyIndex( type, basePropertyName ); - final Object baseValue = type.getPropertyValue( component, index, getEntityMode() ); + final Object baseValue = type.getPropertyValue( component, index ); if ( loc > 0 ) { if ( baseValue == null ) { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java index 7e376d62b58c..f5b33d1c1fcd 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java @@ -31,16 +31,16 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; import org.hibernate.proxy.map.MapProxyFactory; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.DynamicMapInstantiator; import org.hibernate.tuple.Instantiator; @@ -53,12 +53,8 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DynamicMapEntityTuplizer.class ); - DynamicMapEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super(entityMetamodel, mappedEntity); - } - - DynamicMapEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { - super(entityMetamodel, mappedEntity); + DynamicMapEntityTuplizer(ServiceRegistry serviceRegistry, EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { + super( serviceRegistry, entityMetamodel, mappedEntity ); } @Override @@ -66,65 +62,18 @@ public EntityMode getEntityMode() { return EntityMode.MAP; } - private PropertyAccessor buildPropertyAccessor(Property mappedProperty) { - if ( mappedProperty.isBackRef() ) { - return mappedProperty.getPropertyAccessor(null); - } - else { - return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); - } - } - - @Override - protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { - return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getName() ); - } - @Override - protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { - return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getName() ); - } - - @Override - protected Instantiator buildInstantiator(PersistentClass mappingInfo) { - return new DynamicMapInstantiator( mappingInfo ); - } - - @Override - protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) { - - ProxyFactory pf = new MapProxyFactory(); - try { - //TODO: design new lifecycle for ProxyFactory - pf.postInstantiate( - getEntityName(), - null, - null, - null, - null, - null - ); - } - catch ( HibernateException he ) { - LOG.unableToCreateProxyFactory( getEntityName(), he ); - pf = null; - } - return pf; + protected Getter buildPropertyGetter(AttributeBinding mappedProperty) { + return buildPropertyAccessor( mappedProperty ).getGetter( null, mappedProperty.getAttribute().getName() ); } private PropertyAccessor buildPropertyAccessor(AttributeBinding mappedProperty) { - // TODO: fix when backrefs are working in new metamodel - //if ( mappedProperty.isBackRef() ) { - // return mappedProperty.getPropertyAccessor( null ); - //} - //else { + if ( mappedProperty.isBackRef() ) { + return null; + } + else { return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); - //} - } - - @Override - protected Getter buildPropertyGetter(AttributeBinding mappedProperty) { - return buildPropertyAccessor( mappedProperty ).getGetter( null, mappedProperty.getAttribute().getName() ); + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java index 3e1092e387da..04f3c11023b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedAssociationAttribute.java @@ -93,7 +93,7 @@ public AssociationKey getAssociationKey() { final Joinable joinable = type.getAssociatedJoinable( sessionFactory() ); - if ( type.getForeignKeyDirection() == ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) { + if ( type.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT ) { final String lhsTableName; final String[] lhsColumnNames; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index a0fc8724c2fc..2f85ae0cc059 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -36,6 +36,7 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.bytecode.spi.EntityInstrumentationMetadata; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NotYetImplementedException; @@ -48,13 +49,15 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.domain.Attribute; -import org.hibernate.metamodel.domain.SingularAttribute; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.IdentifierProperty; @@ -149,263 +152,6 @@ public class EntityMetamodel implements Serializable { private final EntityTuplizer entityTuplizer; private final EntityInstrumentationMetadata instrumentationMetadata; - public EntityMetamodel( - PersistentClass persistentClass, - AbstractEntityPersister persister, - SessionFactoryImplementor sessionFactory) { - this.sessionFactory = sessionFactory; - this.persister = persister; - - name = persistentClass.getEntityName(); - rootName = persistentClass.getRootClass().getEntityName(); - entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name ); - - identifierAttribute = PropertyFactory.buildIdentifierAttribute( - persistentClass, - sessionFactory.getIdentifierGenerator( rootName ) - ); - - versioned = persistentClass.isVersioned(); - - instrumentationMetadata = persistentClass.hasPojoRepresentation() - ? Environment.getBytecodeProvider().getEntityInstrumentationMetadata( persistentClass.getMappedClass() ) - : new NonPojoInstrumentationMetadata( persistentClass.getEntityName() ); - - boolean hasLazy = false; - - propertySpan = persistentClass.getPropertyClosureSpan(); - properties = new NonIdentifierAttribute[propertySpan]; - List naturalIdNumbers = new ArrayList(); - // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - propertyNames = new String[propertySpan]; - propertyTypes = new Type[propertySpan]; - propertyUpdateability = new boolean[propertySpan]; - propertyInsertability = new boolean[propertySpan]; - nonlazyPropertyUpdateability = new boolean[propertySpan]; - propertyCheckability = new boolean[propertySpan]; - propertyNullability = new boolean[propertySpan]; - propertyVersionability = new boolean[propertySpan]; - propertyLaziness = new boolean[propertySpan]; - cascadeStyles = new CascadeStyle[propertySpan]; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // generated value strategies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - this.inMemoryValueGenerationStrategies = new InMemoryValueGenerationStrategy[propertySpan]; - this.inDatabaseValueGenerationStrategies = new InDatabaseValueGenerationStrategy[propertySpan]; - - boolean foundPreInsertGeneratedValues = false; - boolean foundPreUpdateGeneratedValues = false; - boolean foundPostInsertGeneratedValues = false; - boolean foundPostUpdateGeneratedValues = false; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Iterator iter = persistentClass.getPropertyClosureIterator(); - int i = 0; - int tempVersionProperty = NO_VERSION_INDX; - boolean foundCascade = false; - boolean foundCollection = false; - boolean foundMutable = false; - boolean foundNonIdentifierPropertyNamedId = false; - boolean foundInsertGeneratedValue = false; - boolean foundUpdateGeneratedValue = false; - boolean foundUpdateableNaturalIdProperty = false; - - while ( iter.hasNext() ) { - Property prop = ( Property ) iter.next(); - - if ( prop == persistentClass.getVersion() ) { - tempVersionProperty = i; - properties[i] = PropertyFactory.buildVersionProperty( - persister, - sessionFactory, - i, - prop, - instrumentationMetadata.isInstrumented() - ); - } - else { - properties[i] = PropertyFactory.buildEntityBasedAttribute( - persister, - sessionFactory, - i, - prop, - instrumentationMetadata.isInstrumented() - ); - } - - if ( prop.isNaturalIdentifier() ) { - naturalIdNumbers.add( i ); - if ( prop.isUpdateable() ) { - foundUpdateableNaturalIdProperty = true; - } - } - - if ( "id".equals( prop.getName() ) ) { - foundNonIdentifierPropertyNamedId = true; - } - - // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - boolean lazy = prop.isLazy() && instrumentationMetadata.isInstrumented(); - if ( lazy ) hasLazy = true; - propertyLaziness[i] = lazy; - - propertyNames[i] = properties[i].getName(); - propertyTypes[i] = properties[i].getType(); - propertyNullability[i] = properties[i].isNullable(); - propertyUpdateability[i] = properties[i].isUpdateable(); - propertyInsertability[i] = properties[i].isInsertable(); - propertyVersionability[i] = properties[i].isVersionable(); - nonlazyPropertyUpdateability[i] = properties[i].isUpdateable() && !lazy; - propertyCheckability[i] = propertyUpdateability[i] || - ( propertyTypes[i].isAssociationType() && ( (AssociationType) propertyTypes[i] ).isAlwaysDirtyChecked() ); - - cascadeStyles[i] = properties[i].getCascadeStyle(); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // generated value strategies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - GenerationStrategyPair pair = buildGenerationStrategyPair( sessionFactory, prop ); - inMemoryValueGenerationStrategies[i] = pair.getInMemoryStrategy(); - inDatabaseValueGenerationStrategies[i] = pair.getInDatabaseStrategy(); - - if ( pair.getInMemoryStrategy() != null ) { - final GenerationTiming timing = pair.getInMemoryStrategy().getGenerationTiming(); - if ( timing != GenerationTiming.NEVER ) { - final ValueGenerator generator = pair.getInMemoryStrategy().getValueGenerator(); - if ( generator != null ) { - // we have some level of generation indicated - if ( timing == GenerationTiming.INSERT ) { - foundPreInsertGeneratedValues = true; - } - else if ( timing == GenerationTiming.ALWAYS ) { - foundPreInsertGeneratedValues = true; - foundPreUpdateGeneratedValues = true; - } - } - } - } - if ( pair.getInDatabaseStrategy() != null ) { - final GenerationTiming timing = pair.getInDatabaseStrategy().getGenerationTiming(); - if ( timing == GenerationTiming.INSERT ) { - foundPostInsertGeneratedValues = true; - } - else if ( timing == GenerationTiming.ALWAYS ) { - foundPostInsertGeneratedValues = true; - foundPostUpdateGeneratedValues = true; - } - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - if ( properties[i].isLazy() ) { - hasLazy = true; - } - - if ( properties[i].getCascadeStyle() != CascadeStyles.NONE ) { - foundCascade = true; - } - - if ( indicatesCollection( properties[i].getType() ) ) { - foundCollection = true; - } - - if ( propertyTypes[i].isMutable() && propertyCheckability[i] ) { - foundMutable = true; - } - - mapPropertyToIndex(prop, i); - i++; - } - - if (naturalIdNumbers.size()==0) { - naturalIdPropertyNumbers = null; - hasImmutableNaturalId = false; - hasCacheableNaturalId = false; - } - else { - naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); - hasImmutableNaturalId = !foundUpdateableNaturalIdProperty; - hasCacheableNaturalId = persistentClass.getNaturalIdCacheRegionName() != null; - } - - this.hasPreInsertGeneratedValues = foundPreInsertGeneratedValues; - this.hasPreUpdateGeneratedValues = foundPreUpdateGeneratedValues; - this.hasInsertGeneratedValues = foundPostInsertGeneratedValues; - this.hasUpdateGeneratedValues = foundPostUpdateGeneratedValues; - - hasCascades = foundCascade; - hasNonIdentifierPropertyNamedId = foundNonIdentifierPropertyNamedId; - versionPropertyIndex = tempVersionProperty; - hasLazyProperties = hasLazy; - if (hasLazyProperties) LOG.lazyPropertyFetchingAvailable(name); - - lazy = persistentClass.isLazy() && ( - // TODO: this disables laziness even in non-pojo entity modes: - !persistentClass.hasPojoRepresentation() || - !ReflectHelper.isFinalClass( persistentClass.getProxyInterface() ) - ); - mutable = persistentClass.isMutable(); - if ( persistentClass.isAbstract() == null ) { - // legacy behavior (with no abstract attribute specified) - isAbstract = persistentClass.hasPojoRepresentation() && - ReflectHelper.isAbstractClass( persistentClass.getMappedClass() ); - } - else { - isAbstract = persistentClass.isAbstract().booleanValue(); - if ( !isAbstract && persistentClass.hasPojoRepresentation() && - ReflectHelper.isAbstractClass( persistentClass.getMappedClass() ) ) { - LOG.entityMappedAsNonAbstract(name); - } - } - selectBeforeUpdate = persistentClass.hasSelectBeforeUpdate(); - dynamicUpdate = persistentClass.useDynamicUpdate(); - dynamicInsert = persistentClass.useDynamicInsert(); - - polymorphic = persistentClass.isPolymorphic(); - explicitPolymorphism = persistentClass.isExplicitPolymorphism(); - inherited = persistentClass.isInherited(); - superclass = inherited ? - persistentClass.getSuperclass().getEntityName() : - null; - hasSubclasses = persistentClass.hasSubclasses(); - - optimisticLockStyle = persistentClass.getOptimisticLockStyle(); - final boolean isAllOrDirty = - optimisticLockStyle == OptimisticLockStyle.ALL - || optimisticLockStyle == OptimisticLockStyle.DIRTY; - if ( isAllOrDirty && !dynamicUpdate ) { - throw new MappingException( "optimistic-lock=all|dirty requires dynamic-update=\"true\": " + name ); - } - if ( versionPropertyIndex != NO_VERSION_INDX && isAllOrDirty ) { - throw new MappingException( "version and optimistic-lock=all|dirty are not a valid combination : " + name ); - } - - hasCollections = foundCollection; - hasMutableProperties = foundMutable; - - iter = persistentClass.getSubclassIterator(); - while ( iter.hasNext() ) { - subclassEntityNames.add( ( (PersistentClass) iter.next() ).getEntityName() ); - } - subclassEntityNames.add( name ); - - if ( persistentClass.hasPojoRepresentation() ) { - entityNameByInheritenceClassMap.put( persistentClass.getMappedClass(), persistentClass.getEntityName() ); - iter = persistentClass.getSubclassIterator(); - while ( iter.hasNext() ) { - final PersistentClass pc = ( PersistentClass ) iter.next(); - entityNameByInheritenceClassMap.put( pc.getMappedClass(), pc.getEntityName() ); - } - } - - entityMode = persistentClass.hasPojoRepresentation() ? EntityMode.POJO : EntityMode.MAP; - final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory(); - final String tuplizerClassName = persistentClass.getTuplizerImplClassName( entityMode ); - if ( tuplizerClassName == null ) { - entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, persistentClass ); - } - else { - entityTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerClassName, this, persistentClass ); - } - } private static GenerationStrategyPair buildGenerationStrategyPair( final SessionFactoryImplementor sessionFactory, @@ -777,40 +523,43 @@ public EntityMetamodel( this.sessionFactory = sessionFactory; this.persister = persister; - name = entityBinding.getEntity().getName(); + name = entityBinding.getEntityName(); - rootName = entityBinding.getHierarchyDetails().getRootEntityBinding().getEntity().getName(); + rootName = entityBinding.getHierarchyDetails().getRootEntityBinding().getEntityName(); entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name ); identifierAttribute = PropertyFactory.buildIdentifierProperty( entityBinding, - sessionFactory.getIdentifierGenerator( rootName ) + sessionFactory.getIdentifierGenerator( rootName ), + sessionFactory ); - versioned = entityBinding.isVersioned(); + versioned = entityBinding.getHierarchyDetails().isVersioned(); - boolean hasPojoRepresentation = false; - Class mappedClass = null; + boolean isPOJO = entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO; Class proxyInterfaceClass = null; - if ( entityBinding.getEntity().getClassReferenceUnresolved() != null ) { - hasPojoRepresentation = true; - mappedClass = entityBinding.getEntity().getClassReference(); - proxyInterfaceClass = entityBinding.getProxyInterfaceType().getValue(); + Class mappedClass = null; + if ( isPOJO ) { + final ClassLoaderService cls = sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ); + mappedClass = cls.classForName( entityBinding.getEntity().getDescriptor().getName().toString() ); + if ( entityBinding.getProxyInterfaceType() != null ) { + proxyInterfaceClass = cls.classForName( entityBinding.getProxyInterfaceType().getName().toString() ); + } + instrumentationMetadata = Environment.getBytecodeProvider().getEntityInstrumentationMetadata( mappedClass ); + } + else { + instrumentationMetadata = new NonPojoInstrumentationMetadata( entityBinding.getEntityName() ); } - instrumentationMetadata = Environment.getBytecodeProvider().getEntityInstrumentationMetadata( mappedClass ); boolean hasLazy = false; // TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding - BasicAttributeBinding rootEntityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - // entityBinding.getAttributeClosureSpan() includes the identifier binding; - // "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null - propertySpan = rootEntityIdentifier == null ? - entityBinding.getAttributeBindingClosureSpan() : - entityBinding.getAttributeBindingClosureSpan() - 1; + + final AttributeBinding [] attributeBindings = entityBinding.getNonIdAttributeBindingClosure(); + propertySpan = attributeBindings.length; properties = new NonIdentifierAttribute[propertySpan]; - List naturalIdNumbers = new ArrayList(); + List naturalIdNumbers = new ArrayList(); // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ propertyNames = new String[propertySpan]; propertyTypes = new Type[propertySpan]; @@ -824,7 +573,6 @@ public EntityMetamodel( cascadeStyles = new CascadeStyle[propertySpan]; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // todo : handle value generations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ this.hasPreInsertGeneratedValues = false; this.hasPreUpdateGeneratedValues = false; @@ -846,31 +594,43 @@ public EntityMetamodel( boolean foundUpdateGeneratedValue = false; boolean foundUpdateableNaturalIdProperty = false; - for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { - if ( attributeBinding == rootEntityIdentifier ) { - // skip the identifier attribute binding - continue; - } + BasicAttributeBinding versionBinding = entityBinding.getHierarchyDetails().getEntityVersion() == null + ? null + : entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding(); - if ( attributeBinding == entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ) { + for ( AttributeBinding attributeBinding : attributeBindings ) { + if ( attributeBinding == versionBinding ) { tempVersionProperty = i; properties[i] = PropertyFactory.buildVersionProperty( persister, - entityBinding.getHierarchyDetails().getVersioningAttributeBinding(), + sessionFactory, + tempVersionProperty, + entityBinding, instrumentationMetadata.isInstrumented() ); } else { - properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, instrumentationMetadata.isInstrumented() ); + properties[i] = PropertyFactory.buildEntityBasedAttribute( + persister, + sessionFactory, + i, + attributeBinding, + instrumentationMetadata.isInstrumented() + ); } - // TODO: fix when natural IDs are added (HHH-6354) - //if ( attributeBinding.isNaturalIdentifier() ) { - // naturalIdNumbers.add( i ); - // if ( attributeBinding.isUpdateable() ) { - // foundUpdateableNaturalIdProperty = true; - // } - //} + if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { + SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class.cast( + attributeBinding + ); + if ( singularAttributeBinding.getNaturalIdMutability() == NaturalIdMutability.MUTABLE ) { + naturalIdNumbers.add( i ); + foundUpdateableNaturalIdProperty = true; + } + else if ( singularAttributeBinding.getNaturalIdMutability() == NaturalIdMutability.IMMUTABLE ) { + naturalIdNumbers.add( i ); + } + } if ( "id".equals( attributeBinding.getAttribute().getName() ) ) { foundNonIdentifierPropertyNamedId = true; @@ -922,7 +682,7 @@ public EntityMetamodel( else { naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); hasImmutableNaturalId = !foundUpdateableNaturalIdProperty; - hasCacheableNaturalId = false; //See previous TODO and HHH-6354 + hasCacheableNaturalId = entityBinding.getHierarchyDetails().getNaturalIdCaching() != null; } hasCascades = foundCascade; @@ -935,18 +695,18 @@ public EntityMetamodel( lazy = entityBinding.isLazy() && ( // TODO: this disables laziness even in non-pojo entity modes: - ! hasPojoRepresentation || + ! isPOJO || ! ReflectHelper.isFinalClass( proxyInterfaceClass ) ); - mutable = entityBinding.isMutable(); + mutable = entityBinding.getHierarchyDetails().isMutable(); if ( entityBinding.isAbstract() == null ) { // legacy behavior (with no abstract attribute specified) - isAbstract = hasPojoRepresentation && + isAbstract = isPOJO && ReflectHelper.isAbstractClass( mappedClass ); } else { - isAbstract = entityBinding.isAbstract().booleanValue(); - if ( !isAbstract && hasPojoRepresentation && + isAbstract = entityBinding.isAbstract(); + if ( !isAbstract && isPOJO && ReflectHelper.isAbstractClass( mappedClass ) ) { LOG.entityMappedAsNonAbstract(name); } @@ -978,12 +738,14 @@ public EntityMetamodel( hasCollections = foundCollection; hasMutableProperties = foundMutable; - for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) { - subclassEntityNames.add( subEntityBinding.getEntity().getName() ); - if ( subEntityBinding.getEntity().getClassReference() != null ) { - entityNameByInheritenceClassMap.put( - subEntityBinding.getEntity().getClassReference(), - subEntityBinding.getEntity().getName() ); + if ( isPOJO ) { + final ClassLoaderService cls = sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ); + for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) { + subclassEntityNames.add( subEntityBinding.getEntityName() ); + final Class subclassClass = cls.classForName( + subEntityBinding.getEntity().getDescriptor().getName().toString() + ); + entityNameByInheritenceClassMap.put( subclassClass, subEntityBinding.getEntityName() ); } } subclassEntityNames.add( name ); @@ -991,15 +753,14 @@ public EntityMetamodel( entityNameByInheritenceClassMap.put( mappedClass, name ); } - entityMode = hasPojoRepresentation ? EntityMode.POJO : EntityMode.MAP; + entityMode = isPOJO ? EntityMode.POJO : EntityMode.MAP; final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory(); - Class tuplizerClass = entityBinding.getCustomEntityTuplizerClass(); - - if ( tuplizerClass == null ) { + Class tuplizerClassName = entityBinding.getCustomTuplizerClass(); + if ( tuplizerClassName == null ) { entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, entityBinding ); } else { - entityTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerClass, this, entityBinding ); + entityTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerClassName, this, entityBinding ); } } @@ -1100,9 +861,9 @@ private void mapPropertyToIndex(Property prop, int i) { private void mapPropertyToIndex(Attribute attribute, int i) { propertyIndexes.put( attribute.getName(), i ); if ( attribute.isSingular() && - ( ( SingularAttribute ) attribute ).getSingularAttributeType().isComponent() ) { - org.hibernate.metamodel.domain.Component component = - ( org.hibernate.metamodel.domain.Component ) ( ( SingularAttribute ) attribute ).getSingularAttributeType(); + ( ( SingularAttribute ) attribute ).getSingularAttributeType().isAggregate() ) { + Aggregate component = + ( Aggregate ) ( ( SingularAttribute ) attribute ).getSingularAttributeType(); for ( Attribute subAttribute : component.attributes() ) { propertyIndexes.put( attribute.getName() + '.' + subAttribute.getName(), diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java index 229656949bda..f244e2701f8d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java @@ -35,12 +35,15 @@ import org.hibernate.tuple.Tuplizer; /** - * Defines further responsibilities reagarding tuplization based on + * Defines further responsibilities regarding tuplization based on * a mapped entity. *

    - * EntityTuplizer implementations should have the following constructor signatures: - * (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.mapping.PersistentClass) - * (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.metamodel.binding.EntityBinding) + * EntityTuplizer implementations should define a constructor with the following arguments:

      + *
    1. {@link org.hibernate.service.ServiceRegistry serviceRegistry}
    2. + *
    3. {@link org.hibernate.tuple.entity.EntityMetamodel}
    4. + *
    5. {@link org.hibernate.metamodel.spi.binding.EntityBinding}
    6. + *
    + * An easy way to check this is to extend the {@link org.hibernate.tuple.entity.AbstractEntityTuplizer} class. * * @author Gavin King * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java index 0cf17f85a695..e5c95741cdfc 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityTuplizerFactory.java @@ -25,14 +25,12 @@ import java.io.Serializable; import java.lang.reflect.Constructor; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.service.ServiceRegistry; /** * A registry allowing users to define the default {@link EntityTuplizer} class to use per {@link EntityMode}. @@ -40,53 +38,14 @@ * @author Steve Ebersole */ public class EntityTuplizerFactory implements Serializable { - public static final Class[] ENTITY_TUP_CTOR_SIG = new Class[] { EntityMetamodel.class, PersistentClass.class }; - public static final Class[] ENTITY_TUP_CTOR_SIG_NEW = new Class[] { EntityMetamodel.class, EntityBinding.class }; + public static final Class[] ENTITY_TUP_CTOR_SIG_NEW = new Class[] { + ServiceRegistry.class, + EntityMetamodel.class, + EntityBinding.class + }; - private Map> defaultImplClassByMode = buildBaseMapping(); - - /** - * Method allowing registration of the tuplizer class to use as default for a particular entity-mode. - * - * @param entityMode The entity-mode for which to register the tuplizer class - * @param tuplizerClass The class to use as the default tuplizer for the given entity-mode. - */ - public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) { - assert isEntityTuplizerImplementor( tuplizerClass ) - : "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + EntityTuplizer.class.getName(); - // TODO: for now we need constructors for both PersistentClass and EntityBinding - assert hasProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG ) - : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; - assert hasProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG_NEW ) - : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; - defaultImplClassByMode.put( entityMode, tuplizerClass ); - } - - /** - * Construct an instance of the given tuplizer class. - * - * @param tuplizerClassName The name of the tuplizer class to instantiate - * @param metamodel The metadata for the entity. - * @param persistentClass The mapping info for the entity. - * - * @return The instantiated tuplizer - * - * @throws HibernateException If class name cannot be resolved to a class reference, or if the - * {@link Constructor#newInstance} call fails. - */ - @SuppressWarnings({ "unchecked" }) - public EntityTuplizer constructTuplizer( - String tuplizerClassName, - EntityMetamodel metamodel, - PersistentClass persistentClass) { - try { - Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName ); - return constructTuplizer( tuplizerClass, metamodel, persistentClass ); - } - catch ( ClassNotFoundException e ) { - throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" ); - } - } + private Class defaultPojoModeTuplizerClass = PojoEntityTuplizer.class; + private Class defaultMapModeTuplizerClass = DynamicMapEntityTuplizer.class; /** * Construct an instance of the given tuplizer class. @@ -107,6 +66,9 @@ public EntityTuplizer constructTuplizer( EntityBinding entityBinding) { try { Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName ); + assert isEntityTuplizerImplementor( tuplizerClass ) + : "Specified EntityTuplizer class [" + tuplizerClassName + "] does not implement ComponentTuplizer"; + return constructTuplizer( tuplizerClass, metamodel, entityBinding ); } catch ( ClassNotFoundException e ) { @@ -114,31 +76,11 @@ public EntityTuplizer constructTuplizer( } } - /** - * Construct an instance of the given tuplizer class. - * - * @param tuplizerClass The tuplizer class to instantiate - * @param metamodel The metadata for the entity. - * @param persistentClass The mapping info for the entity. - * - * @return The instantiated tuplizer - * - * @throws HibernateException if the {@link Constructor#newInstance} call fails. - */ - public EntityTuplizer constructTuplizer( - Class tuplizerClass, - EntityMetamodel metamodel, - PersistentClass persistentClass) { - Constructor constructor = getProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG ); - assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; - try { - return constructor.newInstance( metamodel, persistentClass ); - } - catch ( Throwable t ) { - throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t ); - } + private boolean isEntityTuplizerImplementor(Class tuplizerClass) { + return ReflectHelper.implementsInterface( tuplizerClass, EntityTuplizer.class ); } + /** * Construct an instance of the given tuplizer class. * @@ -154,40 +96,25 @@ public EntityTuplizer constructTuplizer( Class tuplizerClass, EntityMetamodel metamodel, EntityBinding entityBinding) { - Constructor constructor = getProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG_NEW ); - assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; + Constructor constructor = getProperConstructor( + tuplizerClass, + ENTITY_TUP_CTOR_SIG_NEW + ); + assert constructor != null + : "Specified EntityTuplizer class [" + tuplizerClass.getName() + "] does not define proper constructor"; + try { - return constructor.newInstance( metamodel, entityBinding ); + return constructor.newInstance( + metamodel.getSessionFactory().getServiceRegistry(), + metamodel, + entityBinding + ); } catch ( Throwable t ) { throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t ); } } - /** - * Construct am instance of the default tuplizer for the given entity-mode. - * - * @param entityMode The entity mode for which to build a default tuplizer. - * @param metamodel The entity metadata. - * @param persistentClass The entity mapping info. - * - * @return The instantiated tuplizer - * - * @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from - * {@link #constructTuplizer} too. - */ - public EntityTuplizer constructDefaultTuplizer( - EntityMode entityMode, - EntityMetamodel metamodel, - PersistentClass persistentClass) { - Class tuplizerClass = defaultImplClassByMode.get( entityMode ); - if ( tuplizerClass == null ) { - throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" ); - } - - return constructTuplizer( tuplizerClass, metamodel, persistentClass ); - } - /** * Construct am instance of the default tuplizer for the given entity-mode. * @@ -204,7 +131,7 @@ public EntityTuplizer constructDefaultTuplizer( EntityMode entityMode, EntityMetamodel metamodel, EntityBinding entityBinding) { - Class tuplizerClass = defaultImplClassByMode.get( entityMode ); + Class tuplizerClass = determineTuplizerClass( entityMode ); if ( tuplizerClass == null ) { throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" ); } @@ -212,13 +139,18 @@ public EntityTuplizer constructDefaultTuplizer( return constructTuplizer( tuplizerClass, metamodel, entityBinding ); } - private boolean isEntityTuplizerImplementor(Class tuplizerClass) { - return ReflectHelper.implementsInterface( tuplizerClass, EntityTuplizer.class ); - } - - private boolean hasProperConstructor(Class tuplizerClass, Class[] constructorArgs) { - return getProperConstructor( tuplizerClass, constructorArgs ) != null - && ! ReflectHelper.isAbstractClass( tuplizerClass ); + private Class determineTuplizerClass(EntityMode entityMode) { + switch ( entityMode ) { + case POJO: { + return defaultPojoModeTuplizerClass; + } + case MAP: { + return defaultMapModeTuplizerClass; + } + default: { + throw new IllegalArgumentException( "Unknown EntityMode : " + entityMode ); + } + } } private Constructor getProperConstructor( @@ -227,14 +159,11 @@ private Constructor getProperConstructor( Constructor constructor = null; try { constructor = clazz.getDeclaredConstructor( constructorArgs ); - if ( ! ReflectHelper.isPublic( constructor ) ) { - try { - // found a constructor, but it was not publicly accessible so try to request accessibility - constructor.setAccessible( true ); - } - catch ( SecurityException e ) { - constructor = null; - } + try { + constructor.setAccessible( true ); + } + catch ( SecurityException e ) { + constructor = null; } } catch ( NoSuchMethodException ignore ) { @@ -243,10 +172,19 @@ private Constructor getProperConstructor( return constructor; } - private static Map> buildBaseMapping() { - Map> map = new ConcurrentHashMap>(); - map.put( EntityMode.POJO, PojoEntityTuplizer.class ); - map.put( EntityMode.MAP, DynamicMapEntityTuplizer.class ); - return map; + public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) { + switch ( entityMode ) { + case POJO: { + defaultPojoModeTuplizerClass = tuplizerClass; + break; + } + case MAP: { + defaultMapModeTuplizerClass = tuplizerClass; + break; + } + default: { + throw new IllegalArgumentException( "Unknown EntityMode : " + entityMode ); + } + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java index 41945c3436a7..9d27999012c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java @@ -26,7 +26,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -35,6 +34,7 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.PropertyNotFoundException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper; import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor; import org.hibernate.bytecode.spi.ReflectionOptimizer; @@ -45,17 +45,19 @@ import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Subclass; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BackRefAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.property.Getter; +import org.hibernate.property.IndexPropertyAccessor; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.ProxyFactory; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.PojoInstantiator; import org.hibernate.type.CompositeType; @@ -72,51 +74,22 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { private final Class mappedClass; private final Class proxyInterface; private final boolean lifecycleImplementor; - private final Set lazyPropertyNames = new HashSet(); + private final Set lazyPropertyNames = new HashSet(); private final ReflectionOptimizer optimizer; private final boolean isInstrumented; - public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super( entityMetamodel, mappedEntity ); - this.mappedClass = mappedEntity.getMappedClass(); - this.proxyInterface = mappedEntity.getProxyInterface(); - this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass ); - this.isInstrumented = entityMetamodel.isInstrumented(); - - Iterator iter = mappedEntity.getPropertyClosureIterator(); - while ( iter.hasNext() ) { - Property property = (Property) iter.next(); - if ( property.isLazy() ) { - lazyPropertyNames.add( property.getName() ); - } - } - - String[] getterNames = new String[propertySpan]; - String[] setterNames = new String[propertySpan]; - Class[] propTypes = new Class[propertySpan]; - for ( int i = 0; i < propertySpan; i++ ) { - getterNames[i] = getters[i].getMethodName(); - setterNames[i] = setters[i].getMethodName(); - propTypes[i] = getters[i].getReturnType(); - } - - if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) { - optimizer = null; + public PojoEntityTuplizer(ServiceRegistry serviceRegistry, EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { + super( serviceRegistry, entityMetamodel, mappedEntity ); + final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class ); + this.mappedClass = cls.classForName( mappedEntity.getEntity().getDescriptor().getName().toString() ); + if ( mappedEntity.getProxyInterfaceType() != null ) { + this.proxyInterface = cls.classForName( + mappedEntity.getProxyInterfaceType().getName().toString() + ); } else { - // todo : YUCK!!! - optimizer = Environment.getBytecodeProvider().getReflectionOptimizer( mappedClass, getterNames, setterNames, propTypes ); -// optimizer = getFactory().getSettings().getBytecodeProvider().getReflectionOptimizer( -// mappedClass, getterNames, setterNames, propTypes -// ); + this.proxyInterface = null; } - - } - - public PojoEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { - super( entityMetamodel, mappedEntity ); - this.mappedClass = mappedEntity.getEntity().getClassReference(); - this.proxyInterface = mappedEntity.getProxyInterfaceType().getValue(); this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass ); this.isInstrumented = entityMetamodel.isInstrumented(); @@ -149,121 +122,14 @@ public PojoEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedE } } - @Override - protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { - // determine the id getter and setter methods from the proxy interface (if any) - // determine all interfaces needed by the resulting proxy - - /* - * We need to preserve the order of the interfaces they were put into the set, since javassist will choose the - * first one's class-loader to construct the proxy class with. This is also the reason why HibernateProxy.class - * should be the last one in the order (on JBossAS7 its class-loader will be org.hibernate module's class- - * loader, which will not see the classes inside deployed apps. See HHH-3078 - */ - Set proxyInterfaces = new java.util.LinkedHashSet(); - - Class mappedClass = persistentClass.getMappedClass(); - Class proxyInterface = persistentClass.getProxyInterface(); - - if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) { - if ( !proxyInterface.isInterface() ) { - throw new MappingException( - "proxy must be either an interface, or the class itself: " + getEntityName() - ); - } - proxyInterfaces.add( proxyInterface ); - } - - if ( mappedClass.isInterface() ) { - proxyInterfaces.add( mappedClass ); - } - - Iterator subclasses = persistentClass.getSubclassIterator(); - while ( subclasses.hasNext() ) { - final Subclass subclass = ( Subclass ) subclasses.next(); - final Class subclassProxy = subclass.getProxyInterface(); - final Class subclassClass = subclass.getMappedClass(); - if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) { - if ( !subclassProxy.isInterface() ) { - throw new MappingException( - "proxy must be either an interface, or the class itself: " + subclass.getEntityName() - ); - } - proxyInterfaces.add( subclassProxy ); - } - } - - proxyInterfaces.add( HibernateProxy.class ); - - Iterator properties = persistentClass.getPropertyIterator(); - Class clazz = persistentClass.getMappedClass(); - while ( properties.hasNext() ) { - Property property = (Property) properties.next(); - Method method = property.getGetter(clazz).getMethod(); - if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { - LOG.gettersOfLazyClassesCannotBeFinal(persistentClass.getEntityName(), property.getName()); - } - method = property.getSetter(clazz).getMethod(); - if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { - LOG.settersOfLazyClassesCannotBeFinal(persistentClass.getEntityName(), property.getName()); - } - } - - Method idGetterMethod = idGetter==null ? null : idGetter.getMethod(); - Method idSetterMethod = idSetter==null ? null : idSetter.getMethod(); - - Method proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ? - null : - ReflectHelper.getMethod(proxyInterface, idGetterMethod); - Method proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null ? - null : - ReflectHelper.getMethod(proxyInterface, idSetterMethod); - - ProxyFactory pf = buildProxyFactoryInternal( persistentClass, idGetter, idSetter ); - try { - pf.postInstantiate( - getEntityName(), - mappedClass, - proxyInterfaces, - proxyGetIdentifierMethod, - proxySetIdentifierMethod, - persistentClass.hasEmbeddedIdentifier() ? - (CompositeType) persistentClass.getIdentifier().getType() : - null - ); - } - catch ( HibernateException he ) { - LOG.unableToCreateProxyFactory(getEntityName(), he); - pf = null; - } - return pf; - } - - protected ProxyFactory buildProxyFactoryInternal(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { - // TODO : YUCK!!! fix after HHH-1907 is complete - return Environment.getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory(); -// return getFactory().getSettings().getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory(); - } - - @Override - protected Instantiator buildInstantiator(PersistentClass persistentClass) { - if ( optimizer == null ) { - return new PojoInstantiator( persistentClass, null ); - } - else { - return new PojoInstantiator( persistentClass, optimizer.getInstantiationOptimizer() ); - } - } - @Override protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { // determine the id getter and setter methods from the proxy interface (if any) // determine all interfaces needed by the resulting proxy - HashSet proxyInterfaces = new HashSet(); - proxyInterfaces.add( HibernateProxy.class ); + Set proxyInterfaces = new java.util.LinkedHashSet(); - Class mappedClass = entityBinding.getEntity().getClassReference(); - Class proxyInterface = entityBinding.getProxyInterfaceType().getValue(); + final Class mappedClass = classForType( entityBinding.getEntity().getDescriptor() ); + final Class proxyInterface = classForType( entityBinding.getProxyInterfaceType() ); if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) { if ( ! proxyInterface.isInterface() ) { @@ -279,26 +145,32 @@ protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idG } for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) { - final Class subclassProxy = subEntityBinding.getProxyInterfaceType().getValue(); - final Class subclassClass = subEntityBinding.getClassReference(); + final Class subclassProxy = classForType( subEntityBinding.getProxyInterfaceType() ); + final Class subclassClass = classForType( subEntityBinding.getEntity().getDescriptor() ); if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) { if ( ! subclassProxy.isInterface() ) { throw new MappingException( - "proxy must be either an interface, or the class itself: " + subEntityBinding.getEntity().getName() + "proxy must be either an interface, or the class itself: " + subEntityBinding.getEntityName() ); } proxyInterfaces.add( subclassProxy ); } } + proxyInterfaces.add( HibernateProxy.class ); + for ( AttributeBinding property : entityBinding.attributeBindings() ) { Method method = getGetter( property ).getMethod(); if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { - LOG.gettersOfLazyClassesCannotBeFinal(entityBinding.getEntity().getName(), property.getAttribute().getName()); + LOG.gettersOfLazyClassesCannotBeFinal( + entityBinding.getEntityName(), property.getAttribute().getName() + ); } method = getSetter( property ).getMethod(); if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { - LOG.settersOfLazyClassesCannotBeFinal(entityBinding.getEntity().getName(), property.getAttribute().getName()); + LOG.settersOfLazyClassesCannotBeFinal( + entityBinding.getEntityName(), property.getAttribute().getName() + ); } } @@ -320,11 +192,11 @@ protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idG proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod, - entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded() + entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierMapper() ? ( CompositeType ) entityBinding .getHierarchyDetails() .getEntityIdentifier() - .getValueBinding() + .getAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping() : null @@ -337,6 +209,14 @@ protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idG return pf; } + private Class classForType(JavaTypeDescriptor td) { + if ( td == null ) { + return null; + } + + return classForName( td.getName().toString() ); + } + protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { // TODO : YUCK!!! fix after HHH-1907 is complete return Environment.getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory(); @@ -346,10 +226,10 @@ protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Ge @Override protected Instantiator buildInstantiator(EntityBinding entityBinding) { if ( optimizer == null ) { - return new PojoInstantiator( entityBinding, null ); + return new PojoInstantiator( serviceRegistry(), entityBinding, null ); } else { - return new PojoInstantiator( entityBinding, optimizer.getInstantiationOptimizer() ); + return new PojoInstantiator( serviceRegistry(), entityBinding, optimizer.getInstantiationOptimizer() ); } } @@ -406,44 +286,51 @@ public boolean isLifecycleImplementor() { return lifecycleImplementor; } - @Override - protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { - return mappedProperty.getGetter( mappedEntity.getMappedClass() ); - } - - @Override - protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { - return mappedProperty.getSetter( mappedEntity.getMappedClass() ); - } - @Override protected Getter buildPropertyGetter(AttributeBinding mappedProperty) { return getGetter( mappedProperty ); } - @Override - protected Setter buildPropertySetter(AttributeBinding mappedProperty) { - return getSetter( mappedProperty ); - } - - private Getter getGetter(AttributeBinding mappedProperty) throws PropertyNotFoundException, MappingException { + private Getter getGetter(AttributeBinding mappedProperty) + throws PropertyNotFoundException, MappingException { return getPropertyAccessor( mappedProperty ).getGetter( - mappedProperty.getContainer().getClassReference(), + classForType( mappedProperty.getContainer().getAttributeContainer().getDescriptor() ), mappedProperty.getAttribute().getName() ); } - private Setter getSetter(AttributeBinding mappedProperty) throws PropertyNotFoundException, MappingException { + @Override + protected Setter buildPropertySetter(AttributeBinding mappedProperty) { + return getSetter( mappedProperty ); + } + + private Setter getSetter(AttributeBinding mappedProperty) + throws PropertyNotFoundException, MappingException { return getPropertyAccessor( mappedProperty ).getSetter( - mappedProperty.getContainer().getClassReference(), + classForType( mappedProperty.getContainer().getAttributeContainer().getDescriptor() ), mappedProperty.getAttribute().getName() ); } - private PropertyAccessor getPropertyAccessor(AttributeBinding mappedProperty) throws MappingException { - // TODO: Fix this then backrefs are working in new metamodel + private PropertyAccessor getPropertyAccessor(AttributeBinding mappedProperty) + throws MappingException { + if ( mappedProperty.isBackRef() ) { + BackRefAttributeBinding backRefAttributeBinding = (BackRefAttributeBinding) mappedProperty; + if ( backRefAttributeBinding.isIndexBackRef() ) { + return new IndexPropertyAccessor( + backRefAttributeBinding.getCollectionRole(), + backRefAttributeBinding.getEntityName() + ); + } + else { + return new BackrefPropertyAccessor( + backRefAttributeBinding.getCollectionRole(), + backRefAttributeBinding.getEntityName() + ); + } + } return PropertyAccessorFactory.getPropertyAccessor( - mappedProperty.getContainer().getClassReference(), + classForType( mappedProperty.getContainer().getAttributeContainer().getDescriptor() ), mappedProperty.getPropertyAccessorName() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java index 49b9cc8d280a..9e712b7c6b3d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractLobType.java @@ -31,7 +31,7 @@ import org.hibernate.MappingException; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; /** * @author Emmanuel Bernard diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index 4d5b0effdd2f..56747ae2244e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -40,7 +40,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.MutabilityPlan; @@ -64,9 +64,12 @@ public abstract class AbstractStandardBasicType // by DynamicParameterizedTypes. private SqlTypeDescriptor sqlTypeDescriptor; private JavaTypeDescriptor javaTypeDescriptor; + // sqlTypes need always to be in sync with sqlTypeDescriptor + private int[] sqlTypes; public AbstractStandardBasicType(SqlTypeDescriptor sqlTypeDescriptor, JavaTypeDescriptor javaTypeDescriptor) { this.sqlTypeDescriptor = sqlTypeDescriptor; + this.sqlTypes = new int[] { sqlTypeDescriptor.getSqlType() }; this.javaTypeDescriptor = javaTypeDescriptor; } @@ -141,9 +144,10 @@ public final void setJavaTypeDescriptor( JavaTypeDescriptor javaTypeDescripto public final SqlTypeDescriptor getSqlTypeDescriptor() { return sqlTypeDescriptor; } - + public final void setSqlTypeDescriptor( SqlTypeDescriptor sqlTypeDescriptor ) { this.sqlTypeDescriptor = sqlTypeDescriptor; + this.sqlTypes = new int[] { sqlTypeDescriptor.getSqlType() }; } public final Class getReturnedClass() { @@ -151,11 +155,11 @@ public final Class getReturnedClass() { } public final int getColumnSpan(Mapping mapping) throws MappingException { - return sqlTypes( mapping ).length; + return 1; } public final int[] sqlTypes(Mapping mapping) throws MappingException { - return new int[] { sqlTypeDescriptor.getSqlType() }; + return sqlTypes; } @Override @@ -359,7 +363,7 @@ public Object replace( Object owner, Map copyCache, ForeignKeyDirection foreignKeyDirection) { - return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT == foreignKeyDirection + return ForeignKeyDirection.FROM_PARENT == foreignKeyDirection ? getReplacement( (T) original, (T) target, session ) : target; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java index fdd7aba4e4b0..1618d16a2589 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java @@ -32,7 +32,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.compare.EqualsHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.dom4j.Element; import org.dom4j.Node; @@ -173,7 +173,7 @@ public Object replace( include = atype.getForeignKeyDirection()==foreignKeyDirection; } else { - include = ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT==foreignKeyDirection; + include = ForeignKeyDirection.FROM_PARENT==foreignKeyDirection; } return include ? replace(original, target, session, owner, copyCache) : target; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/AnyType.java b/hibernate-core/src/main/java/org/hibernate/type/AnyType.java index 582d65adc3d9..cdf0eaa331c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AnyType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AnyType.java @@ -45,7 +45,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Joinable; import org.hibernate.proxy.HibernateProxy; @@ -464,7 +464,7 @@ public FetchMode getFetchMode(int i) { @Override public ForeignKeyDirection getForeignKeyDirection() { - return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT; + return ForeignKeyDirection.FROM_PARENT; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java index 3a76e13f9b59..6c5e16063231 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java @@ -53,7 +53,7 @@ import org.hibernate.internal.util.MarkerObject; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.entity.EntityPersister; @@ -366,7 +366,7 @@ public boolean isAssociationType() { @Override public ForeignKeyDirection getForeignKeyDirection() { - return ForeignKeyDirection.FOREIGN_KEY_TO_PARENT; + return ForeignKeyDirection.TO_PARENT; } /** diff --git a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java index f706f3cc8945..7dfdff89e35d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java @@ -43,7 +43,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.tuple.StandardProperty; import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.tuple.component.ComponentTuplizer; @@ -66,6 +66,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced private final CascadeStyle[] cascade; private final FetchMode[] joinedFetch; private final boolean isKey; + private boolean hasNotNullProperty; protected final EntityMode entityMode; protected final ComponentTuplizer componentTuplizer; @@ -88,6 +89,9 @@ public ComponentType(TypeFactory.TypeScope typeScope, ComponentMetamodel metamod this.propertyNullability[i] = prop.isNullable(); this.cascade[i] = prop.getCascadeStyle(); this.joinedFetch[i] = prop.getFetchMode(); + if (!prop.isNullable()) { + hasNotNullProperty = true; + } } this.entityMode = metamodel.getEntityMode(); @@ -182,18 +186,15 @@ public boolean isSame(Object x, Object y) throws HibernateException { } @Override - public boolean isEqual(Object x, Object y) - throws HibernateException { + public boolean isEqual(final Object x, final Object y) throws HibernateException { if ( x == y ) { return true; } if ( x == null || y == null ) { return false; } - Object[] xvalues = getPropertyValues( x, entityMode ); - Object[] yvalues = getPropertyValues( y, entityMode ); for ( int i = 0; i < propertySpan; i++ ) { - if ( !propertyTypes[i].isEqual( xvalues[i], yvalues[i] ) ) { + if ( !propertyTypes[i].isEqual( getPropertyValue( x, i ), getPropertyValue( y, i ) ) ) { return false; } } @@ -201,18 +202,15 @@ public boolean isEqual(Object x, Object y) } @Override - public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) - throws HibernateException { + public boolean isEqual(final Object x, final Object y, final SessionFactoryImplementor factory) throws HibernateException { if ( x == y ) { return true; } if ( x == null || y == null ) { return false; } - Object[] xvalues = getPropertyValues( x, entityMode ); - Object[] yvalues = getPropertyValues( y, entityMode ); for ( int i = 0; i < propertySpan; i++ ) { - if ( !propertyTypes[i].isEqual( xvalues[i], yvalues[i], factory ) ) { + if ( !propertyTypes[i].isEqual( getPropertyValue( x, i ), getPropertyValue( y, i ), factory ) ) { return false; } } @@ -220,14 +218,12 @@ public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) } @Override - public int compare(Object x, Object y) { + public int compare(final Object x, final Object y) { if ( x == y ) { return 0; } - Object[] xvalues = getPropertyValues( x, entityMode ); - Object[] yvalues = getPropertyValues( y, entityMode ); for ( int i = 0; i < propertySpan; i++ ) { - int propertyCompare = propertyTypes[i].compare( xvalues[i], yvalues[i] ); + int propertyCompare = propertyTypes[i].compare( getPropertyValue( x, i ), getPropertyValue( y, i ) ); if ( propertyCompare != 0 ) { return propertyCompare; } @@ -240,11 +236,10 @@ public boolean isMethodOf(Method method) { } @Override - public int getHashCode(Object x) { + public int getHashCode(final Object x) { int result = 17; - Object[] values = getPropertyValues( x, entityMode ); for ( int i = 0; i < propertySpan; i++ ) { - Object y = values[i]; + Object y = getPropertyValue( x, i ); result *= 37; if ( y != null ) { result += propertyTypes[i].getHashCode( y ); @@ -254,11 +249,10 @@ public int getHashCode(Object x) { } @Override - public int getHashCode(Object x, SessionFactoryImplementor factory) { + public int getHashCode(final Object x, final SessionFactoryImplementor factory) { int result = 17; - Object[] values = getPropertyValues( x, entityMode ); for ( int i = 0; i < propertySpan; i++ ) { - Object y = values[i]; + Object y = getPropertyValue( x, i ); result *= 37; if ( y != null ) { result += propertyTypes[i].getHashCode( y, factory ); @@ -268,40 +262,34 @@ public int getHashCode(Object x, SessionFactoryImplementor factory) { } @Override - public boolean isDirty(Object x, Object y, SessionImplementor session) - throws HibernateException { + public boolean isDirty(final Object x, final Object y, final SessionImplementor session) throws HibernateException { if ( x == y ) { return false; } if ( x == null || y == null ) { return true; } - Object[] xvalues = getPropertyValues( x, entityMode ); - Object[] yvalues = getPropertyValues( y, entityMode ); - for ( int i = 0; i < xvalues.length; i++ ) { - if ( propertyTypes[i].isDirty( xvalues[i], yvalues[i], session ) ) { + for ( int i = 0; i < propertySpan; i++ ) { + if ( propertyTypes[i].isDirty( getPropertyValue( x, i ), getPropertyValue( y, i ), session ) ) { return true; } } return false; } - public boolean isDirty(Object x, Object y, boolean[] checkable, SessionImplementor session) - throws HibernateException { + public boolean isDirty(final Object x, final Object y, final boolean[] checkable, final SessionImplementor session) throws HibernateException { if ( x == y ) { return false; } if ( x == null || y == null ) { return true; } - Object[] xvalues = getPropertyValues( x, entityMode ); - Object[] yvalues = getPropertyValues( y, entityMode ); int loc = 0; - for ( int i = 0; i < xvalues.length; i++ ) { + for ( int i = 0; i < propertySpan; i++ ) { int len = propertyTypes[i].getColumnSpan( session.getFactory() ); if ( len <= 1 ) { final boolean dirty = ( len == 0 || checkable[loc] ) && - propertyTypes[i].isDirty( xvalues[i], yvalues[i], session ); + propertyTypes[i].isDirty( getPropertyValue( x, i ), getPropertyValue( y, i ), session ); if ( dirty ) { return true; } @@ -309,7 +297,7 @@ public boolean isDirty(Object x, Object y, boolean[] checkable, SessionImplement else { boolean[] subcheckable = new boolean[len]; System.arraycopy( checkable, loc, subcheckable, 0, len ); - final boolean dirty = propertyTypes[i].isDirty( xvalues[i], yvalues[i], subcheckable, session ); + final boolean dirty = propertyTypes[i].isDirty( getPropertyValue( x, i ), getPropertyValue( y, i ), subcheckable, session ); if ( dirty ) { return true; } @@ -320,23 +308,20 @@ public boolean isDirty(Object x, Object y, boolean[] checkable, SessionImplement } @Override - public boolean isModified(Object old, Object current, boolean[] checkable, SessionImplementor session) - throws HibernateException { - + public boolean isModified(final Object old, final Object current, final boolean[] checkable, final SessionImplementor session) throws HibernateException { if ( current == null ) { return old != null; } if ( old == null ) { return true; } - Object[] currentValues = getPropertyValues( current, session ); Object[] oldValues = ( Object[] ) old; int loc = 0; - for ( int i = 0; i < currentValues.length; i++ ) { + for ( int i = 0; i < propertySpan; i++ ) { int len = propertyTypes[i].getColumnSpan( session.getFactory() ); boolean[] subcheckable = new boolean[len]; System.arraycopy( checkable, loc, subcheckable, 0, len ); - if ( propertyTypes[i].isModified( oldValues[i], currentValues[i], subcheckable, session ) ) { + if ( propertyTypes[i].isModified( oldValues[i], getPropertyValue( current, i ), subcheckable, session ) ) { return true; } loc += len; @@ -410,13 +395,26 @@ public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, @Override public Object getPropertyValue(Object component, int i, SessionImplementor session) throws HibernateException { - return getPropertyValue( component, i, entityMode ); + return getPropertyValue( component, i ); } - public Object getPropertyValue(Object component, int i, EntityMode entityMode) throws HibernateException { - return componentTuplizer.getPropertyValue( component, i ); + return getPropertyValue( component, i ); + } + + public Object getPropertyValue(Object component, int i) + throws HibernateException { + if ( component instanceof Object[] ) { + // A few calls to hashCode pass the property values already in an + // Object[] (ex: QueryKey hash codes for cached queries). + // It's easiest to just check for the condition here prior to + // trying reflection. + return (( Object[] ) component)[i]; + } else { + return componentTuplizer.getPropertyValue( component, i ); + } } + @Override public Object[] getPropertyValues(Object component, SessionImplementor session) throws HibernateException { @@ -811,4 +809,8 @@ public Object extract(CallableStatement statement, String[] paramNames, SessionI return resolve( values, session, null ); } + + public boolean hasNotNullProperty() { + return hasNotNullProperty; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java index 146f4fe1277f..bc4cbc872a35 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CompositeCustomType.java @@ -40,7 +40,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.LoggableUserType; diff --git a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java index 552bd24a8487..3cc6e69bc36e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java @@ -38,7 +38,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.usertype.EnhancedUserType; import org.hibernate.usertype.LoggableUserType; import org.hibernate.usertype.Sized; diff --git a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java index f7f2f0eeec86..147b67f67442 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java @@ -64,6 +64,19 @@ public abstract class EntityType extends AbstractType implements AssociationType private final boolean unwrapProxy; private final boolean referenceToPrimaryKey; + /** + * Cached because of performance + * @see #getIdentifierType(SessionImplementor) + * @see #getIdentifierType(Mapping) + */ + private transient volatile Type associatedIdentifierType; + + /** + * Cached because of performance + * @see #getAssociatedEntityPersister + */ + private transient volatile EntityPersister associatedEntityPersister; + private transient Class returnedClass; /** @@ -248,7 +261,7 @@ public String getAssociatedEntityName(SessionFactoryImplementor factory) { */ @Override public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException { - return ( Joinable ) factory.getEntityPersister( associatedEntityName ); + return ( Joinable ) getAssociatedEntityPersister( factory ); } /** @@ -346,7 +359,7 @@ public Object replace( else { Object id = getIdentifier( original, session ); if ( id == null ) { - throw new AssertionFailure("non-transient entity has a null id"); + throw new AssertionFailure("non-transient entity has a null id: " + original.getClass().getName()); } id = getIdentifierOrUniqueKeyType( session.getFactory() ) .replace(id, null, session, owner, copyCache); @@ -357,7 +370,7 @@ public Object replace( @Override public int getHashCode(Object x, SessionFactoryImplementor factory) { - EntityPersister persister = factory.getEntityPersister(associatedEntityName); + EntityPersister persister = getAssociatedEntityPersister( factory ); if ( !persister.canExtractIdOutOfEntity() ) { return super.getHashCode( x ); } @@ -385,7 +398,7 @@ public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) { return x == y; } - EntityPersister persister = factory.getEntityPersister(associatedEntityName); + EntityPersister persister = getAssociatedEntityPersister( factory ); if ( !persister.canExtractIdOutOfEntity() ) { return super.isEqual(x, y ); } @@ -498,7 +511,21 @@ else if ( uniqueKeyPropertyName != null ) { @Override public Type getSemiResolvedType(SessionFactoryImplementor factory) { - return factory.getEntityPersister( associatedEntityName ).getIdentifierType(); + return getAssociatedEntityPersister( factory ).getIdentifierType(); + } + + protected EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) { + final EntityPersister persister = associatedEntityPersister; + //The following branch implements a simple lazy-initialization, but rather than the canonical + //form it returns the local variable to avoid a second volatile read: associatedEntityPersister + //needs to be volatile as the initialization might happen by a different thread than the readers. + if ( persister == null ) { + associatedEntityPersister = factory.getEntityPersister( getAssociatedEntityName() ); + return associatedEntityPersister; + } + else { + return persister; + } } protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException { @@ -513,7 +540,7 @@ else if ( value == null ) { return null; } else { - EntityPersister entityPersister = session.getFactory().getEntityPersister( getAssociatedEntityName() ); + EntityPersister entityPersister = getAssociatedEntityPersister( session.getFactory() ); Object propertyValue = entityPersister.getPropertyValue( value, uniqueKeyPropertyName ); // We now have the value of the property-ref we reference. However, // we need to dig a little deeper, as that property might also be @@ -551,7 +578,7 @@ public String toLoggableString(Object value, SessionFactoryImplementor factory) return "null"; } - EntityPersister persister = factory.getEntityPersister( associatedEntityName ); + EntityPersister persister = getAssociatedEntityPersister( factory ); StringBuilder result = new StringBuilder().append( associatedEntityName ); if ( persister.hasIdentifierProperty() ) { @@ -599,8 +626,18 @@ public boolean isLogicalOneToOne() { * @param factory The mappings... * @return The identifier type */ - Type getIdentifierType(Mapping factory) { - return factory.getIdentifierType( getAssociatedEntityName() ); + Type getIdentifierType(final Mapping factory) { + final Type type = associatedIdentifierType; + //The following branch implements a simple lazy-initialization, but rather than the canonical + //form it returns the local variable to avoid a second volatile read: associatedIdentifierType + //needs to be volatile as the initialization might happen by a different thread than the readers. + if ( type == null ) { + associatedIdentifierType = factory.getIdentifierType( getAssociatedEntityName() ); + return associatedIdentifierType; + } + else { + return type; + } } /** @@ -609,8 +646,15 @@ Type getIdentifierType(Mapping factory) { * @param session The originating session * @return The identifier type */ - Type getIdentifierType(SessionImplementor session) { - return getIdentifierType( session.getFactory() ); + Type getIdentifierType(final SessionImplementor session) { + final Type type = associatedIdentifierType; + if ( type == null ) { + associatedIdentifierType = getIdentifierType( session.getFactory() ); + return associatedIdentifierType; + } + else { + return type; + } } /** @@ -666,8 +710,7 @@ public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory) */ protected final Object resolveIdentifier(Serializable id, SessionImplementor session) throws HibernateException { boolean isProxyUnwrapEnabled = unwrapProxy && - session.getFactory() - .getEntityPersister( getAssociatedEntityName() ) + getAssociatedEntityPersister( session.getFactory() ) .isInstrumented(); Object proxyOrEntity = session.internalLoad( diff --git a/hibernate-core/src/main/java/org/hibernate/type/EnumType.java b/hibernate-core/src/main/java/org/hibernate/type/EnumType.java index b6b494b6823f..8e45125dffa5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EnumType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EnumType.java @@ -38,6 +38,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.usertype.DynamicParameterizedType; import org.hibernate.usertype.EnhancedUserType; @@ -68,11 +69,25 @@ * @author Steve Ebersole */ @SuppressWarnings("unchecked") -public class EnumType implements EnhancedUserType, DynamicParameterizedType,LoggableUserType, Serializable { +public class EnumType implements EnhancedUserType, DynamicParameterizedType, LoggableUserType, Serializable { private static final Logger LOG = Logger.getLogger( EnumType.class.getName() ); + /** + * Keys the enum Class in the config settings + */ public static final String ENUM = "enumClass"; + + /** + * Keys the boolean decision of whether named value mapping should be + * used, as opposed to ordinal. + */ public static final String NAMED = "useNamed"; + + /** + * Keys the JDBC type code to be used to represent the enum values. + * Typically this is either {@link java.sql.Types#INTEGER} (ORDINAL) or + * {@link java.sql.Types#VARCHAR} (NAMED) + */ public static final String TYPE = "type"; private Class enumClass; @@ -237,6 +252,9 @@ else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) { } else { String enumClassName = (String) parameters.get( ENUM ); + if( StringHelper.isEmpty( enumClassName )){ + enumClassName = (String)parameters.get( DynamicParameterizedType.RETURNED_CLASS ); + } try { enumClass = ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java b/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java index 594d07dee719..c00aedd10945 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ForeignKeyDirection.java @@ -23,61 +23,45 @@ */ package org.hibernate.type; -import java.io.Serializable; - +import org.hibernate.engine.internal.Cascade; import org.hibernate.engine.internal.CascadePoint; /** * Represents directionality of the foreign key constraint + * * @author Gavin King */ -public abstract class ForeignKeyDirection implements Serializable { - protected ForeignKeyDirection() {} - /** - * Should we cascade at this cascade point? - * - * @param cascadePoint The point at which the cascade is being initiated. - * - * @return {@code true} if cascading should be performed now. - * - * @see org.hibernate.engine.internal.Cascade - */ - public abstract boolean cascadeNow(CascadePoint cascadePoint); - +public enum ForeignKeyDirection { /** * A foreign key from child to parent */ - public static final ForeignKeyDirection FOREIGN_KEY_TO_PARENT = new ForeignKeyDirection() { + TO_PARENT { @Override public boolean cascadeNow(CascadePoint cascadePoint) { return cascadePoint != CascadePoint.BEFORE_INSERT_AFTER_DELETE; } - @Override - public String toString() { - return "toParent"; - } - - Object readResolve() { - return FOREIGN_KEY_TO_PARENT; - } - }; + }, /** * A foreign key from parent to child */ - public static final ForeignKeyDirection FOREIGN_KEY_FROM_PARENT = new ForeignKeyDirection() { + FROM_PARENT { @Override public boolean cascadeNow(CascadePoint cascadePoint) { return cascadePoint != CascadePoint.AFTER_INSERT_BEFORE_DELETE; } - - @Override - public String toString() { - return "fromParent"; - } - - Object readResolve() { - return FOREIGN_KEY_FROM_PARENT; - } }; + + /** + * Should we cascade at this cascade point? + * + * @param cascadePoint The point at which the cascade is being initiated. + * + * @return {@code true} if cascading should be performed now. + * + * @see org.hibernate.engine.internal.Cascade + */ + public abstract boolean cascadeNow(CascadePoint cascadePoint); + } + diff --git a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java index 63c76af840e4..3344aa31cc76 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java @@ -36,7 +36,7 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.entity.EntityPersister; /** @@ -176,7 +176,7 @@ public void nullSafeSet( } public ForeignKeyDirection getForeignKeyDirection() { - return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT; + return ForeignKeyDirection.FROM_PARENT; } public Object hydrate( @@ -200,7 +200,7 @@ public Object hydrate( private void scheduleBatchLoadIfNeeded(Serializable id, SessionImplementor session) throws MappingException { //cannot batch fetch by unique key (property-ref associations) if ( uniqueKeyPropertyName == null && id != null ) { - final EntityPersister persister = session.getFactory().getEntityPersister( getAssociatedEntityName() ); + final EntityPersister persister = getAssociatedEntityPersister( session.getFactory() ); if ( persister.isBatchLoadable() ) { final EntityKey entityKey = session.generateEntityKey( id, persister ); if ( !session.getPersistenceContext().containsEntity( entityKey ) ) { @@ -209,7 +209,7 @@ private void scheduleBatchLoadIfNeeded(Serializable id, SessionImplementor sessi } } } - + public boolean useLHSPrimaryKey() { return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/MetaType.java b/hibernate-core/src/main/java/org/hibernate/type/MetaType.java index da7d9e385e71..4d17afc19638 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/MetaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/MetaType.java @@ -34,7 +34,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.dom4j.Node; diff --git a/hibernate-core/src/main/java/org/hibernate/type/NullableType.java b/hibernate-core/src/main/java/org/hibernate/type/NullableType.java index a8c4efcf7ec7..82a3370df65e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/NullableType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/NullableType.java @@ -35,7 +35,7 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.compare.EqualsHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.jboss.logging.Logger; diff --git a/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java index 960adf18d880..539a8541ef56 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java @@ -34,7 +34,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.persister.entity.EntityPersister; /** @@ -178,7 +178,7 @@ public Object hydrate( } protected boolean isNullable() { - return foreignKeyType==ForeignKeyDirection.FOREIGN_KEY_TO_PARENT; + return foreignKeyType==ForeignKeyDirection.TO_PARENT; } public boolean useLHSPrimaryKey() { diff --git a/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java index 70c86b3f6afe..ccc0c8676294 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java @@ -33,7 +33,7 @@ import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; /** * A one-to-one association that maps to specific formula(s) diff --git a/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java b/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java index 1a6b3954fbfc..19ae5b3d6eea 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java +++ b/hibernate-core/src/main/java/org/hibernate/type/StandardBasicTypes.java @@ -191,6 +191,14 @@ private StandardBasicTypes() { */ public static final CalendarDateType CALENDAR_DATE = CalendarDateType.INSTANCE; + /** + * The standard Hibernate type for mapping {@link java.util.Calendar} to JDBC + * {@link java.sql.Types#TIME TIME}. + * + * @see CalendarDateType + */ + public static final CalendarTimeType CALENDAR_TIME = CalendarTimeType.INSTANCE; + /** * The standard Hibernate type for mapping {@link Class} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}. * diff --git a/hibernate-core/src/main/java/org/hibernate/type/Type.java b/hibernate-core/src/main/java/org/hibernate/type/Type.java index e486934784c0..25df093f28b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/Type.java +++ b/hibernate-core/src/main/java/org/hibernate/type/Type.java @@ -34,7 +34,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; import org.dom4j.Node; diff --git a/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java b/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java index f39270db8efb..0f878af71b20 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java @@ -128,7 +128,7 @@ public Type type(Class typeClass, Properties parameters) { public static void injectParameters(Object type, Properties parameters) { if ( ParameterizedType.class.isInstance( type ) ) { - ( (ParameterizedType) type ).setParameterValues(parameters); + ( (ParameterizedType) type ).setParameterValues( parameters ); } else if ( parameters!=null && !parameters.isEmpty() ) { throw new MappingException( "type is not parameterized: " + type.getClass().getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java index 6bfa05e97eff..2794b495724b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java @@ -26,7 +26,6 @@ import java.math.BigDecimal; import java.sql.Blob; import java.sql.Clob; -import java.sql.Date; import java.sql.Ref; import java.sql.Struct; import java.sql.Time; @@ -108,7 +107,7 @@ private static ConcurrentHashMap buildJdbcJavaClassMappings() { jdbcJavaClassMappings.put( Float.class, Types.REAL ); jdbcJavaClassMappings.put( Double.class, Types.DOUBLE ); jdbcJavaClassMappings.put( byte[].class, Types.LONGVARBINARY ); - jdbcJavaClassMappings.put( Date.class, Types.DATE ); + jdbcJavaClassMappings.put( java.sql.Date.class, Types.DATE ); jdbcJavaClassMappings.put( Time.class, Types.TIME ); jdbcJavaClassMappings.put( Timestamp.class, Types.TIMESTAMP ); jdbcJavaClassMappings.put( Blob.class, Types.BLOB ); @@ -123,7 +122,7 @@ private static ConcurrentHashMap buildJdbcJavaClassMappings() { jdbcJavaClassMappings.put( char[].class, Types.VARCHAR ); jdbcJavaClassMappings.put( Character[].class, Types.VARCHAR ); jdbcJavaClassMappings.put( Byte[].class, Types.LONGVARBINARY ); - jdbcJavaClassMappings.put( Date.class, Types.TIMESTAMP ); + jdbcJavaClassMappings.put( java.util.Date.class, Types.TIMESTAMP ); jdbcJavaClassMappings.put( Calendar.class, Types.TIMESTAMP ); return jdbcJavaClassMappings; diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java b/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java index 3f3e63080f9d..32ad6fa3c788 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/Sized.java @@ -23,7 +23,7 @@ */ package org.hibernate.usertype; -import org.hibernate.metamodel.relational.Size; +import org.hibernate.metamodel.spi.relational.Size; /** * Extends dictated/default column size declarations from {@link org.hibernate.type.Type} to the {@link UserType} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractUnifiedBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractUnifiedBinder.java new file mode 100644 index 000000000000..2354cd373475 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractUnifiedBinder.java @@ -0,0 +1,181 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import java.io.InputStream; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.transform.Source; +import javax.xml.validation.Schema; + +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.xml.internal.stax.BufferedXMLEventReader; +import org.hibernate.xml.internal.stax.LocalXmlResourceResolver; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.UnifiedBinder; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractUnifiedBinder implements UnifiedBinder { + private final boolean validateXml; + + protected AbstractUnifiedBinder() { + this( true ); + } + + protected AbstractUnifiedBinder(boolean validateXml) { + this.validateXml = validateXml; + } + + public boolean isValidationEnabled() { + return validateXml; + } + + @Override + public T bind(InputStream stream, Origin origin) { + final XMLEventReader eventReader = createReader( stream, origin ); + return doBind( eventReader, origin ); + } + + protected XMLEventReader createReader(InputStream stream, Origin origin) { + try { + // create a standard StAX reader + final XMLEventReader staxReader = staxFactory().createXMLEventReader( stream ); + // and wrap it in a buffered reader (keeping 100 element sized buffer) + return new BufferedXMLEventReader( staxReader, 100 ); + } + catch ( XMLStreamException e ) { + throw new MappingException( "Unable to create stax reader", e, origin ); + } + } + + @Override + public T bind(Source source, Origin origin) { + final XMLEventReader eventReader = createReader( source, origin ); + return doBind( eventReader, origin ); + } + + protected XMLEventReader createReader(Source source, Origin origin) { + try { + // create a standard StAX reader + final XMLEventReader staxReader = staxFactory().createXMLEventReader( source ); + // and wrap it in a buffered reader (keeping 100 element sized buffer) + return new BufferedXMLEventReader( staxReader, 100 ); + } + catch ( XMLStreamException e ) { + throw new MappingException( "Unable to create stax reader", e, origin ); + } + } + + private T doBind(XMLEventReader eventReader, Origin origin) { + try { + final StartElement rootElementStartEvent = seekRootElementStartEvent( eventReader, origin ); + return doBind( eventReader, rootElementStartEvent, origin ); + } + finally { + try { + eventReader.close(); + } + catch ( Exception ignore ) { + } + } + } + + private XMLInputFactory staxFactory; + + private XMLInputFactory staxFactory() { + if ( staxFactory == null ) { + staxFactory = buildStaxFactory(); + } + return staxFactory; + } + + @SuppressWarnings( { "UnnecessaryLocalVariable" }) + private XMLInputFactory buildStaxFactory() { + XMLInputFactory staxFactory = XMLInputFactory.newInstance(); + staxFactory.setXMLResolver( LocalXmlResourceResolver.INSTANCE ); + return staxFactory; + } + + protected StartElement seekRootElementStartEvent(XMLEventReader staxEventReader, Origin origin) { + XMLEvent rootElementStartEvent; + try { + rootElementStartEvent = staxEventReader.peek(); + while ( rootElementStartEvent != null && !rootElementStartEvent.isStartElement() ) { + staxEventReader.nextEvent(); + rootElementStartEvent = staxEventReader.peek(); + } + } + catch ( Exception e ) { + throw new MappingException( "Error accessing stax stream", e, origin ); + } + + if ( rootElementStartEvent == null ) { + throw new MappingException( "Could not locate root element", origin ); + } + + return rootElementStartEvent.asStartElement(); + } + + protected abstract T doBind(XMLEventReader staxEventReader, StartElement rootElementStartEvent, Origin origin); + + protected static boolean hasNamespace(StartElement startElement) { + return ! "".equals( startElement.getName().getNamespaceURI() ); + } + + @SuppressWarnings("unchecked") + protected T jaxb(XMLEventReader reader, Schema xsd, Class modelClass, Origin origin) { + final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler(); + + try { + final JAXBContext jaxbContext = JAXBContext.newInstance( modelClass ); + final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + if ( isValidationEnabled() ) { + unmarshaller.setSchema( xsd ); + } + else { + unmarshaller.setSchema( null ); + } + unmarshaller.setEventHandler( handler ); + + return (T) unmarshaller.unmarshal( reader ); + } + catch ( JAXBException e ) { + throw new MappingException( + "Unable to perform unmarshalling at line number " + handler.getLineNumber() + + " and column " + handler.getColumnNumber() + + ". Message: " + handler.getMessage(), + e, + origin + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java new file mode 100644 index 000000000000..ea08f76af912 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java @@ -0,0 +1,195 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import java.io.InputStream; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.validation.Schema; + +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.xml.internal.stax.BufferedXMLEventReader; +import org.hibernate.xml.internal.stax.LocalXmlResourceResolver; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.XmlBinder; + +import org.jboss.logging.Logger; + +/** + * Base implementation (template) of the XmlBinder contract. + *

    + * Generally implementors should just have to implement:

      + *
    1. {@link #getJaxbContext}
    2. + *
    3. {@link #getSchema}
    4. + *
    5. (optionally) {@link #wrapReader}
    6. + *
    + * + * @author Steve Ebersole + * @author Strong Liu + * + * @deprecated See {@link AbstractUnifiedBinder} + */ +@Deprecated +abstract class AbstractXmlBinder implements XmlBinder { + protected static final Logger log = Logger.getLogger( AbstractXmlBinder.class ); + + protected final ServiceRegistry serviceRegistry; + protected final boolean validateXml; + + public AbstractXmlBinder(ServiceRegistry serviceRegistry) { + this( serviceRegistry, true ); + } + + public AbstractXmlBinder(ServiceRegistry serviceRegistry, boolean validateXml) { + this.serviceRegistry = serviceRegistry; + this.validateXml = validateXml; + } + + @Override + public BindResult bind(InputStream stream, Origin origin) { + try { + BufferedXMLEventReader staxReader = new BufferedXMLEventReader(staxFactory().createXMLEventReader( stream ), 100); + try { + return unmarshal( staxReader, origin ); + } + finally { + try { + staxReader.close(); + } + catch ( Exception ignore ) { + } + } + } + catch ( XMLStreamException e ) { + throw new MappingException( "Unable to create stax reader", e, origin ); + } + } + + private XMLInputFactory staxFactory; + + private XMLInputFactory staxFactory() { + if ( staxFactory == null ) { + staxFactory = buildStaxFactory(); + } + return staxFactory; + } + + @SuppressWarnings( { "UnnecessaryLocalVariable" }) + private XMLInputFactory buildStaxFactory() { + XMLInputFactory staxFactory = XMLInputFactory.newInstance(); + staxFactory.setXMLResolver( LocalXmlResourceResolver.INSTANCE ); + return staxFactory; + } + + @SuppressWarnings( { "unchecked" }) + private BindResult unmarshal(XMLEventReader staxEventReader, final Origin origin) { + XMLEvent rootElementStartEvent; + try { + rootElementStartEvent = staxEventReader.peek(); + while ( rootElementStartEvent != null && !rootElementStartEvent.isStartElement() ) { + staxEventReader.nextEvent(); + rootElementStartEvent = staxEventReader.peek(); + } + } + catch ( Exception e ) { + throw new MappingException( "Error accessing stax stream", e, origin ); + } + + if ( rootElementStartEvent == null ) { + throw new MappingException( "Could not locate root element", origin ); + } + + + final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler(); + try { + final Schema schema = getSchema( rootElementStartEvent, origin ); + staxEventReader = wrapReader( staxEventReader, rootElementStartEvent ); + + final JAXBContext jaxbContext = getJaxbContext( rootElementStartEvent ); + final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setSchema( schema ); + unmarshaller.setEventHandler( handler ); + + final Object target = unmarshaller.unmarshal( staxEventReader ); + return new BindResult( target, origin ); + } + catch ( JAXBException e ) { + throw new MappingException( + "Unable to perform unmarshalling at line number " + handler.getLineNumber() + + " and column " + handler.getColumnNumber() + + ". Message: " + handler.getMessage(), + e, + origin + ); + } + } + + /** + * Identify the Schema to use to validate the document being processed. + * + * @param rootElementStartEvent The peeked event that represents the start of the root element of the document + * @param origin + * + * @return + * + * @throws JAXBException + */ + protected abstract Schema getSchema(XMLEvent rootElementStartEvent, Origin origin) throws JAXBException; + + /** + * Wrap the given StAX event reader in another if needed. + * + * @param xmlEventReader The "real" reader. + * @param rootElementStartEvent The peeked event that represents the start of the root element of the document + * + * @return The wrapped reader. Simply return the given reader if no wrapping is needed. + */ + protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent rootElementStartEvent) { + return xmlEventReader; + } + + /** + * Get the JAXB context representing the Java model to bind to. + * + * @param event + * + * @return + * + * @throws JAXBException + */ + protected abstract JAXBContext getJaxbContext(XMLEvent event) throws JAXBException; + + protected static boolean isNamespaced(StartElement startElement) { + return ! "".equals( startElement.getName().getNamespaceURI() ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java new file mode 100644 index 000000000000..19cd9508135d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.XMLEvent; +import javax.xml.validation.Schema; + +import org.jboss.logging.Logger; + +import org.hibernate.xml.internal.stax.LocalSchemaLocator; +import org.hibernate.xml.spi.Origin; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; +import org.hibernate.service.ServiceRegistry; + +/** + * @author Steve Ebersole + */ +public class ConfigurationXmlBinder extends AbstractXmlBinder { + private static final Logger log = Logger.getLogger( ConfigurationXmlBinder.class ); + + public static final String HIBERNATE_CONFIGURATION_URI = "http://www.hibernate.org/xsd/hibernate-configuration"; + + + public ConfigurationXmlBinder(ServiceRegistry serviceRegistry) { + this( serviceRegistry, true ); + } + + public ConfigurationXmlBinder(ServiceRegistry serviceRegistry, boolean validateXml) { + super(serviceRegistry, validateXml); + } + + @Override + protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent event) { + if ( !isNamespaced( event.asStartElement() ) ) { + // if the elements are not namespaced, wrap the reader in a reader which will namespace them as pulled. + log.debug( "cfg.xml document did not define namespaces; wrapping in custom event reader to introduce namespace information" ); + return new NamespaceAddingEventReader( xmlEventReader, HIBERNATE_CONFIGURATION_URI ); + } + return super.wrapReader( xmlEventReader, event ); + } + + @Override + protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException{ + return JAXBContext.newInstance( JaxbHibernateConfiguration.class ); + } + + @Override + protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException { + if ( schema == null ) { + schema = LocalSchemaLocator.resolveLocalSchema( "org/hibernate/hibernate-configuration-4.0.xsd" ); + } + return schema; + } + + private Schema schema; + + + + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ContextProvidingValidationEventHandler.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ContextProvidingValidationEventHandler.java new file mode 100644 index 000000000000..96f5eceb54e4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ContextProvidingValidationEventHandler.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import javax.xml.bind.ValidationEvent; +import javax.xml.bind.ValidationEventHandler; +import javax.xml.bind.ValidationEventLocator; + +/** + * ValidationEventHandler implementation providing easier access to where (line/column) an error occurred. + * + * @author Steve Ebersole + */ +class ContextProvidingValidationEventHandler implements ValidationEventHandler { + private int lineNumber; + private int columnNumber; + private String message; + + @Override + public boolean handleEvent(ValidationEvent validationEvent) { + ValidationEventLocator locator = validationEvent.getLocator(); + lineNumber = locator.getLineNumber(); + columnNumber = locator.getColumnNumber(); + message = validationEvent.getMessage(); + return false; + } + + public int getLineNumber() { + return lineNumber; + } + + public int getColumnNumber() { + return columnNumber; + } + + public String getMessage() { + return message; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/HbmEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/HbmEventReader.java new file mode 100644 index 000000000000..8cd26571f1bc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/HbmEventReader.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; + +import org.hibernate.xml.internal.stax.LocalSchema; + +/** + * @author Steve Ebersole + */ +public class HbmEventReader extends EventReaderDelegate { + private static final List NAMESPACE_URIS_TO_MAP = Arrays.asList( + // the initial (premature) hbm.xml xsd namespace + "http://www.hibernate.org/xsd/hibernate-mapping" + ); + + private final XMLEventFactory xmlEventFactory; + + public HbmEventReader(XMLEventReader reader) { + this( reader, XMLEventFactory.newInstance() ); + } + + public HbmEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory) { + super( reader ); + this.xmlEventFactory = xmlEventFactory; + } + + @Override + public XMLEvent peek() throws XMLStreamException { + return wrap( super.peek() ); + } + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + return wrap( super.nextEvent() ); + } + + private XMLEvent wrap(XMLEvent event) { + if ( event != null && event.isStartElement() ) { + return applyNamespace( event.asStartElement() ); + } + return event; + } + + @SuppressWarnings("unchecked") + private StartElement applyNamespace(StartElement startElement) { + final List targetNamespaces = new ArrayList(); + + if ( "".equals( startElement.getName().getNamespaceURI() ) ) { + // add the default namespace mapping + targetNamespaces.add( xmlEventFactory.createNamespace( LocalSchema.HBM.getNamespaceUri() ) ); + } + + // transfer any namespaces directly, unless it is in the "to map" list in which case + // we transfer a mapped copy pointing to the new namespace + final Iterator originalNamespaces = startElement.getNamespaces(); + while ( originalNamespaces.hasNext() ) { + Namespace namespace = originalNamespaces.next(); + if ( NAMESPACE_URIS_TO_MAP.contains( namespace.getNamespaceURI() ) ) { + // this is a namespace "to map" so map it + namespace = xmlEventFactory.createNamespace( namespace.getPrefix(), LocalSchema.HBM.getNamespaceUri() ); + } + targetNamespaces.add( namespace ); + } + + return xmlEventFactory.createStartElement( + new QName( LocalSchema.HBM.getNamespaceUri(), startElement.getName().getLocalPart() ), + startElement.getAttributes(), + targetNamespaces.iterator() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/LegacyJPAEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/LegacyJPAEventReader.java new file mode 100644 index 000000000000..e95bff9bda19 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/LegacyJPAEventReader.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; + +import org.hibernate.xml.internal.stax.LocalXmlResourceResolver; + +/** + * + * We're lying to the xml validator here :D + *

    + * + * Since JPA 2.1 changed its orm.xml namespace, so to support all versions + *

      + *
    • 1.0
    • + *
    • 2.0
    • + *
    • 2.1
    • + *
    + * + * the validator must recognize all of these two namespaces. + * + * but it is very hard to do that, so we're making an assumption (because I really don't konw if this is true or not) + * here that JPA 2.1 is backward compatible w/ the old releases. + * + * So, there it comes, we just simply remove all legacy namespaces if it is an orm.xml and add the expected namespace + * , here is it JPA 2.1, to every elements in the xml. + * + * Finally, for the xml validator, it always see the JPA 2.1 namespace only, and it would be happy to do the validation. + * + *

    + * {@see HHH-8108} for more discussion. + * + * @author Strong Liu + */ +public class LegacyJPAEventReader extends EventReaderDelegate { + private final XMLEventFactory xmlEventFactory; + private final String namespaceUri; + + public LegacyJPAEventReader(XMLEventReader reader, String namespaceUri) { + this( reader, XMLEventFactory.newInstance(), namespaceUri ); + } + + public LegacyJPAEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory, String namespaceUri) { + super( reader ); + this.xmlEventFactory = xmlEventFactory; + this.namespaceUri = namespaceUri; + } + + private StartElement withNamespace(StartElement startElement) { + + Iterator attributes; + Iterator namespacesItr; + if ( "entity-mappings".equals( startElement.getName().getLocalPart() ) ) { + List st = new ArrayList(); + Iterator itr = startElement.getAttributes(); + while ( itr.hasNext() ) { + Attribute obj = (Attribute) itr.next(); + if ( "version".equals( obj.getName().getLocalPart() ) ) { + if ( "".equals( obj.getName().getPrefix() ) ) { + st.add( xmlEventFactory.createAttribute( obj.getName(), "2.1" ) ); + } + } + else { + st.add( obj ); + } + } + attributes = st.iterator(); + // otherwise, wrap the start element event to provide a default namespace mapping + final List namespaces = new ArrayList(); + namespaces.add( xmlEventFactory.createNamespace( "", namespaceUri ) ); + Iterator originalNamespaces = startElement.getNamespaces(); + while ( originalNamespaces.hasNext() ) { + Namespace ns = (Namespace) originalNamespaces.next(); + if ( !LocalXmlResourceResolver.INITIAL_JPA_ORM_NS.equals( ns.getNamespaceURI() ) ) { + namespaces.add( ns ); + } + } + namespacesItr = namespaces.iterator(); + } else { + attributes = startElement.getAttributes(); + namespacesItr = startElement.getNamespaces(); + } + + return xmlEventFactory.createStartElement( + new QName( namespaceUri, startElement.getName().getLocalPart() ), + attributes, + namespacesItr + ); + } + + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + return wrap( super.nextEvent() ); + } + private XMLEvent wrap(XMLEvent event) { + if ( event!=null && event.isStartElement() ) { + return withNamespace( event.asStartElement() ); + } + return event; + } + + @Override + public XMLEvent peek() throws XMLStreamException { + return wrap( super.peek() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java new file mode 100644 index 000000000000..f5302a60e8fe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java @@ -0,0 +1,156 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.XMLEvent; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.xml.internal.stax.LocalSchema; +import org.hibernate.xml.internal.stax.SupportedOrmXsdVersion; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Loads {@code hbm.xml} and {@code orm.xml} files and processes them using StAX and JAXB. + * + * @author Steve Ebersole + * @author Hardy Ferentschik + * + * @deprecated see {@link org.hibernate.xml.internal.jaxb.UnifiedMappingBinder} + */ +@Deprecated +public class MappingXmlBinder extends AbstractXmlBinder { + public MappingXmlBinder(ServiceRegistry serviceRegistry) { + this( serviceRegistry, true ); + } + + public MappingXmlBinder(ServiceRegistry serviceRegistry, boolean validateXml) { + super(serviceRegistry, validateXml); + } + + @Override + protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException { + final String elementName = event.asStartElement().getName().getLocalPart(); + final Class jaxbTarget; + if ( "entity-mappings".equals( elementName ) ) { + jaxbTarget = JaxbEntityMappings.class; + } + else { + jaxbTarget = JaxbHibernateMapping.class; + } + return JAXBContext.newInstance( jaxbTarget ); + } + + @Override + protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException { + final String elementName = event.asStartElement().getName().getLocalPart(); + final Schema validationSchema; + if ( "entity-mappings".equals( elementName ) ) { + return LocalSchema.MAPPING.getSchema(); + } + else { + validationSchema = validateXml ? SupportedOrmXsdVersion.HBM_4_0.getSchema() : null; + } + return validationSchema; + } + + @Override + protected XMLEventReader wrapReader(XMLEventReader staxEventReader, XMLEvent event) { + final String elementName = event.asStartElement().getName().getLocalPart(); + if ( "entity-mappings".equals( elementName ) ) { + return new UnifiedMappingEventReader( staxEventReader ); + } + else { + return new HbmEventReader( staxEventReader ); + } + } + + + @SuppressWarnings( { "unchecked" }) + public BindResult bind(Document document, Origin origin) { + Element rootElement = document.getDocumentElement(); + if ( rootElement == null ) { + throw new MappingException( "No root element found", origin ); + } + + final Schema validationSchema; + final Class jaxbTarget; + + if ( "entity-mappings".equals( rootElement.getNodeName() ) ) { + final String explicitVersion = rootElement.getAttribute( "version" ); + validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion, origin ) : null; + jaxbTarget = JaxbEntityMappings.class; + } + else { + validationSchema = validateXml ? SupportedOrmXsdVersion.HBM_4_0.getSchema() : null; + jaxbTarget = JaxbHibernateMapping.class; + } + + final Object target; + try { + JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + unmarshaller.setSchema( validationSchema ); + target = unmarshaller.unmarshal( new DOMSource( document ) ); + } + catch ( JAXBException e ) { + throw new MappingException( "Unable to perform unmarshalling", e, origin ); + } + + return new BindResult( target, origin ); + } + + private Schema resolveSupportedOrmXsd(String explicitVersion, Origin origin) { + if ( StringHelper.isEmpty( explicitVersion ) ) { + return SupportedOrmXsdVersion.ORM_2_1.getSchema(); + } + + // Here we always use JPA 2.1 schema to do the validation, since the {@link LegacyJPAEventReader} already + // transforms the legacy orm.xml to JPA 2.1 namespace and version. + // + // This may cause some problems, like a jpa 1.0 orm.xml having some element which is only available in the later + // version. It is "invalid" but due to the fact we're using the latest schema to do the validation, then + // it is "valid". Don't know if this will cause any problems, but let's do it for now. + // + // However, still check for the validity of the version by calling #parse. If someone explicitly uses a value + // that doesn't exist, we still need to throw the exception. + SupportedOrmXsdVersion.parse( explicitVersion, origin ); + + return SupportedOrmXsdVersion.ORM_2_1.getSchema(); + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/NamespaceAddingEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/NamespaceAddingEventReader.java new file mode 100644 index 000000000000..b67345fc0bc2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/NamespaceAddingEventReader.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; + +/** + * Used to wrap a StAX {@link XMLEventReader} in order to introduce namespaces into the underlying document. This + * is intended for temporary migration feature to allow legacy HBM mapping documents (DTD-based) to continue to + * parse correctly. This feature will go away eventually. + * + * @author Steve Ebersole + */ +public class NamespaceAddingEventReader extends EventReaderDelegate { + private final XMLEventFactory xmlEventFactory; + private final String namespaceUri; + + public NamespaceAddingEventReader(XMLEventReader reader, String namespaceUri) { + this( reader, XMLEventFactory.newInstance(), namespaceUri ); + } + + public NamespaceAddingEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory, String namespaceUri) { + super( reader ); + this.xmlEventFactory = xmlEventFactory; + this.namespaceUri = namespaceUri; + } + + private StartElement withNamespace(StartElement startElement) { + // otherwise, wrap the start element event to provide a default namespace mapping + final List namespaces = new ArrayList(); + namespaces.add( xmlEventFactory.createNamespace( "", namespaceUri ) ); + Iterator originalNamespaces = startElement.getNamespaces(); + while ( originalNamespaces.hasNext() ) { + Namespace ns = (Namespace) originalNamespaces.next(); + namespaces.add( ns ); + } + return xmlEventFactory.createStartElement( + new QName( namespaceUri, startElement.getName().getLocalPart() ), + startElement.getAttributes(), + namespaces.iterator() + ); + } + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + return wrap( super.nextEvent() ); + } + + private XMLEvent wrap(XMLEvent event) { + if ( event.isStartElement() ) { + return withNamespace( event.asStartElement() ); + } + return event; + } + + @Override + public XMLEvent peek() throws XMLStreamException { + return wrap( super.peek() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java new file mode 100644 index 000000000000..22cdd3390c60 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + +import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; +import org.hibernate.metamodel.source.internal.jaxb.hbm.HbmXmlTransformer; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.xml.internal.stax.LocalSchema; +import org.hibernate.xml.spi.Origin; + +import org.jboss.logging.Logger; + +/** + * Binder for the unified orm.xml schema + * + * @author Steve Ebersole + */ +public class UnifiedMappingBinder extends AbstractUnifiedBinder { + private static final Logger log = Logger.getLogger( UnifiedMappingBinder.class ); + + public UnifiedMappingBinder() { + super(); + } + + public UnifiedMappingBinder(boolean validateXml) { + super( validateXml ); + } + + @Override + protected JaxbEntityMappings doBind( + XMLEventReader staxEventReader, + StartElement rootElementStartEvent, + Origin origin) { + final String rootElementLocalName = rootElementStartEvent.getName().getLocalPart(); + if ( "hibernate-mapping".equals( rootElementLocalName ) ) { + // todo: finalize message test here, and possibly use a message logger + log.debug( + "Found legacy Hibernate hbm.xml mapping; performing on-the-fly transformation. " + + "Consider using build-time transformation tool to speed up run-time parsing" + ); + + XMLEventReader hbmReader = new HbmEventReader( staxEventReader ); + JaxbHibernateMapping hbmBindings = jaxb( hbmReader, LocalSchema.HBM.getSchema(), JaxbHibernateMapping.class, origin ); + return HbmXmlTransformer.INSTANCE.transform( hbmBindings, origin ); + } + else { + final XMLEventReader reader = new UnifiedMappingEventReader( staxEventReader ); + return jaxb( reader, LocalSchema.MAPPING.getSchema(), JaxbEntityMappings.class, origin ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingEventReader.java new file mode 100644 index 000000000000..48624ea40eb9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingEventReader.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.jaxb; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; + +import org.hibernate.xml.internal.stax.LocalSchema; + +import org.jboss.logging.Logger; + +/** + * @author Steve Ebersole + */ +public class UnifiedMappingEventReader extends EventReaderDelegate { + private static final Logger log = Logger.getLogger( UnifiedMappingEventReader.class ); + + private static final List JPA_NAMESPACE_URIS = Arrays.asList( + // JPA 1.0 and 2.0 namespace uri + "http://java.sun.com/xml/ns/persistence/orm", + // JPA 2.1 namespace uri + "http://xmlns.jcp.org/xml/ns/persistence/orm" + ); + + private final XMLEventFactory xmlEventFactory; + + public UnifiedMappingEventReader(XMLEventReader reader) { + this( reader, XMLEventFactory.newInstance() ); + } + + public UnifiedMappingEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory) { + super( reader ); + this.xmlEventFactory = xmlEventFactory; + } + + @Override + public XMLEvent peek() throws XMLStreamException { + return wrap( super.peek() ); + } + + @Override + public XMLEvent nextEvent() throws XMLStreamException { + return wrap( super.nextEvent() ); + } + + private XMLEvent wrap(XMLEvent event) { + if ( event != null && event.isStartElement() ) { + return applyNamespace( event.asStartElement() ); + } + return event; + } + + @SuppressWarnings("unchecked") + private StartElement applyNamespace(StartElement startElement) { + Iterator attributesItr; + Iterator namespacesItr; + + if ( "entity-mappings".equals( startElement.getName().getLocalPart() ) ) { + final List targetNamespaces = new ArrayList(); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // namespaces are a little more complicated. We copy over all namespaces, + // but if any uris match known JPA namespaces which point that given + // prefix to our namespace instead. + final Iterator originalNamespaces = startElement.getNamespaces(); + while ( originalNamespaces.hasNext() ) { + Namespace namespace = originalNamespaces.next(); + if ( JPA_NAMESPACE_URIS.contains( namespace.getNamespaceURI() ) ) { + // this namespace was recognized as a "JPA namespace" by uri, + // so map our unified namespace uri to that prefix + namespace = xmlEventFactory.createNamespace( namespace.getPrefix(), LocalSchema.MAPPING.getNamespaceUri() ); + } + targetNamespaces.add( namespace ); + } + + attributesItr = startElement.getAttributes(); + namespacesItr = targetNamespaces.iterator(); + } + else { + attributesItr = startElement.getAttributes(); + namespacesItr = startElement.getNamespaces(); + } + + final StartElement adjusted = xmlEventFactory.createStartElement( + new QName( LocalSchema.MAPPING.getNamespaceUri(), startElement.getName().getLocalPart() ), + attributesItr, + namespacesItr + ); + if ( log.isDebugEnabled() ) { + log.debugf( "Created new StartElement with adjusted namespace : %s ", adjusted ); + } + return adjusted; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/BaseXMLEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/BaseXMLEventReader.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/BaseXMLEventReader.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/BaseXMLEventReader.java index e77971bf4b17..6962eadd882f 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/BaseXMLEventReader.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/BaseXMLEventReader.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLStreamConstants; @@ -67,9 +67,6 @@ public final XMLEvent nextEvent() throws XMLStreamException { return this.previousEvent; } - /* (non-Javadoc) - * @see java.util.Iterator#next() - */ @Override public final Object next() { try { @@ -80,9 +77,6 @@ public final Object next() { } } - /* (non-Javadoc) - * @see javax.xml.stream.XMLEventReader#getElementText() - */ @Override public final String getElementText() throws XMLStreamException { XMLEvent event = this.previousEvent; @@ -125,9 +119,6 @@ public final String getElementText() throws XMLStreamException { return text.toString(); } - /* (non-Javadoc) - * @see javax.xml.stream.XMLEventReader#nextTag() - */ @Override public final XMLEvent nextTag() throws XMLStreamException { XMLEvent event = this.nextEvent(); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/BufferedXMLEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/BufferedXMLEventReader.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/BufferedXMLEventReader.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/BufferedXMLEventReader.java index 91ea8cf8ba5d..d3b6524ddc08 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/BufferedXMLEventReader.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/BufferedXMLEventReader.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import java.util.ArrayList; import java.util.LinkedList; @@ -67,9 +67,6 @@ public List getBuffer() { return new ArrayList(this.eventBuffer); } - /* (non-Javadoc) - * @see org.jasig.portal.xml.stream.BaseXMLEventReader#internalNextEvent() - */ @Override protected XMLEvent internalNextEvent() throws XMLStreamException { //If there is an iterator to read from reset was called, use the iterator diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/FilteringXMLEventReader.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/FilteringXMLEventReader.java similarity index 99% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/FilteringXMLEventReader.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/FilteringXMLEventReader.java index 6e2e07be4449..5ed91d987e3b 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/FilteringXMLEventReader.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/FilteringXMLEventReader.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import java.util.Deque; import java.util.LinkedList; diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalSchema.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalSchema.java new file mode 100644 index 000000000000..84f52423d583 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalSchema.java @@ -0,0 +1,122 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.stax; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.jboss.logging.Logger; + +/** + * @author Steve Ebersole + */ +public enum LocalSchema { + MAPPING( + "http://www.hibernate.org/xsd/orm/mapping", + "org/hibernate/xsd/mapping/mapping-2.1.0.xsd", + "2.1.0" + ), + HBM( + "http://www.hibernate.org/xsd/orm/hbm", + "org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd", + "4.0" + ) +// , CONFIGURATION( ) +// , CFG( ) + ; + + private static final Logger log = Logger.getLogger( LocalSchema.class ); + + private final String namespaceUri; + private final String localResourceName; + private final String currentVersion; + private final Schema schema; + + LocalSchema(String namespaceUri, String localResourceName, String currentVersion) { + this.namespaceUri = namespaceUri; + this.localResourceName = localResourceName; + this.currentVersion = currentVersion; + this.schema = resolveLocalSchema( localResourceName ); + } + + public String getNamespaceUri() { + return namespaceUri; + } + + public String getCurrentVersion() { + return currentVersion; + } + + public Schema getSchema() { + return schema; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // todo : centralize this... + // this is all a general case of wanting to resolve resources strictly + // using the ClassLoader + + private static javax.xml.validation.Schema resolveLocalSchema(String schemaName) { + return resolveLocalSchema( resolveLocalSchemaUrl( schemaName ) ); + } + + private static URL resolveLocalSchemaUrl(String schemaName) { + URL url = LocalSchemaLocator.class.getClassLoader().getResource( schemaName ); + if ( url == null ) { + throw new XmlInfrastructureException( "Unable to locate schema [" + schemaName + "] via classpath" ); + } + return url; + } + + private static javax.xml.validation.Schema resolveLocalSchema(URL schemaUrl) { + try { + InputStream schemaStream = schemaUrl.openStream(); + try { + StreamSource source = new StreamSource( schemaUrl.openStream() ); + SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); + return schemaFactory.newSchema( source ); + } + catch (Exception e) { + throw new XmlInfrastructureException( "Unable to load schema [" + schemaUrl.toExternalForm() + "]", e ); + } + finally { + try { + schemaStream.close(); + } + catch (IOException e) { + log.debugf( "Problem closing schema stream - %s", e.toString() ); + } + } + } + catch (IOException e) { + throw new XmlInfrastructureException( "Stream error handling schema url [" + schemaUrl.toExternalForm() + "]" ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalSchemaLocator.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalSchemaLocator.java new file mode 100644 index 000000000000..66227d18958c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalSchemaLocator.java @@ -0,0 +1,99 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.stax; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.jboss.logging.Logger; + +/** + * Helper for resolving XML Schema references locally. + *

    + * Note that *by design* we always use our ClassLoader to perform the lookups here. + * + * @author Steve Ebersole + * + * @deprecated No longer used. Because of the move to "unified" XML processing, references on {@link LocalSchema} + * are all that are needed + */ +@Deprecated +public class LocalSchemaLocator { + private static final Logger log = Logger.getLogger( LocalSchemaLocator.class ); + + /** + * Disallow direct instantiation + */ + private LocalSchemaLocator() { + } + + /** + * Given the resource name of a schema, locate its URL reference via ClassLoader lookup. + * + * @param schemaName + * + * @return + */ + public static URL resolveLocalSchemaUrl(String schemaName) { + URL url = LocalSchemaLocator.class.getClassLoader().getResource( schemaName ); + if ( url == null ) { + throw new XmlInfrastructureException( "Unable to locate schema [" + schemaName + "] via classpath" ); + } + return url; + } + + public static Schema resolveLocalSchema(String schemaName){ + return resolveLocalSchema( resolveLocalSchemaUrl( schemaName ) ); + } + + public static Schema resolveLocalSchema(URL schemaUrl) { + try { + InputStream schemaStream = schemaUrl.openStream(); + try { + StreamSource source = new StreamSource(schemaUrl.openStream()); + SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); + return schemaFactory.newSchema(source); + } + catch ( Exception e ) { + throw new XmlInfrastructureException( "Unable to load schema [" + schemaUrl.toExternalForm() + "]", e ); + } + finally { + try { + schemaStream.close(); + } + catch ( IOException e ) { + log.debugf( "Problem closing schema stream - %s", e.toString() ); + } + } + } + catch ( IOException e ) { + throw new XmlInfrastructureException( "Stream error handling schema url [" + schemaUrl.toExternalForm() + "]" ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/LocalXmlResourceResolver.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalXmlResourceResolver.java similarity index 90% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/LocalXmlResourceResolver.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalXmlResourceResolver.java index 1cd8ecb2cb59..cb49b0db26c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/LocalXmlResourceResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/LocalXmlResourceResolver.java @@ -21,26 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import java.io.IOException; import java.io.InputStream; import java.net.URL; import javax.xml.stream.XMLStreamException; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ConfigHelper; -import org.jboss.logging.Logger; - /** * @author Steve Ebersole + * + * @deprecated No longer used. "resolvers" to stop remote lookups are no longer needed given the + * way we now process the XML. */ +@Deprecated public class LocalXmlResourceResolver implements javax.xml.stream.XMLResolver { - private static final CoreMessageLogger log = Logger.getMessageLogger( - CoreMessageLogger.class, - MappingReader.class.getName() - ); + private static final CoreMessageLogger log = CoreLogging.messageLogger( LocalXmlResourceResolver.class ); public static final LocalXmlResourceResolver INSTANCE = new LocalXmlResourceResolver(); @@ -65,10 +65,10 @@ public Object resolveEntity(String publicID, String systemID, String baseURI, St if ( namespace != null ) { log.debugf( "Interpreting namespace : %s", namespace ); if ( INITIAL_JPA_ORM_NS.equals( namespace ) ) { - return openUrlStream( MappingReader.SupportedOrmXsdVersion.ORM_2_0.getSchemaUrl() ); + return openUrlStream( SupportedOrmXsdVersion.ORM_2_0.getSchemaUrl() ); } else if ( SECOND_JPA_ORM_NS.equals( namespace ) ) { - return openUrlStream( MappingReader.SupportedOrmXsdVersion.ORM_2_1.getSchemaUrl() ); + return openUrlStream( SupportedOrmXsdVersion.ORM_2_1.getSchemaUrl() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/SupportedOrmXsdVersion.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/SupportedOrmXsdVersion.java new file mode 100644 index 000000000000..a8e1ac74e2c0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/SupportedOrmXsdVersion.java @@ -0,0 +1,83 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.internal.stax; + +import java.net.URL; +import javax.xml.validation.Schema; + +import org.hibernate.xml.spi.Origin; + +/** + * @author Steve Ebersole + */ +public enum SupportedOrmXsdVersion { + ORM_1_0( "org/hibernate/jpa/orm_1_0.xsd" ), + ORM_2_0( "org/hibernate/jpa/orm_2_0.xsd" ), + ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" ), + ORM_2_1_0( "org/hibernate/xsd/mapping/mapping-2.1.0.xsd" ), + HBM_4_0( "org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd" ); + + private final String schemaResourceName; + + SupportedOrmXsdVersion(String schemaResourceName) { + this.schemaResourceName = schemaResourceName; + } + + public static SupportedOrmXsdVersion parse(String name, Origin origin) { + if ( "1.0".equals( name ) ) { + return ORM_1_0; + } + else if ( "2.0".equals( name ) ) { + return ORM_2_0; + } + else if ( "2.1".equals( name ) ) { + return ORM_2_1; + } + else if ( "2.1.0".equals( name ) ) { + return ORM_2_1_0; + } + else if ( "4.0".equals( name ) ) { + return HBM_4_0; + } + throw new UnsupportedOrmXsdVersionException( name, origin ); + } + + private URL schemaUrl; + + public URL getSchemaUrl() { + if ( schemaUrl == null ) { + schemaUrl = LocalSchemaLocator.resolveLocalSchemaUrl( schemaResourceName ); + } + return schemaUrl; + } + + private Schema schema; + + public Schema getSchema() { + if ( schema == null ) { + schema = LocalSchemaLocator.resolveLocalSchema( getSchemaUrl() ); + } + return schema; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/UnsupportedOrmXsdVersionException.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/UnsupportedOrmXsdVersionException.java similarity index 95% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/UnsupportedOrmXsdVersionException.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/UnsupportedOrmXsdVersionException.java index 9fb984929c40..e3d7e4a33d88 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/UnsupportedOrmXsdVersionException.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/UnsupportedOrmXsdVersionException.java @@ -21,9 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import org.hibernate.HibernateException; +import org.hibernate.xml.spi.Origin; /** * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLStreamConstantsUtils.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/XMLStreamConstantsUtils.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLStreamConstantsUtils.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/XMLStreamConstantsUtils.java index ba70312a304c..8aa34c893b1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLStreamConstantsUtils.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/XMLStreamConstantsUtils.java @@ -21,15 +21,11 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import javax.xml.stream.XMLStreamConstants; /** - * - * - * - * * Note, copied from the uPortal project by permission of author. See * https://github.com/Jasig/uPortal/blob/master/uportal-war/src/main/java/org/jasig/portal/xml/stream/XMLStreamConstantsUtils.java * diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlInfrastructureException.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/XmlInfrastructureException.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlInfrastructureException.java rename to hibernate-core/src/main/java/org/hibernate/xml/internal/stax/XmlInfrastructureException.java index b6a3c3040c25..b67862bf7f40 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XmlInfrastructureException.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/XmlInfrastructureException.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.util.xml; +package org.hibernate.xml.internal.stax; import org.hibernate.HibernateException; diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/package-info.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/package-info.java new file mode 100644 index 000000000000..9fddf21bb893 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/stax/package-info.java @@ -0,0 +1,28 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +/** + * Contains basic support for Java XML Processing (JAXP) via Streaming API for XML (StAX) + */ +package org.hibernate.xml.internal.stax; diff --git a/hibernate-core/src/main/java/org/hibernate/xml/package-info.java b/hibernate-core/src/main/java/org/hibernate/xml/package-info.java new file mode 100644 index 000000000000..b26d29314def --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/package-info.java @@ -0,0 +1,28 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +/** + * Contains basic support for consuming XML, mainly for reading configuration and mapping XML. + */ +package org.hibernate.xml; diff --git a/hibernate-core/src/main/java/org/hibernate/xml/spi/BindResult.java b/hibernate-core/src/main/java/org/hibernate/xml/spi/BindResult.java new file mode 100644 index 000000000000..38b0e85ecb06 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/spi/BindResult.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.spi; + +import java.io.Serializable; + +/** + * Return object for the result of performing JAXB binding. + * + * @author Hardy Ferentschik + * @author Steve Ebersole + */ +public class BindResult implements Serializable { + private final T root; + private final Origin origin; + + public BindResult(T root, Origin origin) { + this.root = root; + this.origin = origin; + } + + /** + * Obtain the root JAXB bound object + * + * @return The JAXB root object + */ + public T getRoot() { + return root; + } + + /** + * Obtain the metadata about the document's origin + * + * @return The origin + */ + public Origin getOrigin() { + return origin; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/spi/Origin.java b/hibernate-core/src/main/java/org/hibernate/xml/spi/Origin.java new file mode 100644 index 000000000000..b1a556175fe3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/spi/Origin.java @@ -0,0 +1,92 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.spi; + +import java.io.Serializable; +import java.util.Locale; + +import org.hibernate.internal.util.compare.EqualsHelper; + +/** + * Describes the origin of an xml document + * + * @author Steve Ebersole + */ +public class Origin implements Serializable { + public static final String UNKNOWN_FILE_PATH = ""; + + private final SourceType type; + private final String name; + + public Origin(SourceType type, String name) { + this.type = type; + this.name = name; + } + + /** + * Retrieve the type of origin. + * + * @return The origin type. + */ + public SourceType getType() { + return type; + } + + /** + * The name of the document origin. Interpretation is relative to the type, but might be the + * resource name or file URL. + * + * @return The name. + */ + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof Origin ) ) { + return false; + } + + final Origin other = (Origin) o; + return type == other.type + && EqualsHelper.equals( name, other.name ); + + } + + @Override + public int hashCode() { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + ( name != null ? name.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return String.format( Locale.ENGLISH, "Origin(name=%s,type=%s)", name, type ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/SourceType.java b/hibernate-core/src/main/java/org/hibernate/xml/spi/SourceType.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/internal/jaxb/SourceType.java rename to hibernate-core/src/main/java/org/hibernate/xml/spi/SourceType.java index 32245a3eaa99..9c019ad03934 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/jaxb/SourceType.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/spi/SourceType.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.internal.jaxb; +package org.hibernate.xml.spi; /** * From what type of source did we obtain the data diff --git a/hibernate-core/src/main/java/org/hibernate/xml/spi/UnifiedBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/spi/UnifiedBinder.java new file mode 100644 index 000000000000..5f0ea1276c58 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/spi/UnifiedBinder.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.spi; + +import java.io.InputStream; +import javax.xml.transform.Source; + +/** + * @author Steve Ebersole + */ +public interface UnifiedBinder { + public T bind(InputStream stream, Origin origin); + public T bind(Source source, Origin origin); +} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java new file mode 100644 index 000000000000..a1421ea53976 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.xml.spi; + +import java.io.InputStream; + +/** + * @author Steve Ebersole + */ +public interface XmlBinder { + public BindResult bind(InputStream stream, Origin origin); +} diff --git a/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd b/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd deleted file mode 100644 index ae674404876b..000000000000 --- a/hibernate-core/src/main/resources/org/hibernate/hibernate-mapping-4.0.xsd +++ /dev/null @@ -1,1816 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd new file mode 100644 index 000000000000..7797ee1c6046 --- /dev/null +++ b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd @@ -0,0 +1,1991 @@ + + + + + + An instance of this XML document may contain mappings for an arbitrary + number of classes. The class mappings may contain associations to classes + mapped in the same document or in another document. No class may be + mapped more than once. Each document may also contain definitions of an + arbitrary number of queries, and import declarations of arbitrary classes. + + + + + + + The document root. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Root entity mapping. Poorly named as entities do not have to be represented by + classes at all. Mapped entities may be represented via different methodologies + (POJO, Map, Dom4j). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vs. @name usage... + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vs. @name usage... + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vs. @name usage... + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares the id type, column and generation algorithm for an entity class. + If a name attribut is given, the id is exposed to the application through the + named property of the class. If not, the id is only exposed to the application + via Session.getIdentifier() + + + + + + + + + + + + + + + + + + + + + + + + + A composite key may be modelled by a java class with a property for each + key column. The class must implement java.io.Serializable and reimplement equals() + and hashCode(). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Versioned data requires a column holding a version number. This is exposed to the + application through a property of the Java class. + + + + + + + + + + + + + + + + + + A natural-id element allows declaration of the unique business key + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Collection declarations nested inside a class declaration indicate a foreign key + relationship from the collection table to the enclosing class. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares the type and column mapping for a collection index (array or + list index, or key of a map). + + + + + + + + + + + + + One to many association. This tag declares the entity-class + element type of a collection and specifies a one-to-many relational model + + + + + + + + + + + + + Declares a one-to-one association between two entities (Or from a component, + component element, etc. to an entity). + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares an association between two entities (Or from a component, component element, + etc. to an entity). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Many to many association. This tag declares the entity-class + element type of a collection and specifies a many-to-many relational model + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + allows customized short-naming of IdentifierGenerator implementations. + ]]> + + + + + + + + IMPORT element definition; an explicit query language "import" + + + + + + + + + + + + + + + + + + + + Polymorphic data requires a column holding a class discriminator value. This + value is not directly exposed to the application. + + + + + + + + + + + + + + + + + + + + #2 : + + CREATE OR REPLACE .... + DROP .... + + ]]> + + + + + + + + + + + + + + + + + + + + dialect-scope element allows scoping auxiliary-objects to a particular + Hibernate dialect implementation. + + + + + + + + + + + allows defining a customized type mapping for a Hibernate type. May + contain parameters for parameterizable types. + ]]> + + + + + + + + + + + FILTER-DEF element; top-level filter definition. + + + + + + + + + + + + + + An "any" association is a polymorphic association to any table with + the given identifier type. The first listed column is a VARCHAR column + holding the name of the class (for that row). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The column element is an alternative to column attributes and required for + mapping associations to classes with composite ids. + + + + + + The comment element allows definition of a database table or column comment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A component is a user-defined class, persisted along with its containing entity + to the table of the entity class. JavaBeans style properties of the component are + mapped to columns of the table of the containing entity. A null component reference + is mapped to null values in all columns and vice versa. Components do not support + shared reference semantics. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A composite element allows a collection to hold instances of an arbitrary + class, without the requirement of joining to an entity table. Composite elements + have component semantics - no shared references and ad hoc null value semantics. + Composite elements may not hold nested collections. + + + + + + + + + + + + + + + + + + + + + + + + + + A dynamic-component maps columns of the database entity to a java.util.Map + at the Java level + + + + + + + + + + + + + + + + + + + + + + + + + Declares the element type of a collection of basic type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + element defines a single path to which the fetch + refers, as well as the style of fetch to apply. The 'root' of the + path is different depending upon the context in which the + containing occurs; within a element, + the entity-name of the containing class mapping is assumed... + ]]> + + + + + + + + + + + + + + + + + + FILTER element; used to apply a filter. + + + + + + + + + + + + + + + + + + + + + + + + Generators generate unique identifiers. The class attribute specifies a Java + class implementing an id generation algorithm. + + + + + + + + + + + + + + + + + + + + + + + A join allows some properties of a class to be persisted to a second table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares the column name of a foreign key. + + + + + + + + + + + + + + + + + + A many-to-one association embedded in a composite identifier or map index + (always not-null, never cascade). + + + + + + + + + + + + + + + + + + + + A property embedded in a composite identifier or map index (always not-null). + + + + + + + + + + + + + + + + + + + + The loader element allows specification of a named query to be used for fetching + an entity or collection + + + + + + + + + A "many to any" defines a polymorphic association to any table + with the given identifier type. The first listed column is a VARCHAR column + holding the name of the class (for that row). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Composite index of a map ie. a map keyed on components. + + + + + + + + + + + + + + + + + + + Many to many association mapped to the key of a map. ie. a map keyed + on entities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + is used to assign meta-level attributes to a class + or property. Is currently used by codegenerator as a placeholder for + values that is not directly related to OR mappings. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The parent element maps a property of the component class as a pointer back to + the owning entity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + properties declares that the contained properties form an alternate key. The name + attribute allows an alternate key to be used as the target of a property-ref. + + + + + + + + + + + + + + + + + + + + + + + + + + + Property of an entity class or component, component-element, composite-id, etc. + JavaBeans style properties are mapped to table columns. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The sql-query element declares a named SQL query string + + + + + + + + + + + + + + + + + + + + + + + + + The query element declares a named Hibernate query string + + + + + + + + + + + + + + + + + + + + The query-param element is used only by tools that generate + finder methods for named queries + + + + + + + + + + FILTER-PARAM element; qualifies parameters found within a FILTER-DEF + condition. + + + + + + + + + + The resultset element declares a named resultset mapping definition for SQL queries + + + + + + + + + + + + + + + + + Defines a return component for a sql-query. Alias refers to the alias + used in the actual sql query; lock-mode specifies the locking to be applied + when the query is executed. The class, collection, and role attributes are mutually exclusive; + class refers to the class name of a "root entity" in the object result; collection refers + to a collection of a given class and is used to define custom sql to load that owned collection + and takes the form "ClassName.propertyName"; role refers to the property path for an eager fetch + and takes the form "owningAlias.propertyName" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TUPLIZER element; defines tuplizer to use for a component/entity for a given entity-mode + + + + + + + + + + + Declares the type of the containing property (overrides an eventually existing type + attribute of the property). May contain param elements to customize a ParametrizableType. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Define a class name type which can be used in the attribute value which requires a class name, + either qualified or not, time to do the validation. + + + + + + + diff --git a/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-2.1.0.xsd b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-2.1.0.xsd new file mode 100644 index 000000000000..c01bbdc435ac --- /dev/null +++ b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-2.1.0.xsd @@ -0,0 +1,2470 @@ + + + + + + + ... + + ]]> + + + + + + + + + + The entity-mappings element is the root element of a mapping + file. It contains the following four types of elements: + + 1. The persistence-unit-metadata element contains metadata + for the entire persistence unit. The behavior is undefined if this element + occurs in multiple mapping files within the same persistence unit. + + 2. The package, schema, catalog and access elements apply to all of + the entity, mapped-superclass and embeddable elements defined in + the same file in which they occur. + + 3. The sequence-generator, table-generator, converter, named-query, + named-native-query, named-stored-procedure-query, and + sql-result-set-mapping elements are global to the persistence + unit. + + a. The behavior is undefined when having more than one sequence-generator + or table-generator occur in a persistence unit (whether in the same or + different mapping file). + + b. The behavior is undefined when having more than one named-query, + named-native-query, sql-result-set-mapping, or named-stored-procedure-query + of the same name in a persistence unit (whether in the same or different + mapping file). + + c. The behavior is undefined when having more than one converter for the same + target type in a persistence unit (whether in the same or different mapping file). + + 4. The entity, mapped-superclass and embeddable elements each define + the mapping information for a managed persistent class. The mapping + information contained in these elements may be complete or it may + be partial. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Metadata that applies to the persistence unit and not just to the mapping + file in which it is contained. + + If the xml-mapping-metadata-complete element is specified, + the complete set of mapping metadata for the persistence unit + is contained in the XML mapping files for the persistence unit. + + + + + + + + + + + + + + + These defaults are applied to the persistence unit as a whole unless they + are overridden by local annotation or XML element settings. + + schema - Used as the schema for all tables, secondary tables, join + tables, collection tables, sequence generators, and table + generators that apply to the persistence unit + + catalog - Used as the catalog for all tables, secondary tables, join + tables, collection tables, sequence generators, and table + generators that apply to the persistence unit + + delimited-identifiers - Used to treat database identifiers as + delimited identifiers. + + access - Used as the access type for all managed classes in + the persistence unit + + cascade-persist - Adds cascade-persist to the set of cascade options + in all entity relationships of the persistence unit + + entity-listeners - List of default entity listeners to be invoked + on each entity in the persistence unit. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + javax.persistence.AccessType enum values + + + + + + + + + + + + + + + Hibernate specific "any" mapping, which is a polymorphic association to any different + tables based on a discriminator + + the given identifier type. The first listed column is a VARCHAR column + holding the name of the class (for that row). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.acme.Employee + ]]> + + + + + + + + + + + + + + + This element contains the entity field or property mappings. + It may be sparsely populated to include only a subset of the + fields or properties. If metadata-complete for the entity is true + then the remainder of the attributes will be defaulted according + to the default rules. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.AssociationOverride + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.AttributeOverride + + + + + + + + + + + + + + + + See javax.persistence.Basic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the org.hibernate.annotations.Cache annotation. + + Used to specify Hibernate-specific extra control over the caching + of entity and collection state. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.CacheMode enum values + + + + + + + + + + + + + + + + + + + javax.persistence.CascadeType enum values + + + + + + + + + + + + + + + + + + + @CollectionTable annotation + + + + + + + + + + + + + + + + + + + + + + + See the javax.persistence.Column annotation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.Convert annotation + + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.Converter annotation + + + + + + + + + + + + + + + + @DiscriminatorColumn annotation + + + + + + + + + + + + + + + + + javax.persistence.DiscriminatorType enum values + + + + + + + + + + + + + + + + + @Target({TYPE}) @Retention(RUNTIME) + public @interface DiscriminatorValue { + String value(); + } + + + + + + + + + + + + + Corresponds to the @ElementCollection annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + See javax.persistence.Embeddable + + Defines the settings and mappings for embeddable objects. + + Again, with metadata-complete=false the mapping is used in + conjunction with annotations. Alternatively, metadata-complete=true + can be used to indicate that no annotations are to be processed + in the class. If this is the case then the defaulting rules will + be recursively applied. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.Embedded annotation + + + + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.EmbeddedId annotation + + + + + + + + + + + + + + + + + See javax.persistence.Entity + + Defines the settings and mappings for an entity. + + May be used in 2 ways: + 1. sparsely populated (metadata-complete=false) and used in + conjunction with the annotations. + 2. as complete self-contained metadata (metadata-complete=true) + indicating that no annotations on the entity class (and its fields + or properties) are to be processed. If this is the case then + the defaulting rules for the entity and its subelements will + be recursively applied. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the JPA javax.persistence.EntityListeners annotation + + + + + + + + + + + + + + Corresponds to the JPA javax.persistence.EntityListener annotation + + Defines an entity listener to be invoked at lifecycle events for + the entities that list this listener. + + + + + + + + + + + + + + + + + + + + + + javax.persistence.EnumType enum values + + + + + + + + + + + + + + + Corresponds to the javax.persistence.Enumerated annotation. + + + + + + + + + + + + javax.persistence.FetchType enum values + + + + + + + + + + + + + + + org.hibernate.FlushMode enum values + + + + + + + + + + + + + + + + @ForeignKey annotation + + + + + + + + + + + + + + + + + + See the javax.persistence.GeneratedValue annotation + + + + + + + + + + javax.persistence.GenerationType rnum values + + todo : add custom ones like INCREMENT, UUID, etc + + + + + + + + + + + + + + + + + Hibernate-specific element used declare and short-name custom + org.hibernate.id.IdentifierGenerator implementations + + + + + + + + + + + + + Corresponds to the javax.persistence.Id annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.IdClass annotation + + + + + + + + + + + + Corresponds to @Index annotation + + + + + + + + + + + + + + + + + + + Corresponds to the @Inheritance annotation + + + + + + + + + + + + Corresponds to the JPA InheritanceType enumeration values + Hibernate's UNION_SUBCLASS + + todo : make a singular enum to cover these + + + + + + + + + + + + + + + + + JoinColumn annotation + + + + + + + + + + + + + + + + + + + + @JoinTable annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to javax.persistence.Lob (marker) annotation + + + + + + + + + + + javax.persistence.LockModeType enum values + + + + + + + + + + + + + + + + + + + + + Hibernate specific "any" mapping (plural form), which is a polymorphic association to any different + tables based on a discriminator. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ManyToMany annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the @ManyToOne annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.MapKey + + + + + + + + + + + + @javax.persistence.MapKeyClass + + + + + + + + + + + + + @javax.persistence.MapKeyColumn + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.MapKeyJoinColumn + + + + + + + + + + + + + + + + + + + + See javax.persistence.MappedSuperclass + + Defines the settings and mappings for a mapped superclass. + + May be used in 2 ways: + 1. sparsely populated (metadata-complete=false) and used in + conjunction with the annotations. + 2. as complete self-contained metadata (metadata-complete=true) + indicating that no annotations are to be processed. If this is + the case then the defaulting rules will be recursively applied. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hibernate-specific element used to describe the meta-value (discriminator) + mapping for ANY associations. + + + + + + + + + + + + + + @NamedEntityGraph annotation + + + + + + + + + + + + + + + + + @NamedAttributeNode annotation + + + + + + + + + + + + @NamedSubgraph annotation + + + + + + + + + + + + + + + + + + Common Hibernate specific extensions available for named query definitions. + + todo : a lot of these extensions could be handled by JPA QueryHint scheme + + + + + + + + + + + + + + + + + + + + + + + Mix of @javax.persistence.NamedNativeQuery and @org.hibernate.annotations.NamedNativeQuery + + + + + + + + + + + + + + + + + + + + + + Mix of @javax.persistence.NamedQuery and @org.hibernate.annotations.NamedQuery + + + + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.NamedStoredProcedureQuery annotation + + + + + + + + + + + + + + + + + + + Corresponds to javax.persistence.StoredProcedureParameter annotation + + + + + + + + + + + + + + + + javax.persistence.ParameterMode enum values + + + + + + + + + + + + + + + + + + @OneToMany annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Corresponds to the @OneToOne annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.OrderBy annotation + + + + + + + + + + + + + @javax.persistence.OrderColumn annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PostLoad annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PostPersist annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PostRemove annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PostUpdate annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PrePersist annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PreRemove annotation + + + + + + + + + + + + + + + + + Corresponds to the javax.persistence.PreUpdate annotation + + + + + + + + + + + + + + + + + @PrimaryKeyJoinColumn annotation + + + + + + + + + + + + + + + @javax.persistence.QueryHint + + + + + + + + + + + + + + + + + + Used only by tools to generate finder methods for named queries + + + + + + + + + + + + + + @javax.persistence.SecondaryTable + + + + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.SequenceGenerator + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.SqlResultSetMapping + + + + + + + + + + + + + + + + + + @javax.persistence.ColumnResult + + + + + + + + + + + + @javax.persistence.ConstructorResult + + + + + + + + + + + + + + + @javax.persistence.EntityResult + + + + + + + + + + + + + + + + @javax.persistence.FieldResult + + + + + + + + + + + + + + + + + + + + + @javax.persistence.Table + + + + + + + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.TableGenerator + + + + + + + + + + + + + + + + + + + + + + + + + + + + @javax.persistence.Temporal + + + + + + + + + + + + javax.persistence.TemporalType enum values + + + + + + + + + + + + + + + + @javax.persistence.Transient + + + + + + + + + + + + @javax.persistence.UniqueConstraint + + + + + + + + + + + + + + + + + @javax.persistence.Version + + + + + + + + + + + + + + + + + + + + + + element defines a single path to which the fetch + refers, as well as the style of fetch to apply. The 'root' of the + path is different depending upon the context in which the + containing occurs; within a element, + the entity-name of the containing class mapping is assumed... + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + Specifies a filter definition. After definition, a filter + can be applied to entity or collection by name. + + + + + + + + + Used to identify all bind parameters in the condition elemement + + + + + + + + + + + + + + + + Applies a filter defined by hbm-filter-def usage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Names a org.hibernate.id.IdentifierGenerator implementation (class attribute) + as well as any configuration information need by the implementation (Hibernate + will pass it the parameters after instantiation). + + + + + + + + + + + + + Corresponds to the org.hibernate.annotations.Parameter annotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The loader element allows specification of a named query to be used for fetching + an entity or collection + + + + + + + + + + + + + + + + + + + + + + + + + tags from hbm.xml dtd; renamed here for + self-documentation. This information is intended mainly for tooling. + ]]> + + + + + + + + + + + + + + + + Corresponds to the org.hibernate.annotations.Type annotation, naming + a org.hibernate.type.* or org.hibernate.usertype.* implementation to use. + + name - names the type implementation class + + param - If the type is able to accept parameters (implementation stems from + org.hibernate.type.Type, org.hibernate.type.CollectionType, or + org.hibernate.usertype.ParameterizedType) the specified parameters will be + passed to the type instance after instantiation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A natural-id element allows declaration of unique business key + + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb b/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb index 59b19b75b111..f73558fb4874 100644 --- a/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb +++ b/hibernate-core/src/main/xjb/hbm-configuration-bindings.xjb @@ -1,8 +1,8 @@ + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + version="2.1"> @@ -15,4 +15,9 @@ + + + + + \ No newline at end of file diff --git a/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb b/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb index 51811d97488d..759a2e87aebc 100644 --- a/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb +++ b/hibernate-core/src/main/xjb/hbm-mapping-bindings.xjb @@ -1,14 +1,16 @@ + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" + jaxb:extensionBindingPrefixes="inheritance" + version="2.1"> - + + @@ -18,107 +20,160 @@ - - org.hibernate.internal.jaxb.mapping.hbm.EntityElement - org.hibernate.internal.jaxb.mapping.hbm.JoinElementSource + + org.hibernate.metamodel.source.internal.jaxb.hbm.EntityElement + org.hibernate.metamodel.source.internal.jaxb.hbm.TableInformationSource + org.hibernate.metamodel.source.internal.jaxb.hbm.JoinElementSource + + + org.hibernate.metamodel.source.internal.jaxb.hbm.ReturnElement + + + org.hibernate.metamodel.source.internal.jaxb.hbm.ReturnElement + + + org.hibernate.metamodel.source.internal.jaxb.hbm.ReturnElement - org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement - org.hibernate.internal.jaxb.mapping.hbm.JoinElementSource + org.hibernate.metamodel.source.internal.jaxb.hbm.SubEntityElement + org.hibernate.metamodel.source.internal.jaxb.hbm.JoinElementSource - org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement + org.hibernate.metamodel.source.internal.jaxb.hbm.SubEntityElement + org.hibernate.metamodel.source.internal.jaxb.hbm.TableInformationSource - org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement + org.hibernate.metamodel.source.internal.jaxb.hbm.SubEntityElement + org.hibernate.metamodel.source.internal.jaxb.hbm.TableInformationSource - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement + + org.hibernate.metamodel.source.internal.jaxb.hbm.TableInformationSource - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement + + org.hibernate.metamodel.source.internal.jaxb.hbm.SingularAttributeSource - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement + + org.hibernate.metamodel.source.internal.jaxb.hbm.SingularAttributeSource - - org.hibernate.internal.jaxb.mapping.hbm.CustomSqlElement + + org.hibernate.metamodel.source.internal.jaxb.hbm.ComponentSourceElement - - - org.hibernate.internal.jaxb.mapping.hbm.SingularAttributeSource - - - org.hibernate.internal.jaxb.mapping.hbm.SingularAttributeSource + + org.hibernate.metamodel.source.internal.jaxb.hbm.ComponentSourceElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.metamodel.source.internal.jaxb.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.IdBagPluralAttributeElementAdapter + org.hibernate.metamodel.source.internal.jaxb.hbm.IdBagPluralAttributeElementAdapter - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.metamodel.source.internal.jaxb.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.metamodel.source.internal.jaxb.hbm.PluralAttributeElement - org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement + org.hibernate.metamodel.source.internal.jaxb.hbm.PluralAttributeElement + + + org.hibernate.metamodel.source.spi.ToolingHintSource + + + org.hibernate.metamodel.source.spi.FilterParameterSource + + + org.hibernate.metamodel.source.internal.jaxb.hbm.PluralAttributeElement + + + + + + + + + + + + + + + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - @@ -131,36 +186,38 @@ - - - - - - - + - + - - - + - - - - + + - + + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/main/xjb/mapping-bindings.xjb b/hibernate-core/src/main/xjb/mapping-bindings.xjb new file mode 100644 index 000000000000..b787a32e1900 --- /dev/null +++ b/hibernate-core/src/main/xjb/mapping-bindings.xjb @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + org.hibernate.metamodel.source.internal.jaxb.ToolingHintContainer + + + + + + + + + + + org.hibernate.metamodel.source.internal.jaxb.Parameterized + + + + + org.hibernate.metamodel.source.internal.jaxb.SchemaAware + + + org.hibernate.metamodel.source.internal.jaxb.SchemaAware + + + org.hibernate.metamodel.source.internal.jaxb.SchemaAware + + + org.hibernate.metamodel.source.internal.jaxb.SchemaAware + + + org.hibernate.metamodel.source.internal.jaxb.SchemaAware + + + org.hibernate.metamodel.source.internal.jaxb.SchemaAware + + + + org.hibernate.metamodel.source.internal.jaxb.ManagedType + + + org.hibernate.metamodel.source.internal.jaxb.ManagedType + + + org.hibernate.metamodel.source.internal.jaxb.ManagedType + + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + org.hibernate.metamodel.source.internal.jaxb.PersistentAttribute + + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + org.hibernate.metamodel.source.internal.jaxb.LifecycleCallback + + + + org.hibernate.metamodel.source.internal.jaxb.AttributesContainer + + + org.hibernate.metamodel.source.internal.jaxb.AttributesContainer + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/main/xjb/orm-bindings.xjb b/hibernate-core/src/main/xjb/orm-bindings.xjb deleted file mode 100644 index 940eb3a86a24..000000000000 --- a/hibernate-core/src/main/xjb/orm-bindings.xjb +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java b/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java index 26b86905a3bd..4b12f148d63a 100644 --- a/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java @@ -38,10 +38,9 @@ import org.hibernate.service.Service; import org.hibernate.service.internal.ProvidedService; -import org.junit.Test; - import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.fail; @@ -55,6 +54,7 @@ public void testBadUrl() throws Exception { DriverConnectionCreator connectionCreator = new DriverConnectionCreator( (Driver) Class.forName( "org.h2.Driver" ).newInstance(), new StandardServiceRegistryImpl( + true, new BootstrapServiceRegistryImpl(), Collections.emptyList(), Collections.emptyList(), diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java index b38f4e2fbcc2..919c26363b71 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/DerbyDialectTestCase.java @@ -23,12 +23,12 @@ */ package org.hibernate.dialect; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import org.hibernate.engine.spi.RowSelection; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * Testing of patched support for Derby limit and offset queries; see HHH-3972 @@ -48,9 +48,12 @@ protected boolean isTenPointFiveReleaseOrNewer() { public void testInsertLimitClause() { final int limit = 50; final String input = "select * from tablename t where t.cat = 5"; - final String expected = "select * from tablename t where t.cat = 5 fetch first " + limit + " rows only"; + final String expected = "select * from tablename t where t.cat = 5 fetch first ? rows only"; - final String actual = new LocalDerbyDialect().getLimitString( input, 0, limit ); + RowSelection rowSelection = new RowSelection(); + rowSelection.setFirstRow( 0 ); + rowSelection.setMaxRows( limit ); + final String actual = new LocalDerbyDialect().buildLimitHandler( input, rowSelection ).getProcessedSql(); assertEquals( expected, actual ); } @@ -59,9 +62,12 @@ public void testInsertLimitWithOffsetClause() { final int limit = 50; final int offset = 200; final String input = "select * from tablename t where t.cat = 5"; - final String expected = "select * from tablename t where t.cat = 5 offset " + offset + " rows fetch next " + limit + " rows only"; + final String expected = "select * from tablename t where t.cat = 5 offset ? rows fetch next ? rows only"; - final String actual = new LocalDerbyDialect().getLimitString( input, offset, limit ); + RowSelection rowSelection = new RowSelection(); + rowSelection.setFirstRow( offset ); + rowSelection.setMaxRows( limit ); + final String actual = new LocalDerbyDialect().buildLimitHandler( input, rowSelection ).getProcessedSql(); assertEquals( expected, actual ); } @@ -70,10 +76,12 @@ public void testInsertLimitWithForUpdateClause() { final int limit = 50; final int offset = 200; final String input = "select c11 as col1, c12 as col2, c13 as col13 from t1 for update of c11, c13"; - final String expected = "select c11 as col1, c12 as col2, c13 as col13 from t1 offset " + offset - + " rows fetch next " + limit + " rows only for update of c11, c13"; + final String expected = "select c11 as col1, c12 as col2, c13 as col13 from t1 offset ? rows fetch next ? rows only for update of c11, c13"; - final String actual = new LocalDerbyDialect().getLimitString( input, offset, limit ); + RowSelection rowSelection = new RowSelection(); + rowSelection.setFirstRow( offset ); + rowSelection.setMaxRows( limit ); + final String actual = new LocalDerbyDialect().buildLimitHandler( input, rowSelection ).getProcessedSql(); assertEquals( expected, actual ); } @@ -82,10 +90,12 @@ public void testInsertLimitWithWithClause() { final int limit = 50; final int offset = 200; final String input = "select c11 as col1, c12 as col2, c13 as col13 from t1 where flight_id between 'AA1111' and 'AA1112' with rr"; - final String expected = "select c11 as col1, c12 as col2, c13 as col13 from t1 where flight_id between 'AA1111' and 'AA1112' offset " + offset - + " rows fetch next " + limit + " rows only with rr"; + final String expected = "select c11 as col1, c12 as col2, c13 as col13 from t1 where flight_id between 'AA1111' and 'AA1112' offset ? rows fetch next ? rows only with rr"; - final String actual = new LocalDerbyDialect().getLimitString( input, offset, limit ); + RowSelection rowSelection = new RowSelection(); + rowSelection.setFirstRow( offset ); + rowSelection.setMaxRows( limit ); + final String actual = new LocalDerbyDialect().buildLimitHandler( input, rowSelection ).getProcessedSql(); assertEquals( expected, actual ); } @@ -94,10 +104,12 @@ public void testInsertLimitWithForUpdateAndWithClauses() { final int limit = 50; final int offset = 200; final String input = "select c11 as col1, c12 as col2, c13 as col13 from t1 where flight_id between 'AA1111' and 'AA1112' for update of c11,c13 with rr"; - final String expected = "select c11 as col1, c12 as col2, c13 as col13 from t1 where flight_id between 'AA1111' and 'AA1112' offset " + offset - + " rows fetch next " + limit + " rows only for update of c11,c13 with rr"; + final String expected = "select c11 as col1, c12 as col2, c13 as col13 from t1 where flight_id between 'AA1111' and 'AA1112' offset ? rows fetch next ? rows only for update of c11,c13 with rr"; - final String actual = new LocalDerbyDialect().getLimitString( input, offset, limit ); + RowSelection rowSelection = new RowSelection(); + rowSelection.setFirstRow( offset ); + rowSelection.setMaxRows( limit ); + final String actual = new LocalDerbyDialect().buildLimitHandler( input, rowSelection ).getProcessedSql(); assertEquals( expected, actual ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java index 2f12c72f8edb..c5872a4785e6 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java @@ -23,7 +23,10 @@ */ package org.hibernate.dialect.resolver; -import java.sql.Connection; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -38,7 +41,6 @@ import org.hibernate.cfg.Environment; import org.hibernate.dialect.DB2400Dialect; import org.hibernate.dialect.DB2Dialect; -import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.DerbyTenFiveDialect; import org.hibernate.dialect.DerbyTenSevenDialect; import org.hibernate.dialect.DerbyTenSixDialect; @@ -47,7 +49,6 @@ import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.InformixDialect; import org.hibernate.dialect.IngresDialect; -import org.hibernate.dialect.Mocks; import org.hibernate.dialect.MySQL5Dialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.Oracle10gDialect; @@ -68,16 +69,10 @@ import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource; import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; import org.hibernate.service.spi.ServiceRegistryImplementor; - +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Before; import org.junit.Test; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - /** * @author Steve Ebersole */ @@ -158,7 +153,7 @@ public void testPreregisteredDialects() { testDetermination( "PostgreSQL", 8, 2, PostgreSQL82Dialect.class, resolver ); testDetermination( "PostgreSQL", 9, 0, PostgreSQL9Dialect.class, resolver ); testDetermination( "EnterpriseDB", 9, 2, PostgresPlusDialect.class, resolver ); - testDetermination( "Apache Derby", 10, 4, DerbyDialect.class, resolver ); + testDetermination( "Apache Derby", 10, 4, DB2Dialect.class, resolver ); testDetermination( "Apache Derby", 10, 5, DerbyTenFiveDialect.class, resolver ); testDetermination( "Apache Derby", 10, 6, DerbyTenSixDialect.class, resolver ); testDetermination( "Apache Derby", 11, 5, DerbyTenSevenDialect.class, resolver ); diff --git a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java index 763d5fcbc34a..e82d113b2edd 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorNoIncrementTest.java @@ -23,8 +23,6 @@ */ package org.hibernate.id; -import static org.junit.Assert.assertEquals; - import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -32,26 +30,31 @@ import java.util.Properties; import org.hibernate.Session; -import org.hibernate.testing.env.TestingDatabaseInfo; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.EJB3NamingStrategy; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.SessionImpl; import org.hibernate.jdbc.Work; -import org.hibernate.mapping.SimpleAuxiliaryDatabaseObject; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.relational.Database; import org.hibernate.type.StandardBasicTypes; + +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; + /** * I went back to 3.3 source and grabbed the code/logic as it existed back then and crafted this * unit test so that we can make sure the value keep being generated in the expected manner @@ -62,15 +65,14 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase { private static final String TEST_SEQUENCE = "test_sequence"; - private Configuration cfg; - private ServiceRegistry serviceRegistry; + private StandardServiceRegistry ssr; private SessionFactoryImplementor sessionFactory; private SequenceHiLoGenerator generator; - private SessionImplementor session; @Before public void setUp() throws Exception { Properties properties = new Properties(); + properties.setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); properties.setProperty( SequenceGenerator.SEQUENCE, TEST_SEQUENCE ); properties.setProperty( SequenceHiLoGenerator.MAX_LO, "0" ); // JPA allocationSize of 1 properties.put( @@ -83,50 +85,51 @@ protected boolean isUseQuotedIdentifiersGlobally() { @Override protected NamingStrategy getNamingStrategy() { - return cfg.getNamingStrategy(); + return EJB3NamingStrategy.INSTANCE; } } ); - Dialect dialect = TestingDatabaseInfo.DIALECT; + BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); + ssrBuilder.applySettings( properties ); + + ssr = ssrBuilder.build(); + + MetadataImplementor metadata = (MetadataImplementor) new MetadataSources( bsr ).buildMetadata( ssr ); + Database database = metadata.getDatabase(); generator = new SequenceHiLoGenerator(); - generator.configure( StandardBasicTypes.LONG, properties, dialect ); - - cfg = TestingDatabaseInfo.buildBaseConfiguration() - .setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - cfg.addAuxiliaryDatabaseObject( - new SimpleAuxiliaryDatabaseObject( - generator.sqlCreateStrings( dialect )[0], - generator.sqlDropStrings( dialect )[0] - ) + generator.configure( + StandardBasicTypes.LONG, + properties, + database.getJdbcEnvironment().getDialect(), + ssr.getService( ClassLoaderService.class ) ); + generator.registerExportables( database ); - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ); - sessionFactory = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry ); + sessionFactory = (SessionFactoryImplementor) metadata.buildSessionFactory(); } + @After public void tearDown() throws Exception { - if(session != null && !session.isClosed()) { - ((Session)session).close(); - } if ( sessionFactory != null ) { sessionFactory.close(); } - if ( serviceRegistry != null ) { - ServiceRegistryBuilder.destroy( serviceRegistry ); + if ( ssr != null ) { + StandardServiceRegistryBuilder.destroy( ssr ); } } @Test public void testHiLoAlgorithm() { - session = (SessionImpl) sessionFactory.openSession(); - ((Session)session).beginTransaction(); + SessionImpl session = (SessionImpl) sessionFactory.openSession(); + session.beginTransaction(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // initially sequence should be uninitialized - assertEquals( 0L, extractSequenceValue( (session) ) ); + assertEquals( 0L, extractSequenceValue( session ) ); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // historically the hilo generators skipped the initial block of values; @@ -156,8 +159,8 @@ public void testHiLoAlgorithm() { assertEquals( 5L, generatedValue.longValue() ); assertEquals( 5L, extractSequenceValue( (session) ) ); - ((Session)session).getTransaction().commit(); - ((Session)session).close(); + session.getTransaction().commit(); + session.close(); } private long extractSequenceValue(final SessionImplementor session) { diff --git a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java index 7239297ff704..b4c1fb20075f 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/SequenceHiLoGeneratorTest.java @@ -23,8 +23,6 @@ */ package org.hibernate.id; -import static org.junit.Assert.assertEquals; - import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -32,26 +30,31 @@ import java.util.Properties; import org.hibernate.Session; -import org.hibernate.testing.env.TestingDatabaseInfo; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.EJB3NamingStrategy; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.SessionImpl; import org.hibernate.jdbc.Work; -import org.hibernate.mapping.SimpleAuxiliaryDatabaseObject; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.relational.Database; import org.hibernate.type.StandardBasicTypes; + +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; + /** * I went back to 3.3 source and grabbed the code/logic as it existed back then and crafted this * unit test so that we can make sure the value keep being generated in the expected manner @@ -62,38 +65,50 @@ public class SequenceHiLoGeneratorTest extends BaseUnitTestCase { private static final String TEST_SEQUENCE = "test_sequence"; - private Configuration cfg; - private ServiceRegistry serviceRegistry; + private StandardServiceRegistry ssr; private SessionFactoryImplementor sessionFactory; private SequenceHiLoGenerator generator; @Before public void setUp() throws Exception { Properties properties = new Properties(); + properties.setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); properties.setProperty( SequenceGenerator.SEQUENCE, TEST_SEQUENCE ); properties.setProperty( SequenceHiLoGenerator.MAX_LO, "3" ); - properties.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, new ObjectNameNormalizer() { - @Override - protected boolean isUseQuotedIdentifiersGlobally() { - return false; - } - - @Override - protected NamingStrategy getNamingStrategy() { - return cfg.getNamingStrategy(); - } - } ); - - Dialect dialect = TestingDatabaseInfo.DIALECT; + properties.put( + PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, + new ObjectNameNormalizer() { + @Override + protected boolean isUseQuotedIdentifiersGlobally() { + return false; + } + + @Override + protected NamingStrategy getNamingStrategy() { + return EJB3NamingStrategy.INSTANCE; + } + } + ); + + BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); + ssrBuilder.applySettings( properties ); + + ssr = ssrBuilder.build(); + + MetadataImplementor metadata = (MetadataImplementor) new MetadataSources( bsr ).buildMetadata( ssr ); + Database database = metadata.getDatabase(); generator = new SequenceHiLoGenerator(); - generator.configure( StandardBasicTypes.LONG, properties, dialect ); - - cfg = TestingDatabaseInfo.buildBaseConfiguration().setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - cfg.addAuxiliaryDatabaseObject( new SimpleAuxiliaryDatabaseObject( generator.sqlCreateStrings( dialect )[0], - generator.sqlDropStrings( dialect )[0] ) ); - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ); - sessionFactory = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry ); + generator.configure( + StandardBasicTypes.LONG, + properties, + database.getJdbcEnvironment().getDialect(), + ssr.getService( ClassLoaderService.class ) + ); + generator.registerExportables( database ); + + sessionFactory = (SessionFactoryImplementor) metadata.buildSessionFactory(); } @After @@ -101,8 +116,8 @@ public void tearDown() throws Exception { if ( sessionFactory != null ) { sessionFactory.close(); } - if ( serviceRegistry != null ) { - ServiceRegistryBuilder.destroy( serviceRegistry ); + if ( ssr != null ) { + StandardServiceRegistryBuilder.destroy( ssr ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java b/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java index b680f461f0bf..143ab995e4d4 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java @@ -25,6 +25,7 @@ import org.junit.Test; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -274,7 +275,13 @@ private static Optimizer buildOptimizer( StandardOptimizerDescriptor descriptor, long initial, int increment) { - return OptimizerFactory.buildOptimizer( descriptor.getExternalName(), Long.class, increment, initial ); + return OptimizerFactory.buildOptimizer( + descriptor.getExternalName(), + Long.class, + increment, + initial, + new ClassLoaderServiceImpl() + ); } private static class SourceMock implements AccessCallback { diff --git a/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java b/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java index 1c2196b4a0e3..e77eb0770bd3 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java @@ -23,11 +23,14 @@ */ package org.hibernate.id.enhanced; -import java.util.Properties; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; -import org.junit.Test; +import java.util.Properties; import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; @@ -35,9 +38,7 @@ import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.StandardBasicTypes; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import org.junit.Test; /** * Tests that SequenceStyleGenerator configures itself as expected in various scenarios @@ -45,13 +46,14 @@ * @author Steve Ebersole */ public class SequenceStyleConfigUnitTest extends BaseUnitTestCase { + private final ClassLoaderService classLoaderService = new ClassLoaderServiceImpl(); + private void assertClassAssignability(Class expected, Class actual) { if ( ! expected.isAssignableFrom( actual ) ) { fail( "Actual type [" + actual.getName() + "] is not assignable to expected type [" + expected.getName() + "]" ); } } - /** * Test all params defaulted with a dialect supporting sequences */ @@ -60,7 +62,7 @@ public void testDefaultedSequenceBackedConfiguration() { Dialect dialect = new SequenceDialect(); Properties props = buildGeneratorPropertiesBase(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); @@ -92,7 +94,7 @@ public void testDefaultedTableBackedConfiguration() { Dialect dialect = new TableDialect(); Properties props = buildGeneratorPropertiesBase(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); @@ -112,7 +114,7 @@ public void testDefaultOptimizerBasedOnIncrementBackedBySequence() { // for dialects which do not support pooled sequences, we default to pooled+table Dialect dialect = new SequenceDialect(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -120,7 +122,7 @@ public void testDefaultOptimizerBasedOnIncrementBackedBySequence() { // for dialects which do support pooled sequences, we default to pooled+sequence dialect = new PooledSequenceDialect(); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -137,7 +139,7 @@ public void testDefaultOptimizerBasedOnIncrementBackedByTable() { props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" ); Dialect dialect = new TableDialect(); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -152,7 +154,7 @@ public void testForceTableUse() { Properties props = buildGeneratorPropertiesBase(); props.setProperty( SequenceStyleGenerator.FORCE_TBL_PARAM, "true" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() ); @@ -171,7 +173,7 @@ public void testExplicitOptimizerWithExplicitIncrementSize() { props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.NONE.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( NoopOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( 1, generator.getOptimizer().getIncrementSize() ); @@ -182,7 +184,7 @@ public void testExplicitOptimizerWithExplicitIncrementSize() { props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.HILO.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( HiLoOptimizer.class, generator.getOptimizer().getClass() ); assertEquals( 20, generator.getOptimizer().getIncrementSize() ); @@ -193,7 +195,7 @@ public void testExplicitOptimizerWithExplicitIncrementSize() { props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.POOLED.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); // because the dialect reports to not support pooled seqyences, the expectation is that we will // use a table for the backing structure... assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() ); @@ -209,13 +211,13 @@ public void testPreferPooledLoSettingHonored() { Properties props = buildGeneratorPropertiesBase(); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledOptimizer.class, generator.getOptimizer().getClass() ); props.setProperty( Environment.PREFER_POOLED_VALUES_LO, "true" ); generator = new SequenceStyleGenerator(); - generator.configure( StandardBasicTypes.LONG, props, dialect ); + generator.configure( StandardBasicTypes.LONG, props, dialect, classLoaderService ); assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() ); assertClassAssignability( PooledLoOptimizer.class, generator.getOptimizer().getClass() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java b/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java index 01db4dae8bf0..1661187b207b 100644 --- a/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jdbc/LobCreatorTest.java @@ -50,7 +50,7 @@ import org.hibernate.engine.jdbc.NonContextualLobCreator; import org.hibernate.engine.jdbc.WrappedBlob; import org.hibernate.engine.jdbc.WrappedClob; -import org.hibernate.engine.jdbc.internal.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -66,7 +66,7 @@ public void testConnectedLobCreator() throws SQLException { LobCreationContext lobCreationContext = new LobCreationContextImpl( connection ); LobCreator lobCreator = - new LobCreatorBuilder( new Properties(), connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection ) .buildLobCreator( lobCreationContext ); assertTrue( lobCreator instanceof ContextualLobCreator ); testLobCreation( lobCreator ); @@ -79,7 +79,7 @@ public void testJdbc3LobCreator() throws SQLException { LobCreationContext lobCreationContext = new LobCreationContextImpl( connection ); LobCreator lobCreator = - new LobCreatorBuilder( new Properties(), connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection ) .buildLobCreator( lobCreationContext ); assertSame( NonContextualLobCreator.INSTANCE, lobCreator ); @@ -92,7 +92,7 @@ public void testJdbc4UnsupportedLobCreator() throws SQLException { LobCreationContext lobCreationContext = new LobCreationContextImpl( connection ); LobCreator lobCreator = - new LobCreatorBuilder( new Properties(), connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection ) .buildLobCreator( lobCreationContext ); assertSame( NonContextualLobCreator.INSTANCE, lobCreator ); @@ -107,7 +107,7 @@ public void testConfiguredNonContextualLobCreator() throws SQLException { Properties props = new Properties(); props.setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" ); LobCreator lobCreator = - new LobCreatorBuilder( props, connection ) + LobCreatorBuilderImpl.makeLobCreatorBuilder( props, connection ) .buildLobCreator( lobCreationContext ); assertSame( NonContextualLobCreator.INSTANCE, lobCreator ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java deleted file mode 100644 index 2598e426dd12..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/AbstractBasicBindingTests.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.sql.Types; -import java.util.Iterator; -import java.util.Set; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.domain.BasicType; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.type.LongType; -import org.hibernate.type.StringType; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * Basic tests of {@code hbm.xml} and annotation binding code - * - * @author Steve Ebersole - */ -public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { - - private StandardServiceRegistryImpl serviceRegistry; - - @Before - public void setUp() { - serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); - } - - @After - public void tearDown() { - serviceRegistry.destroy(); - } - - protected ServiceRegistry basicServiceRegistry() { - return serviceRegistry; - } - - @Test - public void testSimpleEntityMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForSimpleEntityBinding( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); - assertRoot( metadata, entityBinding ); - assertIdAndSimpleProperty( entityBinding ); - - assertNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ); - } - - @Test - public void testSimpleVersionedEntityMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForSimpleVersionedEntityBinding( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding entityBinding = metadata.getEntityBinding( SimpleVersionedEntity.class.getName() ); - assertIdAndSimpleProperty( entityBinding ); - - assertNotNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ); - assertNotNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding().getAttribute() ); - } - - @Test - public void testEntityWithManyToOneMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForSimpleEntityBinding( sources ); - addSourcesForManyToOne( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - - EntityBinding simpleEntityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); - assertIdAndSimpleProperty( simpleEntityBinding ); - - Set referenceBindings = simpleEntityBinding.locateAttributeBinding( "id" ) - .getEntityReferencingAttributeBindings(); - assertEquals( "There should be only one reference binding", 1, referenceBindings.size() ); - - SingularAssociationAttributeBinding referenceBinding = referenceBindings.iterator().next(); - EntityBinding referencedEntityBinding = referenceBinding.getReferencedEntityBinding(); - // TODO - Is this assertion correct (HF)? - assertEquals( "Should be the same entity binding", referencedEntityBinding, simpleEntityBinding ); - - EntityBinding entityWithManyToOneBinding = metadata.getEntityBinding( ManyToOneEntity.class.getName() ); - Iterator it = entityWithManyToOneBinding.getEntityReferencingAttributeBindings() - .iterator(); - assertTrue( it.hasNext() ); - assertSame( entityWithManyToOneBinding.locateAttributeBinding( "simpleEntity" ), it.next() ); - assertFalse( it.hasNext() ); - } - - @Test - public void testSimpleEntityWithSimpleComponentMapping() { - MetadataSources sources = new MetadataSources( serviceRegistry ); - addSourcesForComponentBinding( sources ); - MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntityWithSimpleComponent.class.getName() ); - assertRoot( metadata, entityBinding ); - assertIdAndSimpleProperty( entityBinding ); - - ComponentAttributeBinding componentAttributeBinding = (ComponentAttributeBinding) entityBinding.locateAttributeBinding( "simpleComponent" ); - assertNotNull( componentAttributeBinding ); - assertSame( componentAttributeBinding.getAttribute().getSingularAttributeType(), componentAttributeBinding.getAttributeContainer() ); - assertEquals( SimpleEntityWithSimpleComponent.class.getName() + ".simpleComponent", componentAttributeBinding.getPathBase() ); - assertSame( entityBinding, componentAttributeBinding.seekEntityBinding() ); - assertNotNull( componentAttributeBinding.getComponent() ); - } - - public abstract void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources); - - public abstract void addSourcesForSimpleEntityBinding(MetadataSources sources); - - public abstract void addSourcesForManyToOne(MetadataSources sources); - - public abstract void addSourcesForComponentBinding(MetadataSources sources); - - protected void assertIdAndSimpleProperty(EntityBinding entityBinding) { - assertNotNull( entityBinding ); - assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() ); - assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - - AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" ); - assertNotNull( idAttributeBinding ); - assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - - assertTrue( idAttributeBinding.getAttribute().isSingular() ); - assertNotNull( idAttributeBinding.getAttribute() ); - SingularAttributeBinding singularIdAttributeBinding = (SingularAttributeBinding) idAttributeBinding; - assertFalse( singularIdAttributeBinding.isNullable() ); - SingularAttribute singularIdAttribute = ( SingularAttribute ) idAttributeBinding.getAttribute(); - BasicType basicIdAttributeType = ( BasicType ) singularIdAttribute.getSingularAttributeType(); - assertSame( Long.class, basicIdAttributeType.getClassReference() ); - - assertNotNull( singularIdAttributeBinding.getValue() ); - assertTrue( singularIdAttributeBinding.getValue() instanceof Column ); - Datatype idDataType = ( (Column) singularIdAttributeBinding.getValue() ).getDatatype(); - assertSame( Long.class, idDataType.getJavaType() ); - assertSame( Types.BIGINT, idDataType.getTypeCode() ); - assertSame( LongType.INSTANCE.getName(), idDataType.getTypeName() ); - - assertNotNull( entityBinding.locateAttributeBinding( "name" ) ); - assertNotNull( entityBinding.locateAttributeBinding( "name" ).getAttribute() ); - assertTrue( entityBinding.locateAttributeBinding( "name" ).getAttribute().isSingular() ); - - SingularAttributeBinding nameBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( "name" ); - assertTrue( nameBinding.isNullable() ); - assertSame( StringType.INSTANCE, nameBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - assertNotNull( nameBinding.getAttribute() ); - assertNotNull( nameBinding.getValue() ); - SingularAttribute singularNameAttribute = ( SingularAttribute ) nameBinding.getAttribute(); - BasicType basicNameAttributeType = ( BasicType ) singularNameAttribute.getSingularAttributeType(); - assertSame( String.class, basicNameAttributeType.getClassReference() ); - - assertNotNull( nameBinding.getValue() ); - SimpleValue nameValue = (SimpleValue) nameBinding.getValue(); - assertTrue( nameValue instanceof Column ); - Datatype nameDataType = nameValue.getDatatype(); - assertSame( String.class, nameDataType.getJavaType() ); - assertSame( Types.VARCHAR, nameDataType.getTypeCode() ); - assertSame( StringType.INSTANCE.getName(), nameDataType.getTypeName() ); - } - - protected void assertRoot(MetadataImplementor metadata, EntityBinding entityBinding) { - assertTrue( entityBinding.isRoot() ); - assertSame( entityBinding, metadata.getRootEntityBinding( entityBinding.getEntity().getName() ) ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicCollectionBindingTests.java deleted file mode 100644 index 2deb0afe3f84..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicCollectionBindingTests.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.metamodel.MetadataSourceProcessingOrder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; - -/** - * @author Steve Ebersole - */ -public class BasicCollectionBindingTests extends BaseUnitTestCase { - private StandardServiceRegistryImpl serviceRegistry; - - @Before - public void setUp() { - serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); - } - - @After - public void tearDown() { - serviceRegistry.destroy(); - } - -// @Test -// public void testAnnotations() { -// doTest( MetadataSourceProcessingOrder.ANNOTATIONS_FIRST ); -// } - - @Test - public void testHbm() { - doTest( MetadataSourceProcessingOrder.HBM_FIRST ); - } - - private void doTest(MetadataSourceProcessingOrder processingOrder) { - MetadataSources sources = new MetadataSources( serviceRegistry ); -// sources.addAnnotatedClass( EntityWithBasicCollections.class ); - sources.addResource( "org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml" ); - MetadataImpl metadata = (MetadataImpl) sources.getMetadataBuilder().with( processingOrder ).build(); - - final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithBasicCollections.class.getName() ); - assertNotNull( entityBinding ); - - PluralAttributeBinding bagBinding = metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theBag" ); - assertNotNull( bagBinding ); - assertSame( bagBinding, entityBinding.locateAttributeBinding( "theBag" ) ); - assertNotNull( bagBinding.getCollectionTable() ); - assertEquals( CollectionElementNature.BASIC, bagBinding.getCollectionElement().getCollectionElementNature() ); - assertEquals( String.class.getName(), ( (BasicCollectionElement) bagBinding.getCollectionElement() ).getHibernateTypeDescriptor().getJavaTypeName() ); - - PluralAttributeBinding setBinding = metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theSet" ); - assertNotNull( setBinding ); - assertSame( setBinding, entityBinding.locateAttributeBinding( "theSet" ) ); - assertNotNull( setBinding.getCollectionTable() ); - assertEquals( CollectionElementNature.BASIC, setBinding.getCollectionElement().getCollectionElementNature() ); - assertEquals( String.class.getName(), ( (BasicCollectionElement) setBinding.getCollectionElement() ).getHibernateTypeDescriptor().getJavaTypeName() ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicHbmBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicHbmBindingTests.java deleted file mode 100644 index 7f2b63ae8c01..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicHbmBindingTests.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import org.junit.Test; - -import org.hibernate.metamodel.MetadataSources; - -/** - * Basic tests of {@code hbm.xml} binding code - * - * @author Steve Ebersole - */ -public class BasicHbmBindingTests extends AbstractBasicBindingTests { - public void addSourcesForSimpleEntityBinding(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/SimpleEntity.hbm.xml" ); - } - - public void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml" ); - } - - public void addSourcesForManyToOne(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml" ); - } - - public void addSourcesForComponentBinding(MetadataSources sources) { - sources.addResource( "org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml" ); - } - - @Test - public void testSimpleEntityWithSimpleComponentMapping() { - super.testSimpleEntityWithSimpleComponentMapping(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml deleted file mode 100644 index 3eb4ca7633ea..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.hbm.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.java deleted file mode 100644 index af2001320bad..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithBasicCollections.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import javax.persistence.ElementCollection; -import javax.persistence.Entity; -import javax.persistence.Id; - -/** - * @author Gail Badner - * @author Steve Ebersole - */ -@Entity -public class EntityWithBasicCollections { - private Long id; - private String name; - private Collection theBag = new ArrayList(); - private Set theSet = new HashSet(); - - public EntityWithBasicCollections() { - } - - public EntityWithBasicCollections(String name) { - this.name = name; - } - - @Id - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @ElementCollection - public Collection getTheBag() { - return theBag; - } - - public void setTheBag(Collection theBag) { - this.theBag = theBag; - } - - @ElementCollection - public Set getTheSet() { - return theSet; - } - - public void setTheSet(Set theSet) { - this.theSet = theSet; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml deleted file mode 100644 index dc6baf6321ee..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.hbm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.java deleted file mode 100644 index 709d769e20b5..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/ManyToOneEntity.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.ManyToOne; - -/** - * @author Gail Badner - */ -@Entity -public class ManyToOneEntity { - @Id - private Long id; - private String theName; - @ManyToOne - SimpleEntity simpleEntity; - - public ManyToOneEntity() { - } - - public ManyToOneEntity(String name) { - this.theName = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return theName; - } - - public void setName(String name) { - this.theName = name; - } - - public SimpleEntity getSimpleEntity() { - return simpleEntity; - } - - public void setSimpleEntity(SimpleEntity simpleEntity) { - this.simpleEntity = simpleEntity; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "EntityWithManyToOne" ); - sb.append( "{id=" ).append( id ); - sb.append( ", theName='" ).append( theName ).append( '\'' ); - sb.append( ", simpleEntity=" ).append( simpleEntity ); - sb.append( '}' ); - return sb.toString(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml deleted file mode 100644 index 14f88143aaf7..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.java deleted file mode 100644 index 227dc31cf412..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntity.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import javax.persistence.Entity; -import javax.persistence.Id; - -/** - * @author Steve Ebersole - */ -@Entity -public class SimpleEntity { - @Id - private Long id; - private String name; - - public SimpleEntity() { - } - - public SimpleEntity(String name) { - this.name = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java deleted file mode 100644 index bf7c6d177c03..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.binding; - -import java.sql.Types; - -import org.junit.Test; - -import org.hibernate.EntityMode; -import org.hibernate.internal.util.ValueHolder; -import org.hibernate.metamodel.domain.Entity; -import org.hibernate.metamodel.domain.SingularAttribute; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.Datatype; -import org.hibernate.metamodel.relational.Schema; -import org.hibernate.metamodel.relational.Size; -import org.hibernate.metamodel.relational.Table; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertSame; - -/** - * Basic binding "smoke" tests - * - * @author Steve Ebersole - */ -public class SimpleValueBindingTests extends BaseUnitTestCase { - public static final Datatype BIGINT = new Datatype( Types.BIGINT, "BIGINT", Long.class ); - public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); - - - @Test - public void testBasicMiddleOutBuilding() { - Table table = new Table( new Schema( null, null ), "the_table" ); - Entity entity = new Entity( "TheEntity", "NoSuchClass", makeJavaType( "NoSuchClass" ), null ); - EntityBinding entityBinding = new EntityBinding( InheritanceType.NO_INHERITANCE, EntityMode.POJO ); - entityBinding.setEntity( entity ); - entityBinding.setPrimaryTable( table ); - - SingularAttribute idAttribute = entity.createSingularAttribute( "id" ); - BasicAttributeBinding attributeBinding = entityBinding.makeBasicAttributeBinding( idAttribute ); - attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" ); - assertSame( idAttribute, attributeBinding.getAttribute() ); - - entityBinding.getHierarchyDetails().getEntityIdentifier().setValueBinding( attributeBinding ); - - Column idColumn = table.locateOrCreateColumn( "id" ); - idColumn.setDatatype( BIGINT ); - idColumn.setSize( Size.precision( 18, 0 ) ); - table.getPrimaryKey().addColumn( idColumn ); - table.getPrimaryKey().setName( "my_table_pk" ); - //attributeBinding.setValue( idColumn ); - } - - ValueHolder> makeJavaType(final String name) { - return new ValueHolder>( - new ValueHolder.DeferredInitializer>() { - @Override - public Class initialize() { - try { - return Class.forName( name ); - } - catch ( Exception e ) { - throw new ClassLoadingException( "Could not load class : " + name, e ); - } - } - } - ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java deleted file mode 100644 index 95b316c2d1b8..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@GenericGenerator(name = "myGenerator", strategy = "sequence") -package org.hibernate.metamodel.binding; - -import org.hibernate.annotations.GenericGenerator; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java new file mode 100644 index 000000000000..25cda5289cbc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java @@ -0,0 +1,255 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import java.util.Iterator; + +import org.hibernate.EntityMode; +import org.hibernate.TruthValue; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.source.internal.annotations.AnnotationMetadataSourceProcessorImpl; +import org.hibernate.metamodel.source.internal.hbm.HbmMetadataSourceProcessorImpl; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifierGeneratorSource; +import org.hibernate.metamodel.source.spi.IdentifierSource; +import org.hibernate.metamodel.source.spi.SimpleIdentifierSource; +import org.hibernate.metamodel.source.spi.SingularAttributeSource; +import org.hibernate.metamodel.source.spi.TableSource; +import org.hibernate.metamodel.source.spi.TableSpecificationSource; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.MetadataSourceProcessor; +import org.hibernate.metamodel.spi.SingularAttributeNature; +import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import org.jboss.jandex.IndexView; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public class AssertSourcesTest extends BaseUnitTestCase { + final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build() ; + + @Test + public void testUserEntitySourcesHbm() { + BindingContext rootContext = RootBindingContextBuilder.buildBindingContext( serviceRegistry ); + + MetadataSources hbm = new MetadataSources( serviceRegistry ); + hbm.addResource( getClass().getPackage().getName().replace( '.', '/' ) + "/User.hbm.xml" ); + MetadataSourceProcessor hbmProcessor = new HbmMetadataSourceProcessorImpl( + rootContext, + hbm + ); + testUserEntitySources( hbmProcessor, rootContext ); + } + + @Test + public void testUserEntitySourcesAnnotations() { + MetadataSources ann = new MetadataSources( serviceRegistry ); + ann.addAnnotatedClass( User.class ); + ann.addAnnotatedClass( User.Name.class ); + + final IndexView indexView = ann.buildJandexView(); + BindingContext rootContext = RootBindingContextBuilder.buildBindingContext( serviceRegistry, indexView ); + + MetadataSourceProcessor annProcessor = new AnnotationMetadataSourceProcessorImpl( + rootContext, + indexView + ); + testUserEntitySources( annProcessor, rootContext ); + } + + private void testUserEntitySources(MetadataSourceProcessor processor, BindingContext rootContext) { + for ( IdentifierGeneratorSource identifierGeneratorSource : processor.extractGlobalIdentifierGeneratorSources() ) { + rootContext.getMetadataCollector().addIdGenerator( + new IdentifierGeneratorDefinition( + identifierGeneratorSource.getGeneratorName(), + identifierGeneratorSource.getGeneratorImplementationName(), + identifierGeneratorSource.getParameters() + ) + ); + } + + Iterator hierarchies = processor.extractEntityHierarchies().iterator(); + assertTrue( hierarchies.hasNext() ); + EntityHierarchySource hierarchy = hierarchies.next(); + assertFalse( hierarchies.hasNext() ); + assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + + EntitySource entitySource = hierarchy.getRoot(); + assertNotNull( entitySource ); + assertEquals( 0, entitySource.getSubTypes().size() ); + + assertEquals( User.class.getName(), entitySource.getClassName() ); + assertEquals( User.class.getName(), entitySource.getEntityName() ); + assertEquals( StringHelper.unqualify( User.class.getName() ), entitySource.getJpaEntityName() ); + + assertEquals( EntityMode.POJO, hierarchy.getEntityMode() ); + assertEquals( TruthValue.FALSE, hierarchy.getCaching().getRequested() ); + assertNull( hierarchy.getDiscriminatorSource() ); + assertNull( entitySource.getDiscriminatorMatchValue() ); + + assertTrue( entitySource.getJpaCallbackClasses() == null || entitySource.getJpaCallbackClasses().isEmpty() ); + + TableSpecificationSource primaryTableSpecificationSource = entitySource.getPrimaryTable(); + assertTrue( TableSource.class.isInstance( primaryTableSpecificationSource ) ); + TableSource primaryTable = (TableSource) primaryTableSpecificationSource; + // todo : should sources be responsible for figuring out logical names? + // these are the things that need to match in terms of lookup keys + assertNull( primaryTable.getExplicitCatalogName() ); + assertNull( primaryTable.getExplicitSchemaName() ); + assertNull( primaryTable.getExplicitTableName() ); + + assertFalse( entitySource.getSecondaryTables().iterator().hasNext() ); + assertTrue( + ArrayHelper.isEmpty( entitySource.getSynchronizedTableNames() ) + ); + + IdentifierSource identifierSource = hierarchy.getIdentifierSource(); + assertNotNull( identifierSource ); + assertEquals( EntityIdentifierNature.SIMPLE, identifierSource.getNature() ); + SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource; + SingularAttributeSource identifierAttributeSource = simpleIdentifierSource.getIdentifierAttributeSource(); + assertEquals( "id", identifierAttributeSource.getName() ); + assertTrue( identifierAttributeSource.isSingular() ); + assertFalse( identifierAttributeSource.isVirtualAttribute() ); + assertFalse( identifierAttributeSource.isLazy() ); + assertEquals( SingularAttributeNature.BASIC, identifierAttributeSource.getSingularAttributeNature() ); + assertEquals( PropertyGeneration.INSERT, identifierAttributeSource.getGeneration() ); +// assertNull( identifierAttributeSource.getPropertyAccessorName() ); + + // todo : here is an interesting question in terms of who is responsible for semantic interpretation + // really an attribute for identifier should never be included in updates + // and it should only be included in inserts only in certain cases + // and should never be nullable + // ^^ all because this is the PK. That is the semantic interpretation of those values based on that context. + // + // So do sources simply return explicit user values? Or do they consider such semantic analysis? + assertTrue( identifierAttributeSource.areValuesIncludedInInsertByDefault() ); + assertFalse( identifierAttributeSource.areValuesIncludedInUpdateByDefault() ); + assertFalse( identifierAttributeSource.areValuesNullableByDefault() ); + + // todo : return collections? or iterables? + // todo : empty collections? or null? + assertEquals( 0, identifierAttributeSource.relationalValueSources().size() ); +// RelationalValueSource relationalValueSource = identifierAttributeSource.relationalValueSources().get( 0 ); +// assertNull( relationalValueSource.getContainingTableName() ); +// assertEquals( RelationalValueSource.Nature.COLUMN, relationalValueSource.getNature() ); +// ColumnSource columnSource = (ColumnSource) relationalValueSource; +// assertNull( columnSource.getName() ); +// assertNull( columnSource.getReadFragment() ); +// assertNull( columnSource.getWriteFragment() ); +// assertNull( columnSource.getDefaultValue() ); +// assertNull( columnSource.getSqlType() ); +// assertNull( columnSource.getCheckCondition() ); +// assertNull( columnSource.getComment() ); +// assertNull( columnSource.getJdbcDataType() ); +// assertNull( columnSource.getSize() ); +// // todo : technically, pk has to be unique, but this another semantic case +// assertFalse( columnSource.isUnique() ); +// // todo : see comments above +// assertFalse( columnSource.isIncludedInInsert() ); +// assertFalse( columnSource.isIncludedInUpdate() ); +// assertFalse( columnSource.isNullable() ); + + assertEquals( 3, entitySource.attributeSources().size() ); + + + } + + @Test + public void testOrderEntitySources() { + MetadataSources ann = new MetadataSources( serviceRegistry ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.OrderPk.class ); + IndexView indexView = ann.buildJandexView(); + MetadataSourceProcessor annProcessor = new AnnotationMetadataSourceProcessorImpl( + RootBindingContextBuilder.buildBindingContext( serviceRegistry, indexView ), + indexView + ); + testOrderEntitySources( annProcessor ); + } + + private void testOrderEntitySources(MetadataSourceProcessor processor) { + Iterator hierarchies = processor.extractEntityHierarchies().iterator(); + assertTrue( hierarchies.hasNext() ); + EntityHierarchySource hierarchy = hierarchies.next(); + assertFalse( hierarchies.hasNext() ); + assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + + EntitySource entitySource = hierarchy.getRoot(); + assertEquals( 0, entitySource.getSubTypes().size() ); + + assertEquals( Order.class.getName(), entitySource.getClassName() ); + assertEquals( Order.class.getName(), entitySource.getEntityName() ); + assertEquals( StringHelper.unqualify( Order.class.getName() ), entitySource.getJpaEntityName() ); + } + + @Test + public void testOrderNonAggregatedEntitySources() { + MetadataSources ann = new MetadataSources( serviceRegistry ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.class ); + ann.addAnnotatedClass( Order.OrderPk.class ); + MetadataSourceProcessor annProcessor; + final IndexView indexView = ann.buildJandexView(); + annProcessor = new AnnotationMetadataSourceProcessorImpl( + RootBindingContextBuilder.buildBindingContext( serviceRegistry, indexView ), + indexView + ); + testOrderNonAggregatedEntitySources( annProcessor ); + } + + private void testOrderNonAggregatedEntitySources(MetadataSourceProcessor processor) { + Iterator hierarchies = processor.extractEntityHierarchies().iterator(); + assertTrue( hierarchies.hasNext() ); + EntityHierarchySource hierarchy = hierarchies.next(); + assertFalse( hierarchies.hasNext() ); + assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + + EntitySource entitySource = hierarchy.getRoot(); + assertEquals( 0, entitySource.getSubTypes().size() ); + + assertEquals( Order.class.getName(), entitySource.getClassName() ); + assertEquals( Order.class.getName(), entitySource.getEntityName() ); + assertEquals( StringHelper.unqualify( Order.class.getName() ), entitySource.getJpaEntityName() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/Foo.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Foo.java similarity index 77% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/Foo.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Foo.java index f06395ca3d9e..ea71ff8e5f16 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/Foo.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Foo.java @@ -21,12 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; + +import java.util.List; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; /** * @author Hardy Ferentschik */ +@Entity public class Foo { + @Id + @GeneratedValue + public long id; + + @ElementCollection + public List bars; } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/MetadataImplTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/MetadataImplTest.java similarity index 87% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/MetadataImplTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/MetadataImplTest.java index 828719c7098a..ccb222c819e5 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/MetadataImplTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/MetadataImplTest.java @@ -21,24 +21,26 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; +package org.hibernate.metamodel.internal.source; import java.util.Iterator; -import org.hibernate.HibernateException; +import org.junit.Test; + import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.Metadata; import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.SessionFactoryBuilder; -import org.hibernate.metamodel.binding.FetchProfile; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.SessionFactoryBuilderImpl; +import org.hibernate.metamodel.spi.binding.FetchProfile; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; /** * @author Hardy Ferentschik @@ -59,17 +61,11 @@ public void testAddingNullPackageName() { sources.buildMetadata(); } - @Test(expected = HibernateException.class) - public void testAddingNonExistingPackageName() { - MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addPackage( "not.a.package" ); - sources.buildMetadata(); - } - @Test public void testAddingPackageName() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addPackage( "org.hibernate.metamodel.source.internal" ); + sources.addPackage( "org.hibernate.metamodel.internal.source" ); + sources.addAnnotatedClass( Foo.class ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); assertFetchProfile( metadata ); @@ -78,7 +74,8 @@ public void testAddingPackageName() { @Test public void testAddingPackageNameWithTrailingDot() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addPackage( "org.hibernate.metamodel.source.internal." ); + sources.addPackage( "org.hibernate.metamodel.internal.source." ); + sources.addAnnotatedClass( Foo.class ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); assertFetchProfile( metadata ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java new file mode 100644 index 000000000000..ed2225fc2c90 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/Order.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * Defines an entity with an embedded id. + * + * @author Steve Ebersole + */ +@Entity +@Table( name = "T_ORDER" ) +public class Order { + private OrderPk id; + + @EmbeddedId + public OrderPk getId() { + return id; + } + + @Embeddable + public static class OrderPk { + private String customerIdentifier; + private int orderNumber; + + OrderPk() { + } + + public OrderPk(String customerIdentifier, int orderNumber) { + this.customerIdentifier = customerIdentifier; + this.orderNumber = orderNumber; + } + + public String getCustomerIdentifier() { + return customerIdentifier; + } + + private void setCustomerIdentifier(String customerIdentifier) { + this.customerIdentifier = customerIdentifier; + } + + public int getOrderNumber() { + return orderNumber; + } + + private void setOrderNumber(int orderNumber) { + this.orderNumber = orderNumber; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java new file mode 100644 index 000000000000..9210c5b30572 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/OrderWithNonEmbeddedId.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +/** + * @author Steve Ebersole + */ +@Entity +@IdClass( Order.OrderPk.class ) +public class OrderWithNonEmbeddedId { + private String customerIdentifier; + private int orderNumber; + + public OrderWithNonEmbeddedId() { + } + + public OrderWithNonEmbeddedId(String customerIdentifier, int orderNumber) { + this.customerIdentifier = customerIdentifier; + this.orderNumber = orderNumber; + } + + @Id + public String getCustomerIdentifier() { + return customerIdentifier; + } + + public void setCustomerIdentifier(String customerIdentifier) { + this.customerIdentifier = customerIdentifier; + } + + @Id + public int getOrderNumber() { + return orderNumber; + } + + public void setOrderNumber(int orderNumber) { + this.orderNumber = orderNumber; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/RootBindingContextBuilder.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/RootBindingContextBuilder.java new file mode 100644 index 000000000000..8da943eed22b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/RootBindingContextBuilder.java @@ -0,0 +1,78 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.metamodel.internal.ClassLoaderAccessImpl; +import org.hibernate.metamodel.internal.MetadataBuilderImpl; +import org.hibernate.metamodel.internal.MetadataBuildingProcess; +import org.hibernate.metamodel.reflite.internal.JavaTypeDescriptorRepositoryImpl; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.internal.annotations.JandexAccessImpl; +import org.hibernate.metamodel.spi.BindingContext; +import org.hibernate.metamodel.spi.ClassLoaderAccess; +import org.hibernate.type.BasicTypeRegistry; +import org.hibernate.type.TypeFactory; +import org.hibernate.type.TypeResolver; + +import org.jboss.jandex.IndexView; + +/** + * @author Steve Ebersole + */ +public class RootBindingContextBuilder { + + public static BindingContext buildBindingContext(StandardServiceRegistry serviceRegistry) { + return buildBindingContext( serviceRegistry, null ); + } + + public static BindingContext buildBindingContext(StandardServiceRegistry serviceRegistry, IndexView index) { + final BasicTypeRegistry basicTypeRegistry = new BasicTypeRegistry(); + final MetadataBuilderImpl.Options options = new MetadataBuilderImpl.Options( serviceRegistry ); + final MetadataBuildingProcess.MappingDefaultsImpl mappingDefaults = new MetadataBuildingProcess.MappingDefaultsImpl( + options + ); + final ClassLoaderAccess classLoaderAccess = new ClassLoaderAccessImpl( null, serviceRegistry ); + final JandexAccessImpl jandexAccess = new JandexAccessImpl( + index, + classLoaderAccess + ); + final JavaTypeDescriptorRepository javaTypeDescriptorRepository = new JavaTypeDescriptorRepositoryImpl( + jandexAccess, + classLoaderAccess + ); + final MetadataBuildingProcess.InFlightMetadataCollectorImpl metadataCollector = new MetadataBuildingProcess.InFlightMetadataCollectorImpl( + options, + new TypeResolver( basicTypeRegistry, new TypeFactory() ) + ); + return new MetadataBuildingProcess.RootBindingContextImpl( + options, + mappingDefaults, + javaTypeDescriptorRepository, + jandexAccess, + classLoaderAccess, + metadataCollector + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImplTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SessionFactoryBuilderImplTest.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImplTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SessionFactoryBuilderImplTest.java index 43e87b6fb5fa..da88c0b38637 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SessionFactoryBuilderImplTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SessionFactoryBuilderImplTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.internal; +package org.hibernate.metamodel.internal.source; import java.io.Serializable; import java.util.Iterator; @@ -38,8 +38,9 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.internal.SessionFactoryBuilderImpl; import org.hibernate.proxy.EntityNotFoundDelegate; - import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.Type; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SimpleEntity.java new file mode 100644 index 000000000000..2c9b9c5f95db --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/SimpleEntity.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Steve Ebersole + */ +@Entity +public class SimpleEntity { + @Id + private Long id; + private String name; + + public SimpleEntity() { + } + + public SimpleEntity(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java new file mode 100644 index 000000000000..26fa3aab631f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/User.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.NaturalId; + +/** + * @author Steve Ebersole + */ +@Entity +public class User { + private Long id; + private Name name; + private String userName; + private Date lastLogin; + private int version; + + @Id + @GeneratedValue( generator = "increment" ) + @GenericGenerator( name = "increment", strategy = "increment" ) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + + @NaturalId + @Column( name = "UNAME" ) + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Temporal( TemporalType.TIMESTAMP ) + public Date getLastLogin() { + return lastLogin; + } + + public void setLastLogin(Date lastLogin) { + this.lastLogin = lastLogin; + } + + @Version + @Column( name = "LAST_UPDATED" ) + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + @Embeddable + public static class Name { + private String firstName; + private String middleName; + private String lastName; + + public Name() { + } + + public Name(String firstName, String middleName, String lastName) { + this.firstName = firstName; + this.middleName = middleName; + this.lastName = lastName; + } + + @Column( name = "FNAME" ) + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + @Column( name="LNAME" ) + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Column( name = "MNAME" ) + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/AccessBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/AccessBindingTest.java new file mode 100644 index 000000000000..88a75a2667b9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/AccessBindingTest.java @@ -0,0 +1,198 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.AnnotationException; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +/** + * Tests for different types of attribute access + * + * @author Hardy Ferentschik + */ + +public class AccessBindingTest extends BaseAnnotationBindingTestCase { + @Entity + class FieldAccess { + @Id + private int id; + } + + @Test + @Resources(annotatedClasses = { FieldAccess.class }) + public void testDefaultFieldAccess() { + EntityBinding binding = getEntityBinding( FieldAccess.class ); + assertEquals( "Wrong access type", "field", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); + } + + @Entity + class PropertyAccess { + private int id; + + @Id + public int getId() { + return id; + } + } + + @Test + @Resources(annotatedClasses = { PropertyAccess.class }) + public void testDefaultPropertyAccess() { + EntityBinding binding = getEntityBinding( PropertyAccess.class ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "id" ).getPropertyAccessorName() + ); + } + + @Entity + class NoAccess { + private int id; + + public int getId() { + return id; + } + } + + @Test(expected = AnnotationException.class) + @Resources(annotatedClasses = { NoAccess.class }) + public void testNoAccess() { + // actual error happens when the binding gets created + } + + @Entity + class MixedAccess { + @Id + private int id; + + private String name; + + @Access(AccessType.PROPERTY) + public String getName() { + return name; + } + } + + @Test + @Resources(annotatedClasses = { MixedAccess.class }) + public void testMixedAccess() { + EntityBinding binding = getEntityBinding( MixedAccess.class ); + assertEquals( "Wrong access type", "field", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "name" ).getPropertyAccessorName() + ); + } + + @Test + @Resources(annotatedClasses = { MixedAccess.class }) + public void test() { + EntityBinding binding = getEntityBinding( MixedAccess.class ); + assertEquals( "Wrong access type", "field", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "name" ).getPropertyAccessorName() + ); + } + + @Entity + class Base { + @Id + int id; + } + + @Entity + @Access(AccessType.PROPERTY) + class ClassConfiguredAccess extends Base { + private String name; + + public String getName() { + return name; + } + } + + @Test + @Resources(annotatedClasses = { ClassConfiguredAccess.class, Base.class }) + public void testExplicitClassConfiguredAccess() { + EntityBinding binding = getEntityBinding( Base.class ); + assertEquals( + "Wrong access type", + "field", + binding.locateAttributeBinding( "id" ).getPropertyAccessorName() + ); + + + binding = getEntityBinding( ClassConfiguredAccess.class ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "name" ).getPropertyAccessorName() + ); + } + + + @Entity + class EntityWithEmbeddedId { + EmbeddableId id; + + @EmbeddedId + public EmbeddableId getId() { + return id; + } + } + + @Embeddable + public class EmbeddableId { + String ssn; + } + + @Test + @Resources(annotatedClasses = { EntityWithEmbeddedId.class, EmbeddableId.class }) + public void testEmbeddedIdWithPropertyAccess() { + EntityBinding binding = getEntityBinding( EntityWithEmbeddedId.class ); + assertEquals( + "Wrong access type", + "property", + binding.locateAttributeBinding( "id" ).getPropertyAccessorName() + ); + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/BatchSizeBindingTest.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/BatchSizeBindingTest.java index b94774e9be0a..77aae2e30965 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/BatchSizeBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -29,7 +29,9 @@ import org.junit.Test; import org.hibernate.annotations.BatchSize; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CacheBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CacheBindingTest.java similarity index 87% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CacheBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CacheBindingTest.java index 4b6bf541996a..0a75a66793a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CacheBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CacheBindingTest.java @@ -21,20 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Cacheable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.SharedCacheMode; -import org.junit.Test; - +import org.hibernate.TruthValue; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.metamodel.binding.Caching; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.Caching; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -63,9 +66,8 @@ public void testJpaCaching() { EntityBinding binding = getEntityBinding( JpaCacheEntity.class ); assertNotNull( "There should be a cache binding", binding.getHierarchyDetails().getCaching() ); Caching caching = binding.getHierarchyDetails().getCaching(); - assertEquals( + assertNull( "Wrong region", - this.getClass().getName() + "$" + JpaCacheEntity.class.getSimpleName(), caching.getRegion() ); assertEquals( "Wrong lazy properties configuration", true, caching.isCacheLazyProperties() ); @@ -75,7 +77,11 @@ public void testJpaCaching() { @Resources(annotatedClasses = NoCacheEntity.class, cacheMode = SharedCacheMode.NONE) public void testNoCaching() { EntityBinding binding = getEntityBinding( NoCacheEntity.class ); - assertNull( "There should be no cache binding", binding.getHierarchyDetails().getCaching() ); + assertEquals( + "There should be no cache binding", + TruthValue.FALSE, + binding.getHierarchyDetails().getCaching().getRequested() + ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CustomSQLBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CustomSQLBindingTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CustomSQLBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CustomSQLBindingTest.java index 935fa511b24e..5129bfc5b308 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/CustomSQLBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/CustomSQLBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; @@ -34,8 +34,10 @@ import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; -import org.hibernate.metamodel.binding.CustomSQL; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.CustomSQL; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java new file mode 100644 index 000000000000..32807d20f26b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ElementCollectionBindingTest.java @@ -0,0 +1,241 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.List; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; + +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.binding.BagBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.xml.spi.SourceType; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +/** + * Tests for different types of @ElementCollection mappings. + * + * @author Hardy Ferentschik + */ + +public class ElementCollectionBindingTest extends BaseAnnotationBindingTestCase { + @Entity + class TestEntity { + @Id + private int id; + + @ElementCollection + @JoinTable + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + public void testElementCollectionWithJoinTableThrowsException() { + try { + sources.addAnnotatedClass( TestEntity.class ); + sources.buildMetadata(); + fail( "Invalid use of @JoinTable with @ElementCollection" ); + } + catch ( MappingException e ) { + assertEquals( "Unexpected error origin", TestEntity.class.getName(), e.getOrigin().getName() ); + assertEquals( "Unexpected type", SourceType.ANNOTATION, e.getOrigin().getType() ); + assertTrue( "Wrong error message", e.getMessage().contains( "HHH000460" ) ); + } + } + + @Entity + class TestEntity2 { + @Id + private int id; + + @ElementCollection + @JoinTable + @CollectionTable + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + public void testCollectionTableAndJoinTableThrowsException() { + try { + sources.addAnnotatedClass( TestEntity2.class ); + sources.buildMetadata(); + fail( "Invalid use of @JoinTable AND @CollectionTable" ); + } + catch ( MappingException e ) { + assertEquals( "Unexpected error origin", TestEntity2.class.getName(), e.getOrigin().getName() ); + assertEquals( "Unexpected type", SourceType.ANNOTATION, e.getOrigin().getType() ); + assertTrue( "Wrong error message", e.getMessage().contains( "HHH000458" ) ); + } + } + + @Entity + class TestEntity3 { + @Id + private int id; + + @ElementCollection + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity3.class) + public void testDefaultJoinTableName() { + EntityBinding entityBinding = getEntityBinding( TestEntity3.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + assertEquals( + "Wrong default collection table name", + "ElementCollectionBindingTest$TestEntity3_strings", + tableSpec.getLogicalName().getText() + ); + } + + @Entity + class TestEntity4 { + @Id + private int id; + + @ElementCollection + @CollectionTable(name = "STRING_COLLECTION") + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity4.class) + public void testExplicitJoinTableName() { + EntityBinding entityBinding = getEntityBinding( TestEntity4.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + assertEquals( + "Wrong default collection table name", + "STRING_COLLECTION", + tableSpec.getLogicalName().getText() + ); + } + + + @Entity + class TestEntity5 { + @Id + private int id; + + @ElementCollection + @CollectionTable(name = "STRING_COLLECTION", joinColumns = @JoinColumn(name = "FOO")) + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity5.class) + public void testJoinColumnAsPartOfCollectionTable() { + EntityBinding entityBinding = getEntityBinding( TestEntity5.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + Column column = tableSpec.locateColumn( "FOO" ); + assertNotNull( "The join column should be named FOO", column ); + } + + @Entity + class TestEntity6 { + @Id + private int id; + + @ElementCollection + @JoinColumn(name = "FOO") + private List strings; + + public int getId() { + return id; + } + + public List getStrings() { + return strings; + } + } + + @Test + @Resources(annotatedClasses = TestEntity6.class) + public void testElementCollectionWithJoinColumn() { + EntityBinding entityBinding = getEntityBinding( TestEntity6.class ); + BagBinding bagBinding = ( BagBinding ) entityBinding.locateAttributeBinding( "strings" ); + TableSpecification tableSpec = bagBinding.getPluralAttributeKeyBinding().getCollectionTable(); + Column column = tableSpec.locateColumn( "FOO" ); + assertNotNull( "The join column should be named FOO", column ); + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java new file mode 100644 index 000000000000..4dce03db2c68 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java @@ -0,0 +1,422 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Parent; +import org.hibernate.annotations.Target; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +/** + * Tests for {@code javax.persistence.Embeddable}. + * + * @author Hardy Ferentschik + */ +public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { + @Entity + class User { + @Id + private int id; + + @Embedded + private Phone phone; + } + + @Embeddable + class Phone { + String countryCode; + String areaCode; + String number; + } + + @Test + @Resources(annotatedClasses = { User.class, Phone.class }) + public void testEmbeddable() { + EntityBinding binding = getEntityBinding( User.class ); + + final String componentName = "phone"; + assertNotNull( binding.locateAttributeBinding( componentName ) ); + assertTrue( binding.locateAttributeBinding( componentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding compositeBinding = (EmbeddedAttributeBinding) binding.locateAttributeBinding( + componentName + ); + + assertNotNull( compositeBinding.getHibernateTypeDescriptor() ); + + assertNotNull( compositeBinding.getRelationalValueBindings() ); + assertEquals( 3, compositeBinding.getRelationalValueBindings().size() ); + + assertEquals( + "Wrong path", + "phone", + compositeBinding.getEmbeddableBinding().getPathBase().getFullPath() + ); + + assertEquals( + "Wrong path", + "org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableBindingTest$User#phone", + compositeBinding.getAttributeRole().getFullPath() + ); + + assertNotNull( compositeBinding.getEmbeddableBinding().locateAttributeBinding( "countryCode" ) ); + assertNotNull( compositeBinding.getEmbeddableBinding().locateAttributeBinding( "areaCode" ) ); + assertNotNull( compositeBinding.getEmbeddableBinding().locateAttributeBinding( "number" ) ); + + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Entity + @AttributeOverride(name = "embedded.name", column = @Column(name = "FUBAR", length = 42)) + class BaseEntity { + @Id + private int id; + + @Embedded + private EmbeddedEntity embedded; + } + + @Embeddable + class EmbeddedEntity { + String name; + } + + @Test + @Resources(annotatedClasses = { BaseEntity.class, EmbeddedEntity.class }) + public void testEmbeddableWithAttributeOverride() { + EntityBinding binding = getEntityBinding( BaseEntity.class ); + + final String componentName = "embedded"; + assertNotNull( binding.locateAttributeBinding( componentName ) ); + assertTrue( binding.locateAttributeBinding( componentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding compositeBinding = (EmbeddedAttributeBinding) binding.locateAttributeBinding( + componentName + ); + + assertNotNull( compositeBinding.getEmbeddableBinding().locateAttributeBinding( "name" ) ); + BasicAttributeBinding nameAttribute = (BasicAttributeBinding) compositeBinding.getEmbeddableBinding().locateAttributeBinding( + "name" + ); + assertEquals( 1, nameAttribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getText() ); + assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() ); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Embeddable + public class Address { + protected String street; + protected String city; + protected String state; + @Embedded + protected Zipcode zipcode; + } + + @Embeddable + public class Zipcode { + protected String zip; + protected String plusFour; + } + + @Entity + public class Customer { + @Id + protected Integer id; + protected String name; + @AttributeOverrides( { + @AttributeOverride(name = "state", + column = @Column(name = "ADDR_STATE")), + @AttributeOverride(name = "zipcode.zip", + column = @Column(name = "ADDR_ZIP")) + }) + @Embedded + protected Address address; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Test + @Resources(annotatedClasses = { Zipcode.class, Address.class, Customer.class }) + public void testNestedEmbeddable() { + EntityBinding binding = getEntityBinding( Customer.class ); + + final String addressComponentName = "address"; + assertNotNull( binding.locateAttributeBinding( addressComponentName ) ); + assertTrue( binding.locateAttributeBinding( addressComponentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding attributeCompositeBinding = (EmbeddedAttributeBinding) binding.locateAttributeBinding( + addressComponentName + ); + + assertNotNull( attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( "street" ) ); + assertNotNull( attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( "city" ) ); + assertNotNull( attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( "state" ) ); + + BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( + "state" + ); + assertEquals( 1, stateAttribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) stateAttribute.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( + "Attribute override specifies a custom column name", + "ADDR_STATE", + column.getColumnName().getText() + ); + + + final String zipComponentName = "zipcode"; + assertNotNull( attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( zipComponentName ) ); + assertTrue( attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( zipComponentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding zipCompositeBinding = (EmbeddedAttributeBinding) attributeCompositeBinding.getEmbeddableBinding().locateAttributeBinding( + zipComponentName + ); + + BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipCompositeBinding.getEmbeddableBinding().locateAttributeBinding( + "zip" + ); + assertEquals( 1, nameAttribute.getRelationalValueBindings().size() ); + column = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( + "Attribute override specifies a custom column name", + "ADDR_ZIP", + column.getColumnName().getText() + ); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Embeddable + public class A { + @Embedded + @AttributeOverrides( { + @AttributeOverride(name = "foo", column = @Column(name = "BAR")), + @AttributeOverride(name = "fubar", column = @Column(name = "A_WINS")) + }) + private B b; + + public B getB() { + return b; + } + } + + @Embeddable + public class B { + private String foo; + private String fubar; + + public String getFoo() { + return foo; + } + + public String getFubar() { + return fubar; + } + } + + @Entity + public class C { + @Id + int id; + + @Embedded + @AttributeOverride(name = "b.fubar", column = @Column(name = "C_WINS")) + protected A a; + + public int getId() { + return id; + } + + public A getA() { + return a; + } + } + + @Test + @Resources(annotatedClasses = { A.class, B.class, C.class }) + public void testAttributeOverrideInEmbeddable() { + EntityBinding binding = getEntityBinding( C.class ); + + final String aComponentName = "a"; + assertNotNull( binding.locateAttributeBinding( aComponentName ) ); + assertTrue( binding.locateAttributeBinding( aComponentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding aCompositeBinding = (EmbeddedAttributeBinding) binding.locateAttributeBinding( + aComponentName + ); + + final String bComponentName = "b"; + assertNotNull( aCompositeBinding.getEmbeddableBinding().locateAttributeBinding( bComponentName ) ); + assertTrue( aCompositeBinding.getEmbeddableBinding().locateAttributeBinding( bComponentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding bCompositeBinding = (EmbeddedAttributeBinding) aCompositeBinding.getEmbeddableBinding().locateAttributeBinding( + bComponentName + ); + + BasicAttributeBinding attribute = (BasicAttributeBinding) bCompositeBinding.getEmbeddableBinding().locateAttributeBinding( + "foo" + ); + assertEquals( 1, attribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) attribute.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( + "Attribute override specifies a custom column name", + "BAR", + column.getColumnName().getText() + ); + + attribute = (BasicAttributeBinding) bCompositeBinding.getEmbeddableBinding().locateAttributeBinding( "fubar" ); + assertEquals( 1, attribute.getRelationalValueBindings().size() ); + column = (org.hibernate.metamodel.spi.relational.Column) attribute.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( + "Attribute override specifies a custom column name", + "C_WINS", + column.getColumnName().getText() + ); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Embeddable + public class EmbeddableEntity { + private String test; + @Parent + private MainEntity parent; + + // require getter/setter for parent because of HHH-1614 + public MainEntity getParent() { + return parent; + } + + public void setParent(MainEntity parent) { + this.parent = parent; + } + } + + @Entity + public class MainEntity { + @Id + private int id; + + @Embedded + private EmbeddableEntity embedded; + } + + @Test + @Resources(annotatedClasses = { MainEntity.class, EmbeddableEntity.class }) + public void testParentReferencingAttributeName() { + EntityBinding binding = getEntityBinding( MainEntity.class ); + + final String componentName = "embedded"; + assertNotNull( binding.locateAttributeBinding( componentName ) ); + assertTrue( binding.locateAttributeBinding( componentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding compositeBinding = (EmbeddedAttributeBinding) binding.locateAttributeBinding( + componentName + ); + + assertNotNull( "No parent reference binding", compositeBinding.getEmbeddableBinding().getParentReference() ); + assertEquals( "Wrong parent reference name", "parent", compositeBinding.getEmbeddableBinding().getParentReference().getName() ); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + public interface Car { + int getHorsePower(); + void setHorsePower(int horsePower); + } + + @Embeddable + public class CarImpl implements Car { + private int horsePower; + + @Override + public int getHorsePower() { + return horsePower; + } + + @Override + public void setHorsePower(int horsePower) { + this.horsePower = horsePower; + } + } + + @Entity + public class Owner { + private int id; + private Car car; + + @Id + public int getId() { + return id; + } + + @Embedded + @Target(CarImpl.class) + public Car getCar() { + return car; + } + } + + @Test + @Resources(annotatedClasses = { Owner.class, CarImpl.class, Car.class }) + public void testTargetAnnotationWithEmbeddable() { + EntityBinding binding = getEntityBinding( Owner.class ); + + final String componentName = "car"; + assertNotNull( binding.locateAttributeBinding( componentName ) ); + assertTrue( binding.locateAttributeBinding( componentName ) instanceof EmbeddedAttributeBinding ); + EmbeddedAttributeBinding compositeBinding = (EmbeddedAttributeBinding) binding.locateAttributeBinding( + componentName + ); + + BasicAttributeBinding attribute = (BasicAttributeBinding) compositeBinding.getEmbeddableBinding().locateAttributeBinding( + "horsePower" + ); + assertTrue( attribute.getAttribute().isTypeResolved() ); + assertEquals( + "Wrong resolved type", + "int", + attribute.getAttribute().getSingularAttributeType().getName() + ); + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddedIdTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddedIdTest.java new file mode 100644 index 000000000000..af3370ea300d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddedIdTest.java @@ -0,0 +1,74 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; + +import org.junit.Test; + +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class EmbeddedIdTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = { User.class, Address.class }) + public void testEmbeddable() { + EntityBinding binding = getEntityBinding( User.class ); + EntityIdentifier identifier = binding.getHierarchyDetails().getEntityIdentifier(); + assertTrue( !identifier.isNonAggregatedComposite() ); + assertEquals( identifier.getNature(), EntityIdentifierNature.AGGREGATED_COMPOSITE ); + } + + @Entity + @Access(AccessType.FIELD) + class User { + private String name; + @EmbeddedId + private Address address; + } + + @Embeddable + class Address { + String street; + String city; + String postCode; + } +} + + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EnumeratedBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EnumeratedBindingTest.java similarity index 82% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EnumeratedBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EnumeratedBindingTest.java index 9049e08c60a0..9948139d9803 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EnumeratedBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EnumeratedBindingTest.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.sql.Types; import java.util.Date; @@ -33,11 +33,14 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.junit.Test; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.usertype.DynamicParameterizedType; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -75,12 +78,12 @@ public void testEnumeratedTypeAttribute() { AttributeBinding attributeBinding = binding.locateAttributeBinding( "customerType" ); HibernateTypeDescriptor descriptor = attributeBinding.getHibernateTypeDescriptor(); assertEquals( org.hibernate.type.EnumType.class.getName(), descriptor.getExplicitTypeName() ); - assertEquals( CustomerType.class.getName(), descriptor.getJavaTypeName() ); + assertEquals( CustomerType.class.getName(), descriptor.getJavaTypeDescriptor().getName().toString() ); assertNotNull( descriptor.getResolvedTypeMapping() ); assertFalse( descriptor.getTypeParameters().isEmpty() ); assertEquals( CustomerType.class.getName(), - descriptor.getTypeParameters().get( org.hibernate.type.EnumType.ENUM ) + descriptor.getTypeParameters().get( DynamicParameterizedType.RETURNED_CLASS ) ); assertEquals( String.valueOf( Types.INTEGER ), @@ -91,12 +94,12 @@ public void testEnumeratedTypeAttribute() { attributeBinding = binding.locateAttributeBinding( "orderType" ); descriptor = attributeBinding.getHibernateTypeDescriptor(); assertEquals( org.hibernate.type.EnumType.class.getName(), descriptor.getExplicitTypeName() ); - assertEquals( OrderType.class.getName(), descriptor.getJavaTypeName() ); + assertEquals( OrderType.class.getName(), descriptor.getJavaTypeDescriptor().getName().toString() ); assertNotNull( descriptor.getResolvedTypeMapping() ); assertFalse( descriptor.getTypeParameters().isEmpty() ); assertEquals( OrderType.class.getName(), - descriptor.getTypeParameters().get( org.hibernate.type.EnumType.ENUM ) + descriptor.getTypeParameters().get( DynamicParameterizedType.RETURNED_CLASS ) ); assertEquals( String.valueOf( Types.VARCHAR ), diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java new file mode 100644 index 000000000000..579a4ac3ff03 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/GenericTest.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import junit.framework.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +/** + * @author Strong Liu + */ +public class GenericTest extends BaseAnnotationBindingTestCase { + @Entity + @Inheritance + public abstract class Event { + private long id; + + @Id + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } + + @Entity + public class LoginEvent extends Event { + + } + + @Entity + @Inheritance + public abstract class Notification { + private long id; + private X event; + + @ManyToOne(optional = false, targetEntity = Event.class) + @JoinColumn + public X getEvent() { + return event; + } + + public void setEvent(X event) { + this.event = event; + } + + @Id + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } + + @Entity + public class LoginNotification extends Notification { + + } + + @Test + @Ignore("not finished yet") + @Resources(annotatedClasses = { LoginNotification.class, Notification.class, LoginEvent.class, Event.class }) + public void testGenericProperty() { + EntityBinding entityBinding = getEntityBinding( LoginNotification.class ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( "event" ); +// Assert.assertNotNull( attributeBinding ); + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/IdentifierGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/IdentifierGeneratorTest.java similarity index 90% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/IdentifierGeneratorTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/IdentifierGeneratorTest.java index c5f0afbbf037..0224174ae695 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/IdentifierGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/IdentifierGeneratorTest.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -22,13 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.fail; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -45,12 +39,21 @@ import org.hibernate.id.SequenceHiLoGenerator; import org.hibernate.id.UUIDHexGenerator; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityIdentifier; -import org.hibernate.metamodel.source.MappingException; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; + import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import org.junit.Test; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + /** * @author Hardy Ferentschik */ @@ -70,7 +73,7 @@ public void testNoIdGeneration() { IdentifierGenerator generator =identifier.getIdentifierGenerator(); assertNotNull( generator ); assertEquals( "Wrong generator", Assigned.class, generator.getClass() ); - assertFalse( identifier.isEmbedded() ); + assertFalse( identifier.isNonAggregatedComposite() ); } @@ -155,7 +158,7 @@ public void testUndefinedGenerator() { fail(); } catch ( MappingException e ) { - assertTrue( e.getMessage().startsWith( "Unable to find named generator" ) ); + assertTrue( e.getMessage().contains( "Unable to find named generator" ) ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/InheritanceBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/InheritanceBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java index 6ba182dd8df9..4c3fbf5f6a55 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/InheritanceBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.util.HashSet; import java.util.Iterator; @@ -33,15 +33,18 @@ import javax.persistence.GeneratedValue; import javax.persistence.Id; -import org.junit.Test; - import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.DiscriminatorOptions; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityDiscriminator; -import org.hibernate.metamodel.relational.DerivedValue; -import org.hibernate.metamodel.relational.SimpleValue; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.Value; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -74,8 +77,10 @@ public void testDiscriminatorValue() { public void testSubclassEntitySuperType() { EntityBinding entityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class ); assertNotNull( entityBinding.getEntity().getSuperType() ); - assertSame( RootOfSingleTableInheritance.class, entityBinding.getEntity().getSuperType().getClassReference() ); - assertEquals( RootOfSingleTableInheritance.class.getName(), entityBinding.getEntity().getSuperType().getClassName() ); + assertEquals( + RootOfSingleTableInheritance.class.getName(), + entityBinding.getEntity().getSuperType().getDescriptor().getName().toString() + ); assertNull( entityBinding.getEntity().getSuperType().getSuperType() ); } @@ -122,30 +127,33 @@ public void testNoPolymorphism() { assertFalse( noInheritanceEntityBinding.isPolymorphic() ); assertFalse( noInheritanceEntityBinding.hasSubEntityBindings() ); assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingClosureSpan() ); - assertFalse( noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() ); - assertFalse( noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() ); + assertEquals( 0, noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().length ); + assertEquals( 0, noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().length ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); } assertEquals( 1, directAttributeBindings.size() ); assertSame( - noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), + noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), directAttributeBindings.iterator().next() ); assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() ); Iterator iterator = noInheritanceEntityBinding.attributeBindings().iterator(); assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); - assertFalse( iterator.hasNext() ); - iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator(); - assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); - assertFalse( iterator.hasNext() ); - iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator(); - assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() ); assertFalse( iterator.hasNext() ); + + AttributeBinding[] attributeBindings = noInheritanceEntityBinding.getAttributeBindingClosure(); + assertTrue( attributeBindings.length > 0 ); + int index =0; + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] ); + assertFalse( index < attributeBindings.length ); + attributeBindings = noInheritanceEntityBinding.getEntitiesAttributeBindingClosure(); + index = 0; + assertTrue( attributeBindings.length > 0 ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] ); + assertFalse( index < attributeBindings.length ); } @Test @@ -156,14 +164,14 @@ public void testNoPolymorphism() { OtherSubclassOfSingleTableInheritance.class, SubclassOfSubclassOfSingleTableInheritance.class }) - public void testRootPolymporhism() { + public void testRootPolymporphism() { EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class ); EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class ); EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class ); EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class ); assertTrue( rootEntityBinding.isRoot() ); - assertNull( rootEntityBinding.getDiscriminatorMatchValue() ); + assertEquals( StringHelper.unqualify( rootEntityBinding.getEntityName() ), rootEntityBinding.getDiscriminatorMatchValue() ); assertNull( rootEntityBinding.getSuperEntityBinding() ); assertSame( rootEntityBinding, getRootEntityBinding( RootOfSingleTableInheritance.class ) ); assertTrue( rootEntityBinding.isPolymorphic() ); @@ -196,7 +204,7 @@ public void testRootPolymporhism() { assertEquals( 1, attributeBindingClosure.size() ); assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : rootEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : rootEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 4, subAttributeBindings.size() ); @@ -223,23 +231,24 @@ public void testPreOrderRootSubEntityClosure() { Iterator directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator(); boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next(); assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() ); - Iterator subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure().iterator(); - assertTrue( subEntityBindingIterator.hasNext() ); + EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure(); + assertTrue( subEntityBindingIterator.length > 0 ); + int i = 0; if ( isSubclassEntityBindingFirst ) { - assertSame( subclassEntityBinding, subEntityBindingIterator.next() ); - assertTrue( subEntityBindingIterator.hasNext() ); - assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() ); - assertTrue( subEntityBindingIterator.hasNext() ); - assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() ); + assertSame( subclassEntityBinding, subEntityBindingIterator[i++] ); + assertTrue( i directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator(); boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next(); assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() ); - Iterator subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure().iterator(); - assertTrue( subEntityBindingIterator.hasNext() ); + EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure(); + int i =0; + assertTrue( subEntityBindingIterator.length > 0 ); if ( isSubclassEntityBindingFirst ) { - assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( subclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() ); + assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( subclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] ); } else { - assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() ); - assertSame( subclassEntityBinding, subEntityBindingIterator.next() ); + assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] ); + assertSame( subclassEntityBinding, subEntityBindingIterator[i++] ); } - assertFalse( subEntityBindingIterator.hasNext() ); + assertFalse( i < subEntityBindingIterator.length ); } @Test @@ -295,8 +305,8 @@ public void testLeafSubclassOfRoot() { assertTrue( otherSubclassEntityBinding.isPolymorphic() ); assertFalse( otherSubclassEntityBinding.hasSubEntityBindings() ); assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingClosureSpan() ); - assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() ); - assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() ); + assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 ); + assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); @@ -312,7 +322,7 @@ public void testLeafSubclassOfRoot() { assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) ); assertTrue( attributeBindingClosure.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 2, subAttributeBindings.size() ); @@ -341,14 +351,16 @@ public void testNonLeafSubclassOfRootPolymporhism() { assertTrue( subclassEntityBinding.isPolymorphic() ); assertTrue( subclassEntityBinding.hasSubEntityBindings() ); assertEquals( 1, subclassEntityBinding.getSubEntityBindingClosureSpan() ); - Iterator itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator(); - assertTrue( itSubEntityBindings.hasNext() ); - assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() ); - assertFalse( itSubEntityBindings.hasNext() ); - itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator(); - assertTrue( itSubEntityBindings.hasNext() ); - assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() ); - assertFalse( itSubEntityBindings.hasNext() ); + EntityBinding[] itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure(); + int i = 0; + assertTrue( i < itSubEntityBindings.length ); + assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] ); + assertFalse( i < itSubEntityBindings.length ); + itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure(); + i = 0; + assertTrue( i < itSubEntityBindings.length ); + assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] ); + assertFalse( i < itSubEntityBindings.length ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : subclassEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); @@ -364,7 +376,7 @@ public void testNonLeafSubclassOfRootPolymporhism() { assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) ); assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 3, subAttributeBindings.size() ); @@ -394,8 +406,8 @@ public void testLeafSubclassOfSubclassOfRootPolymporhism() { assertTrue( subclassOfSubclassEntityBinding.isPolymorphic() ); assertFalse( subclassOfSubclassEntityBinding.hasSubEntityBindings() ); assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingClosureSpan() ); - assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() ); - assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() ); + assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 ); + assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 ); Set directAttributeBindings = new HashSet(); for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.attributeBindings() ) { assertTrue( directAttributeBindings.add( attributeBinding ) ); @@ -412,7 +424,7 @@ public void testLeafSubclassOfSubclassOfRootPolymporhism() { assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) ); assertTrue( attributeBindingClosure.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) ); Set subAttributeBindings = new HashSet(); - for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) { + for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) { assertTrue( subAttributeBindings.add( subAttributeBinding ) ); } assertEquals( 3, subAttributeBindings.size() ); @@ -446,23 +458,23 @@ public void testRootDiscriminatorMatchValue() { assertEquals( "base", rootEntityBinding.getDiscriminatorMatchValue() ); } - @Test - @Resources(annotatedClasses = { Fruit.class, Apple.class }) - public void testDiscriminatorFormula() { - EntityBinding rootEntityBinding = getEntityBinding( Fruit.class ); - assertTrue( rootEntityBinding.isRoot() ); - EntityBinding entityBinding = getEntityBinding( Apple.class ); - assertFalse( entityBinding.isRoot() ); + @Test + @Resources(annotatedClasses = { Fruit.class, Apple.class }) + public void testDiscriminatorFormula() { + EntityBinding rootEntityBinding = getEntityBinding( Fruit.class ); + assertTrue( rootEntityBinding.isRoot() ); + EntityBinding entityBinding = getEntityBinding( Apple.class ); + assertFalse( entityBinding.isRoot() ); EntityDiscriminator discriminator = rootEntityBinding.getHierarchyDetails().getEntityDiscriminator(); - SimpleValue simpleValue = discriminator.getBoundValue(); - assertTrue( simpleValue instanceof DerivedValue); - DerivedValue derivedValue = (DerivedValue)simpleValue; - assertEquals( "case when zik_type is null then 0 else zik_type end", derivedValue.getExpression() ); + Value simpleValue = discriminator.getRelationalValue(); + assertTrue( simpleValue instanceof DerivedValue); + DerivedValue derivedValue = (DerivedValue)simpleValue; + assertEquals( "case when zik_type is null then 0 else zik_type end", derivedValue.getExpression() ); assertTrue( "Wrong default value", discriminator.isForced() ); assertFalse( "Wrong default value", discriminator.isInserted() ); - } + } - @Entity + @Entity class SingleEntity { @Id @GeneratedValue @@ -507,19 +519,19 @@ class Base { class Jump extends Base { } - @Entity - @DiscriminatorColumn(discriminatorType = DiscriminatorType.INTEGER) - @DiscriminatorFormula("case when zik_type is null then 0 else zik_type end") - @DiscriminatorOptions(force = true, insert = false) - class Fruit { - @Id - private int id; - } + @Entity + @DiscriminatorColumn(discriminatorType = DiscriminatorType.INTEGER) + @DiscriminatorFormula("case when zik_type is null then 0 else zik_type end") + @DiscriminatorOptions(force = true, insert = false) + class Fruit { + @Id + private int id; + } - @Entity - class Apple extends Fruit { + @Entity + class Apple extends Fruit { - } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/LobBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/LobBindingTests.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/LobBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/LobBindingTests.java index 6069d630484d..0a1e8048de98 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/LobBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/LobBindingTests.java @@ -22,7 +22,7 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.io.Serializable; import java.sql.Blob; @@ -31,11 +31,9 @@ import javax.persistence.Id; import javax.persistence.Lob; -import org.junit.Test; - -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; import org.hibernate.type.BlobType; import org.hibernate.type.CharacterArrayClobType; import org.hibernate.type.ClobType; @@ -46,6 +44,10 @@ import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.WrappedMaterializedBlobType; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -114,7 +116,7 @@ private ExpectedValue(String explicitTypeName, private void checkHibernateTypeDescriptor(ExpectedValue expectedValue, String attributeName) { HibernateTypeDescriptor descriptor = getTypeDescriptor( attributeName ); assertEquals( expectedValue.explicitTypeName, descriptor.getExplicitTypeName() ); - assertEquals( expectedValue.javaTypeName, descriptor.getJavaTypeName() ); + assertEquals( expectedValue.javaTypeName, descriptor.getJavaTypeDescriptor().getName().toString() ); assertEquals( expectedValue.isResolvedTypeMappingNull, descriptor.getResolvedTypeMapping() == null ); assertEquals( expectedValue.resolvedTypeMappingClass, descriptor.getResolvedTypeMapping().getClass() ); assertEquals( expectedValue.isTypeParametersNull, descriptor.getTypeParameters() == null ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java new file mode 100644 index 000000000000..e712cb179257 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; + +/** + * Tests for {@link javax.persistence.MappedSuperclass} {@link javax.persistence.AttributeOverrides} + * and {@link javax.persistence.AttributeOverride}. + * + * @author Hardy Ferentschik + */ +public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) + public void testSimpleAttributeOverrideInMappedSuperclass() { + EntityBinding binding = getEntityBinding( MyEntity.class ); + SingularAttributeBinding nameBinding = ( SingularAttributeBinding ) binding.locateAttributeBinding( "name" ); + assertNotNull( "the name attribute should be bound to MyEntity", nameBinding ); + + assertEquals( 1, nameBinding.getRelationalValueBindings().size() ); + Column column = ( Column ) nameBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( "Wrong column name", "MY_NAME", column.getColumnName().toString() ); + } + + @Test + @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) + public void testLastAttributeOverrideWins() { + EntityBinding binding = getEntityBinding( MyEntity.class ); + SingularAttributeBinding fooBinding = ( SingularAttributeBinding ) binding.locateAttributeBinding( "foo" ); + assertNotNull( "the foo attribute should be bound to MyEntity", fooBinding ); + + assertEquals( 1, fooBinding.getRelationalValueBindings().size() ); + Column column = ( Column ) fooBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( "Wrong column name", "MY_FOO", column.getColumnName().toString() ); + } + + @Test + @Resources(annotatedClasses = { SubclassOfNoEntity.class, NoEntity.class }) + public void testNonEntityBaseClass() { + EntityBinding binding = getEntityBinding( SubclassOfNoEntity.class ); + assertEquals( "Wrong entity name", SubclassOfNoEntity.class.getName(), binding.getEntityName() ); + assertNull( "Supertype should not be mapped", binding.getEntity().getSuperType() ); + } + + @Test + @Resources(annotatedClasses = { Foo.class, SuperFoo.class }) + public void testOverrideOfIdAttribute() { + EntityBinding binding = getEntityBinding( Foo.class ); + + SingularAttributeBinding idAttributeBinding = ( SingularAttributeBinding ) binding.locateAttributeBinding( "id" ); + assertNotNull( "the id attribute should be bound to Foo", idAttributeBinding ); + + assertEquals( 1, idAttributeBinding.getRelationalValueBindings().size() ); + Column column = ( Column ) idAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertEquals( "Wrong column name", "FOO_ID", column.getColumnName().toString() ); + assertEquals( "Wrong column name", 1, column.getSize().getLength() ); + } + + @MappedSuperclass + class MyMappedSuperClassBase { + @Id + private int id; + String foo; + } + + @MappedSuperclass + @AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "SUPER_FOO")) + class MyMappedSuperClass extends MyMappedSuperClassBase { + String name; + } + + @Entity + @AttributeOverrides({ + @AttributeOverride(name = "name", column = @javax.persistence.Column(name = "MY_NAME")), + @AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "MY_FOO")) + }) + class MyEntity extends MyMappedSuperClass { + private Long count; + + } + + class NoEntity { + String name; + int age; + } + + @Entity + class SubclassOfNoEntity extends NoEntity { + @Id + private int id; + } + + + @MappedSuperclass + class SuperFoo { + @Id + private int id; + } + + @Entity + @AttributeOverride(name = "id", column = @javax.persistence.Column(name = "FOO_ID", length = 1)) + class Foo extends SuperFoo { + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MapsIdTest.java similarity index 81% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MapsIdTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MapsIdTest.java index 81b0a3b8b57b..ddb0607e00a2 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MapsIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MapsIdTest.java @@ -22,19 +22,22 @@ * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; +import java.util.List; import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.MapsId; import javax.persistence.OneToMany; -import org.junit.Test; - import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MappingException; +import org.hibernate.metamodel.source.spi.MappingException; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.junit.Test; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -59,17 +62,16 @@ public class DependentId { @Entity public class Dependent { - @Id // should be @EmbeddedId, but embedded id are not working atm - DependentId id; + @EmbeddedId + DependentId id; @MapsId("empid") @OneToMany - Employee emp; // maps the empid attribute of embedded id @ManyToOne Employee emp; + List emp; // maps the empid attribute of embedded id @ManyToOne Employee emp; } @Test - @Resources(annotatedClasses = DependentId.class) public void testMapsIsOnOneToManyThrowsException() { try { sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); @@ -81,12 +83,13 @@ public void testMapsIsOnOneToManyThrowsException() { } catch ( MappingException e ) { assertTrue( - e.getMessage() - .startsWith( "@MapsId can only be specified on a many-to-one or one-to-one associations" ) + e.getMessage().contains( + "@MapsId can only be specified on a many-to-one or one-to-one associations" + ) ); assertEquals( "Wrong error origin", - "org.hibernate.metamodel.source.annotations.entity.MapsIdTest$Dependent", + MapsIdTest.Dependent.class.getName(), e.getOrigin().getName() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java new file mode 100644 index 000000000000..960a3a8931eb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/NaturalIdBindingTests.java @@ -0,0 +1,196 @@ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.List; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.TruthValue; +import org.hibernate.annotations.NaturalId; +import org.hibernate.annotations.NaturalIdCache; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class NaturalIdBindingTests extends BaseAnnotationBindingTestCase { + @Entity + public class SimpleEntityWithNaturalId { + @Id + long id; + @NaturalId + String name; + @NaturalId(mutable = true) + int age; + } + + @Test + @Resources(annotatedClasses = NaturalIdBindingTests.SimpleEntityWithNaturalId.class) + public void testSimpleNaturalIdAttributeBinding() { + EntityBinding entityBinding = getEntityBinding( SimpleEntityWithNaturalId.class ); + assertEquals( TruthValue.FALSE, entityBinding.getHierarchyDetails().getNaturalIdCaching().getRequested() ); + + SingularAttributeBinding attributeBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( + "name" + ); + assertEquals( + NaturalIdMutability.IMMUTABLE, + attributeBinding.getNaturalIdMutability() + ); + + List relationalValueBindings = attributeBinding.getRelationalValueBindings(); + assertEquals( 1, relationalValueBindings.size() ); + + RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + + assertFalse( + "immutable (by default) natural id should not be included in the update list", + relationalValueBinding.isIncludeInUpdate() + ); + + Column column = Column.class.cast( relationalValueBinding.getValue() ); + +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + + //------------------------------------------------------------------------------------------------------- + attributeBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( + "age" + ); + assertEquals( + NaturalIdMutability.MUTABLE, + attributeBinding.getNaturalIdMutability() + ); + + relationalValueBindings = attributeBinding.getRelationalValueBindings(); + assertEquals( 1, relationalValueBindings.size() ); + + relationalValueBinding = relationalValueBindings.get( 0 ); + + assertTrue( + "mutable natural id should be included in the update list", + relationalValueBinding.isIncludeInUpdate() + ); + + column = Column.class.cast( relationalValueBinding.getValue() ); + +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + // ----------------------------------------------------------------------------------------------------- + + assertTrue( SchemaUtil.columnHasUniqueKey( entityBinding.getPrimaryTable(), "age" ) ); + assertTrue( SchemaUtil.columnHasUniqueKey( entityBinding.getPrimaryTable(), "name" ) ); + } + + @Entity + public class EntityWithEmbedded { + @Id + long id; + @NaturalId + @Embedded + Component component; + + } + + @Embeddable + public class Component { + String name; + String age; + } + + @Test + @Resources(annotatedClasses = { EntityWithEmbedded.class, Component.class }) + public void testEmbeddedNaturalIdAttributeBinding() { + EntityBinding entityBinding = getEntityBinding( EntityWithEmbedded.class ); + assertEquals( TruthValue.FALSE, entityBinding.getHierarchyDetails().getNaturalIdCaching().getRequested() ); + + SingularAttributeBinding attributeBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( + "component" + ); + assertEquals( + NaturalIdMutability.IMMUTABLE, + attributeBinding.getNaturalIdMutability() + ); + + List relationalValueBindings = attributeBinding.getRelationalValueBindings(); + for ( RelationalValueBinding valueBinding : relationalValueBindings ) { + assertFalse( + "immutable (by default) natural id should not be included in the update list", + valueBinding.isIncludeInUpdate() + ); + Column column = Column.class.cast( valueBinding.getValue() ); +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + } + + assertTrue( SchemaUtil.columnHasUniqueKey( entityBinding.getPrimaryTable(), "age" ) ); + assertTrue( SchemaUtil.columnHasUniqueKey( entityBinding.getPrimaryTable(), "name" ) ); + } + + @Entity + @NaturalIdCache + public class EntityWithAssociation { + @Id + long id; + + @NaturalId + String name; + + @ManyToOne + @NaturalId + SimpleEntity simpleEntity; + } + + @Entity + public class SimpleEntity { + @Id + long id; + String simpleName; + } + + @Test + @Resources(annotatedClasses = { + EntityWithAssociation.class, + SimpleEntity.class + }) + public void testAssociationNaturalIdBinding() { + EntityBinding entityBinding = getEntityBinding( EntityWithAssociation.class ); + assertNotNull( entityBinding.getHierarchyDetails().getNaturalIdCaching() ); + assertNull( entityBinding.getHierarchyDetails().getNaturalIdCaching().getRegion() ); + + SingularAttributeBinding attributeBinding = (SingularAttributeBinding)entityBinding.locateAttributeBinding( "simpleEntity" ); + assertEquals( NaturalIdMutability.IMMUTABLE, attributeBinding.getNaturalIdMutability() ); + + List relationalValueBindings = attributeBinding.getRelationalValueBindings(); + assertEquals( 1, relationalValueBindings.size() ); + RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + + assertFalse( + "immutable natural id should not be included in the update list", + relationalValueBinding.isIncludeInUpdate() + ); + + Column column = Column.class.cast( relationalValueBinding.getValue() ); + +// assertFalse( "natural id column should not be nullable", column.isNullable() ); + // ----------------------------------------------------------------------------------------------------- + + assertTrue( SchemaUtil.columnHasUniqueKey( entityBinding.getPrimaryTable(), "name" ) ); + assertTrue( SchemaUtil.columnHasUniqueKey( entityBinding.getPrimaryTable(), "simpleEntity_id" ) ); + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java new file mode 100644 index 000000000000..ffc889dd1ffa --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/OneToManyBindingTest.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import org.junit.Test; + +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.test.annotations.loader.Player; +import org.hibernate.test.annotations.loader.Team; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class OneToManyBindingTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = { Team.class, Player.class }) + public void testPluralAttributeBindingTest() { + EntityBinding playerBinding = getEntityBinding( Player.class ); + assertNotNull( playerBinding ); + + AttributeBinding attributeBinding = playerBinding.locateAttributeBinding( "team" ); + assertTrue( attributeBinding.isAssociation() ); + + HibernateTypeDescriptor typeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + EntityBinding teamBinding = getEntityBinding( Team.class ); + assertNotNull( teamBinding ); + attributeBinding = teamBinding.locateAttributeBinding( "players" ); + assertTrue( attributeBinding.isAssociation() ); + typeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + PluralAttributeBinding pluralAttributeBinding = PluralAttributeBinding.class.cast( attributeBinding ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/ProxyBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ProxyBindingTest.java similarity index 81% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/ProxyBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ProxyBindingTest.java index b27dea539995..a2cafc0d9c21 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/ProxyBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/ProxyBindingTest.java @@ -21,15 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; -import org.junit.Test; - import org.hibernate.annotations.Proxy; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -46,7 +48,11 @@ public class ProxyBindingTest extends BaseAnnotationBindingTestCase { public void testProxyNoAttributes() { EntityBinding binding = getEntityBinding( ProxiedEntity.class ); assertTrue( "Wrong laziness", binding.isLazy() ); - assertEquals( "Wrong proxy interface", ProxiedEntity.class, binding.getProxyInterfaceType().getValue() ); + assertEquals( + "Wrong proxy interface", + ProxiedEntity.class.getName(), + binding.getProxyInterfaceType().getName().toString() + ); } @Test @@ -54,7 +60,11 @@ public void testProxyNoAttributes() { public void testNoProxy() { EntityBinding binding = getEntityBinding( NoProxyEntity.class ); assertTrue( "Wrong laziness", binding.isLazy() ); - assertEquals( "Wrong proxy interface", NoProxyEntity.class, binding.getProxyInterfaceType().getValue() ); + assertEquals( + "Wrong proxy interface", + NoProxyEntity.class.getName(), + binding.getProxyInterfaceType().getName().toString() + ); } @Test @@ -72,8 +82,8 @@ public void testProxyInterface() { assertTrue( "Wrong laziness", binding.isLazy() ); assertEquals( "Wrong proxy interface", - "org.hibernate.metamodel.source.annotations.entity.ProxyBindingTest$ProxyInterfaceEntity", - binding.getProxyInterfaceType().getValue().getName() + ProxyBindingTest.ProxyInterfaceEntity.class.getName(), + binding.getProxyInterfaceType().getName().toString() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/QuotedIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/QuotedIdentifierTest.java new file mode 100644 index 000000000000..9e5452980238 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/QuotedIdentifierTest.java @@ -0,0 +1,96 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.junit.Test; + +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static org.junit.Assert.assertEquals; + +/** + * @author Strong Liu + */ +public class QuotedIdentifierTest extends BaseAnnotationBindingTestCase { + private final String ormPath = "org/hibernate/metamodel/internal/source/annotations/xml/orm-quote-identifier.xml"; + + @Test + @Resources(annotatedClasses = { Item.class, Item2.class, Item3.class, Item4.class }, ormXmlPath = ormPath) + public void testDelimitedIdentifiers() { + EntityBinding item = getEntityBinding( Item.class ); + assertIdentifierEquals( "`QuotedIdentifierTest$Item`", item ); + + item = getEntityBinding( Item2.class ); + assertIdentifierEquals( "`TABLE_ITEM2`", item ); + + item = getEntityBinding( Item3.class ); + assertIdentifierEquals( "`TABLE_ITEM3`", item ); + + // TODO: not sure about this -- revisit after metamodel merge +// item = getEntityBinding( Item4.class ); +// assertIdentifierEquals( "`TABLE_ITEM4`", item ); + } + + //todo check if the column names are quoted + + private void assertIdentifierEquals(String expected, EntityBinding realValue) { + org.hibernate.metamodel.spi.relational.Table table = (org.hibernate.metamodel.spi.relational.Table) realValue.getPrimaryTable(); + assertEquals( Identifier.toIdentifier( expected ), table.getPhysicalName() ); + } + + @Entity + private static class Item { + @Id + Long id; + } + + @Entity + @Table(name = "TABLE_ITEM2") + private static class Item2 { + @Id + Long id; + } + + @Entity + @Table(name = "`TABLE_ITEM3`") + private static class Item3 { + @Id + Long id; + } + + @Entity + @Table(name = "\"TABLE_ITEM4\"") + private static class Item4 { + @Id + Long id; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/RowIdBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/RowIdBindingTests.java similarity index 79% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/RowIdBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/RowIdBindingTests.java index 7874ce1968ca..9732953c5ccf 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/RowIdBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/RowIdBindingTests.java @@ -21,15 +21,18 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.Id; -import org.junit.Test; - import org.hibernate.annotations.RowId; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Table; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; import static junit.framework.Assert.assertEquals; @@ -43,14 +46,14 @@ public class RowIdBindingTests extends BaseAnnotationBindingTestCase { @Resources(annotatedClasses = NoRowIdEntity.class) public void testNoRowId() { EntityBinding binding = getEntityBinding( NoRowIdEntity.class ); - assertEquals( "Wrong row id", null, binding.getRowId() ); + assertEquals( "Wrong row id", null, ( (Table) binding.getPrimaryTable() ).getRowId() ); } @Test @Resources(annotatedClasses = RowIdEntity.class) public void testRowId() { EntityBinding binding = getEntityBinding( RowIdEntity.class ); - assertEquals( "Wrong row id", "rowid", binding.getRowId() ); + assertEquals( "Wrong row id", "rowid", ( (Table) binding.getPrimaryTable() ).getRowId() ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java new file mode 100644 index 000000000000..73b2e1602254 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java @@ -0,0 +1,109 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.Iterator; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.SecondaryTable; + +import org.junit.Test; + +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertSame; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +/** + * @author Hardy Ferentschik + */ +public class SecondaryTableTest extends BaseAnnotationBindingTestCase { + @Entity + @SecondaryTable(name = "SECOND_TABLE") + @SuppressWarnings( {"UnusedDeclaration"}) + class EntityWithSecondaryTable { + @Id + private long id; + + @Column(table = "SECOND_TABLE") + private String name; + } + + @Test + @Resources(annotatedClasses = EntityWithSecondaryTable.class) + public void testSecondaryTableExists() { + EntityBinding binding = getEntityBinding( EntityWithSecondaryTable.class ); + Table table = (Table) binding.locateTable( "SECOND_TABLE" ); + assertEquals( "The secondary table should exist", "SECOND_TABLE", table.getPhysicalName().getText() ); + + assertEquals( 2, table.values().size() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) table.values().get( 0 ); + // TODO: the first column should be the secondary table's primary key??? + //assertSame( "First column is not the primary key", table.getPrimaryKey().getColumns().get( 0 ), column ); + // the second column should be the column for the attribute + column = (org.hibernate.metamodel.spi.relational.Column) table.values().get( 1 ); + assertEquals( "Wrong column name", "name", column.getColumnName().getText() ); + + Iterator fkIterator = table.getForeignKeys().iterator(); + assertTrue( fkIterator.hasNext() ); + ForeignKey foreignKey = fkIterator.next(); + assertEquals( "Wrong number of foreign key columns", 1, foreignKey.getTargetColumns().size() ); + assertSame( "Wrong column is the foreign key column", table.values().get( 0 ), foreignKey.getSourceColumns().get( 0 ) ); + assertEquals( "Wrong foreign key target column", binding.getPrimaryTable().getPrimaryKey().getColumns(), foreignKey.getTargetColumns() ); + assertFalse( fkIterator.hasNext() ); + + BasicAttributeBinding nameAttrBinding = (BasicAttributeBinding) binding.locateAttributeBinding( "name" ); + assertEquals( 1, nameAttrBinding.getRelationalValueBindings().size() ); + RelationalValueBinding valueBinding = nameAttrBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + assertSame( table, valueBinding.getTable() ); + assertSame( column, valueBinding.getValue() ); + } + + @Test + @Resources(annotatedClasses = EntityWithSecondaryTable.class) + public void testRetrievingUnknownTable() { + EntityBinding binding = getEntityBinding( EntityWithSecondaryTable.class ); + try { + binding.locateTable( "FOO" ); + fail(); + } + catch ( AssertionFailure e ) { + assertTrue( e.getMessage().startsWith( "Unable to find table" ) ); + } + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SynchronizeBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SynchronizeBindingTest.java similarity index 75% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SynchronizeBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SynchronizeBindingTest.java index 04bf0ec8a9aa..0aca288a5942 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SynchronizeBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SynchronizeBindingTest.java @@ -21,16 +21,17 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; -import java.util.Set; import javax.persistence.Entity; import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.Synchronize; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -45,17 +46,26 @@ public class SynchronizeBindingTest extends BaseAnnotationBindingTestCase { @Resources(annotatedClasses = TestEntityWithSynchronizeAnnotation.class) public void testSynchronizeAnnotation() { EntityBinding binding = getEntityBinding( TestEntityWithSynchronizeAnnotation.class ); - Set synchronizedTableNames = binding.getSynchronizedTableNames(); - assertEquals( "Wrong number of synced tables", 2, synchronizedTableNames.size() ); - assertTrue( "Table name missing", synchronizedTableNames.contains( "Foo" ) ); - assertTrue( "Table name missing", synchronizedTableNames.contains( "Bar" ) ); + String [] synchronizedTableNames = binding.getSynchronizedTableNames(); + assertEquals( "Wrong number of synced tables", 2, synchronizedTableNames.length ); + assertTrue( "Table name missing", contains( synchronizedTableNames, "Foo" ) ); + assertTrue( "Table name missing", contains( synchronizedTableNames, "Bar" ) ); + } + + private boolean contains(String[] arrays, String key) { + for ( String s : arrays ) { + if ( key.equals( s ) ) { + return true; + } + } + return false; } @Test @Resources(annotatedClasses = TestEntity.class) public void testNoSynchronizeAnnotation() { EntityBinding binding = getEntityBinding( TestEntity.class ); - assertTrue( "There should be no cache binding", binding.getSynchronizedTableNames().size() == 0 ); + assertTrue( "There should be no cache binding", binding.getSynchronizedTableNames().length == 0 ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TableNameTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TableNameTest.java similarity index 80% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TableNameTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TableNameTest.java index eb31eb09b932..75b0845a7b66 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TableNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TableNameTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -31,8 +31,10 @@ import org.junit.Test; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.InheritanceType; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; import static junit.framework.Assert.assertEquals; @@ -59,7 +61,7 @@ public void testSingleInheritanceDefaultTableName() { assertEquals( "wrong table name", "TableNameTest$A", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); binding = getEntityBinding( B.class ); @@ -67,7 +69,7 @@ public void testSingleInheritanceDefaultTableName() { assertEquals( "wrong table name", "TableNameTest$A", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); } @@ -92,7 +94,7 @@ public void testJoinedSubclassDefaultTableName() { assertEquals( "wrong table name", "FOO", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); binding = getEntityBinding( JoinedB.class ); @@ -100,7 +102,7 @@ public void testJoinedSubclassDefaultTableName() { assertEquals( "wrong table name", "TableNameTest$JoinedB", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); } @@ -125,7 +127,7 @@ public void testTablePerClassDefaultTableName() { assertEquals( "wrong table name", "TableNameTest$TablePerClassA", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); binding = getEntityBinding( TablePerClassB.class ); @@ -133,7 +135,7 @@ public void testTablePerClassDefaultTableName() { assertEquals( "wrong table name", "TableNameTest$TablePerClassB", - ( (org.hibernate.metamodel.relational.Table) binding.getPrimaryTable() ).getTableName().getName() + ( (org.hibernate.metamodel.spi.relational.Table) binding.getPrimaryTable() ).getPhysicalName().getText() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TemporalBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TemporalBindingTest.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TemporalBindingTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TemporalBindingTest.java index b85b6c9d3266..ba20ee1c067d 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/TemporalBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/TemporalBindingTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.metamodel.internal.source.annotations.entity; import java.util.Date; import javax.persistence.Entity; @@ -29,37 +29,26 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.junit.Test; - -import org.hibernate.AnnotationException; -import org.hibernate.metamodel.binding.AttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; import org.hibernate.type.TimestampType; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; + /** * @author Strong Liu */ public class TemporalBindingTest extends BaseAnnotationBindingTestCase { - @Entity - class Item1 { - @Id - long id; - Date date; - } - - @Test(expected = AnnotationException.class) - @Resources(annotatedClasses = TemporalBindingTest.Item1.class) - public void testNoTemporalAnnotationOnTemporalTypeAttribute() { - getEntityBinding( Item1.class ); - - } - - @Entity + + @Entity class Item2 { @Id long id; @@ -74,7 +63,7 @@ public void testTemporalTypeAttribute() { AttributeBinding attributeBinding = binding.locateAttributeBinding( "date" ); HibernateTypeDescriptor descriptor = attributeBinding.getHibernateTypeDescriptor(); assertEquals( "timestamp", descriptor.getExplicitTypeName() ); - assertEquals( Date.class.getName(), descriptor.getJavaTypeName() ); + assertEquals( Date.class.getName(), descriptor.getJavaTypeDescriptor().getName().toString() ); assertNotNull( descriptor.getResolvedTypeMapping() ); assertEquals( TimestampType.class, descriptor.getResolvedTypeMapping().getClass() ); assertNotNull( descriptor.getTypeParameters() ); @@ -95,7 +84,7 @@ public void testTemporalTypeAsId() { AttributeBinding attributeBinding = binding.locateAttributeBinding( "date" ); HibernateTypeDescriptor descriptor = attributeBinding.getHibernateTypeDescriptor(); assertEquals( "timestamp", descriptor.getExplicitTypeName() ); - assertEquals( Date.class.getName(), descriptor.getJavaTypeName() ); + assertEquals( Date.class.getName(), descriptor.getJavaTypeDescriptor().getName().toString() ); assertNotNull( descriptor.getResolvedTypeMapping() ); assertEquals( TimestampType.class, descriptor.getResolvedTypeMapping().getClass() ); assertNotNull( descriptor.getTypeParameters() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java new file mode 100644 index 000000000000..de9e7faab7b8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/UniqueConstraintBindingTest.java @@ -0,0 +1,129 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.metamodel.internal.source.annotations.entity; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import java.util.List; +import java.util.Set; + +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.OrderColumn; +import javax.persistence.Table; +import javax.persistence.TableGenerator; +import javax.persistence.UniqueConstraint; + +import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +/** + * test for {@link javax.persistence.UniqueConstraint} + * + * @author Strong Liu + * @author Brett Meyer + */ +public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = { TableWithUniqueConstraint.class, SecondTable.class }) + public void testTableUniqueConstraints() { + EntityBinding binding = getEntityBinding( TableWithUniqueConstraint.class ); + testTableUniqueConstraints( binding.getPrimaryTable(), "u1", 2 ); + testTableUniqueConstraints( ( (MultipleHiLoPerTableGenerator) binding.getHierarchyDetails() + .getEntityIdentifier().getIdentifierGenerator() ).getTable(), "u2", 1 ); + testTableUniqueConstraints( SchemaUtil.getCollection( TableWithUniqueConstraint.class, "secondTables", meta ) + .getPluralAttributeKeyBinding().getCollectionTable(), "u3", 2 ); + testTableUniqueConstraints( SchemaUtil.getCollection( TableWithUniqueConstraint.class, "elements", meta ) + .getPluralAttributeKeyBinding().getCollectionTable(), "u4", 1 ); + } + + private void testTableUniqueConstraints(TableSpecification table, String ukName, int ukNumColumns) { + Iterable uniqueKeyIterable = table.getUniqueKeys(); + assertNotNull( uniqueKeyIterable ); + int i = 0; + for ( UniqueKey key : uniqueKeyIterable ) { + i++; + assertEquals( ukName, key.getName().getText() ); + assertTrue( table == key.getTable() ); + assertNotNull( key.getColumns() ); + assertEquals( "There should be " + ukNumColumns + " columns in the unique constraint", ukNumColumns, key.getColumns().size() ); + assertEquals( "There should be " + ukNumColumns + " columns in the unique constraint", ukNumColumns, key.getColumnSpan() ); + } + assertEquals( "There should only be one unique constraint", 1, i ); + } + + @Entity + @Table(uniqueConstraints = { @UniqueConstraint(name = "u1", columnNames = { "name", "age" }) }) + class TableWithUniqueConstraint { + @Id + @GeneratedValue(strategy = GenerationType.TABLE, generator = "fooGenerator") + @TableGenerator(name = "fooGenerator", table = "foo_generator_table", valueColumnName = "fooGeneratorValue", uniqueConstraints = @UniqueConstraint(columnNames = "fooGeneratorValue", name = "u2")) + int id; + + String name; + + int age; + + @ManyToMany + @JoinTable(name = "JoinTable", joinColumns = @JoinColumn(name = "secondTable"), inverseJoinColumns = @JoinColumn(name = "tableWithUniqueConstraint"), uniqueConstraints = @UniqueConstraint(columnNames = { + "secondTable", "tableWithUniqueConstraint" }, name = "u3")) + Set secondTables; + + @ElementCollection + @CollectionTable(name = "CollectionTable", joinColumns = @JoinColumn(name = "element"), uniqueConstraints = @UniqueConstraint(columnNames = "element", name = "u4")) + @OrderColumn(name = "element_index") + public List elements; + // TODO: int[] is not completely supported using the new metamodel yet, so I changed int[] to List + } + + @Entity + class SecondTable { + @Id + @GeneratedValue + int id; + + String name; + + int age; + + @ManyToMany(mappedBy = "secondTables") + Set tableWithUniqueConstraint; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java new file mode 100644 index 000000000000..53d07f915e6e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import java.util.Date; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Version; + +import org.hibernate.annotations.Source; +import org.hibernate.annotations.SourceType; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.type.DbTimestampType; +import org.hibernate.type.LongType; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Strong Liu + */ +public class VersionBindingTests extends BaseAnnotationBindingTestCase { + @Entity + class Item1 { + @Id + long id; + long version; + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item1.class) + public void testNoVersionAnnotation() { + assertFalse( getEntityBinding( Item1.class ).getHierarchyDetails().isVersioned() ); + } + + @Entity + class Item2 { + @Id + private long id; + @Version + private Long version; + + //we need add getters / setters due to HHH-6561 + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item2.class) + public void testVersionTypeAttribute() { + EntityBinding binding = getEntityBinding( Item2.class ); + assertTrue( binding.getHierarchyDetails().isVersioned() ); + HibernateTypeDescriptor descriptor = binding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding() + .getHibernateTypeDescriptor(); +// assertEquals( "Long", descriptor.getExplicitTypeName() ); + assertEquals( Long.class.getName(), + descriptor.getJavaTypeDescriptor().getName().toString() + ); + assertNotNull( descriptor.getResolvedTypeMapping() ); + assertEquals( LongType.class, descriptor.getResolvedTypeMapping().getClass() ); + assertNotNull( descriptor.getTypeParameters() ); + assertTrue( descriptor.getTypeParameters().isEmpty() ); + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item2.class) + public void testVersionUnsavedValue() { + EntityBinding binding = getEntityBinding( Item2.class ); + assertTrue( binding.getHierarchyDetails().isVersioned() ); + assertEquals( "undefined", binding.getHierarchyDetails().getEntityVersion().getUnsavedValue() ); + } + + @Entity + class Item3 { + @Id + Long id; + @Version + @Source(SourceType.DB) + Date version; + } + + @Test + @Resources(annotatedClasses = VersionBindingTests.Item3.class) + public void testVersionAttributeWithSource() { + EntityBinding binding = getEntityBinding( Item3.class ); + assertTrue( binding.getHierarchyDetails().isVersioned() ); + HibernateTypeDescriptor descriptor = binding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding() + .getHibernateTypeDescriptor(); + assertEquals( "dbtimestamp", descriptor.getExplicitTypeName() ); + assertEquals( + Date.class.getName(), + descriptor.getJavaTypeDescriptor().getName().toString() + ); + assertNotNull( descriptor.getResolvedTypeMapping() ); + assertEquals( DbTimestampType.class, descriptor.getResolvedTypeMapping().getClass() ); + assertNotNull( descriptor.getTypeParameters() ); + assertTrue( descriptor.getTypeParameters().isEmpty() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/WhereClauseTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/WhereClauseTest.java new file mode 100644 index 000000000000..9fbac5dc5de6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/WhereClauseTest.java @@ -0,0 +1,34 @@ +package org.hibernate.metamodel.internal.source.annotations.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Where; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +/** + * @author Hardy Ferentschik + */ +public class WhereClauseTest extends BaseAnnotationBindingTestCase { + @Test + @Resources(annotatedClasses = Foo.class) + public void testWhereFilter() { + EntityBinding binding = getEntityBinding( Foo.class ); + assertEquals( "Wrong where filter", "1=1", binding.getHierarchyDetails().getWhere() ); + } + + @Entity + @Where(clause = "1=1") + class Foo { + @Id + private long id; + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileBinderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileBinderTest.java new file mode 100644 index 000000000000..abaae147a5a4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/FetchProfileBinderTest.java @@ -0,0 +1,160 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.global; + +import java.util.Iterator; +import java.util.List; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +import org.hibernate.MappingException; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.FetchProfile; +import org.hibernate.annotations.FetchProfiles; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static junit.framework.Assert.fail; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Hardy Ferentschik + */ +public class FetchProfileBinderTest extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + @Test + public void testSingleFetchProfile() { + @FetchProfile(name = "foo", fetchOverrides = { + @FetchProfile.FetchOverride(entity = Foo.class, association = "bars", mode = FetchMode.JOIN) + }) + @Entity + class Foo { + @Id + @GeneratedValue + public long id; + + @ElementCollection + public List bars; + } + + Metadata meta = new MetadataSources( serviceRegistry ).addAnnotatedClass( Foo.class ).buildMetadata(); + + Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); + assertTrue( mappedFetchProfiles.hasNext() ); + org.hibernate.metamodel.spi.binding.FetchProfile profile = mappedFetchProfiles.next(); + assertEquals( "Wrong fetch profile name", "foo", profile.getName() ); + org.hibernate.metamodel.spi.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); + assertEquals( "Wrong association name", "bars", fetch.getAssociation() ); + assertEquals( "Wrong association type", Foo.class.getName(), fetch.getEntity() ); + } + + @Test + public void testFetchProfiles() { + Metadata meta = new MetadataSources( serviceRegistry ).addAnnotatedClass( FooBar.class ).buildMetadata(); + + Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); + assertTrue( mappedFetchProfiles.hasNext() ); + org.hibernate.metamodel.spi.binding.FetchProfile profile = mappedFetchProfiles.next(); + assertProfiles( profile ); + + assertTrue( mappedFetchProfiles.hasNext() ); + profile = mappedFetchProfiles.next(); + assertProfiles( profile ); + } + + private void assertProfiles(org.hibernate.metamodel.spi.binding.FetchProfile profile) { + if ( profile.getName().equals( "foobar" ) ) { + org.hibernate.metamodel.spi.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); + assertEquals( "Wrong association name", "fubars", fetch.getAssociation() ); + assertEquals( "Wrong association type", FooBar.class.getName(), fetch.getEntity() ); + } + else if ( profile.getName().equals( "fubar" ) ) { + org.hibernate.metamodel.spi.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); + assertEquals( "Wrong association name", "fubars", fetch.getAssociation() ); + assertEquals( "Wrong association type", FooBar.class.getName(), fetch.getEntity() ); + } + else { + fail( "Wrong fetch name:" + profile.getName() ); + } + } + + @Test(expected = MappingException.class) + public void testNonJoinFetchThrowsException() { + @FetchProfile(name = "foo", fetchOverrides = { + @FetchProfile.FetchOverride(entity = Foo.class, association = "bars", mode = FetchMode.SELECT) + }) + @Entity + class Foo { + @Id + @GeneratedValue + public long id; + + @ElementCollection + public List bars; + } + + new MetadataSources( serviceRegistry ).addAnnotatedClass( Foo.class ).buildMetadata(); + } + + @FetchProfiles( { + @FetchProfile(name = "foobar", fetchOverrides = { + @FetchProfile.FetchOverride(entity = FooBar.class, association = "fubars", mode = FetchMode.JOIN) + }), + @FetchProfile(name = "fubar", fetchOverrides = { + @FetchProfile.FetchOverride(entity = FooBar.class, association = "fubars", mode = FetchMode.JOIN) + }) + }) + @Entity + class FooBar { + @Id + @GeneratedValue + public long id; + + @ElementCollection + public List fubars; + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/QueryBinderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/QueryBinderTest.java similarity index 75% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/QueryBinderTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/QueryBinderTest.java index dc27113eb1e8..c09d0e16b7d7 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/QueryBinderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/global/QueryBinderTest.java @@ -21,27 +21,22 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.global; +package org.hibernate.metamodel.internal.source.annotations.global; import javax.persistence.NamedNativeQuery; -import org.jboss.jandex.Index; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn; import org.hibernate.engine.spi.NamedSQLQueryDefinition; +import org.hibernate.metamodel.Metadata; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContextImpl; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; + import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -51,16 +46,11 @@ * @author Hardy Ferentschik */ public class QueryBinderTest extends BaseUnitTestCase { - private StandardServiceRegistryImpl serviceRegistry; - private ClassLoaderService service; - private MetadataImpl meta; @Before public void setUp() { serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); - service = serviceRegistry.getService( ClassLoaderService.class ); - meta = (MetadataImpl) new MetadataSources( serviceRegistry ).buildMetadata(); } @After @@ -68,13 +58,12 @@ public void tearDown() { serviceRegistry.destroy(); } - @Test(expected = NotYetImplementedException.class) + @Test public void testNoResultClass() { @NamedNativeQuery(name = "fubar", query = "SELECT * FROM FOO") class Foo { } - Index index = JandexHelper.indexForClass( service, Foo.class ); - QueryBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); + new MetadataSources( serviceRegistry ).addAnnotatedClass( Foo.class ).buildMetadata(); } @Test @@ -82,9 +71,7 @@ public void testResultClass() { @NamedNativeQuery(name = "fubar", query = "SELECT * FROM FOO", resultClass = Foo.class) class Foo { } - Index index = JandexHelper.indexForClass( service, Foo.class ); - QueryBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); - + Metadata meta = new MetadataSources( serviceRegistry ).addAnnotatedClass( Foo.class ).buildMetadata(); NamedSQLQueryDefinition namedQuery = meta.getNamedNativeQuery( "fubar" ); assertNotNull( namedQuery ); NativeSQLQueryReturn queryReturns[] = namedQuery.getQueryReturns(); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/BaseAnnotationIndexTestCase.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/BaseAnnotationIndexTestCase.java new file mode 100644 index 000000000000..27a862544967 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/BaseAnnotationIndexTestCase.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import java.util.Set; + +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.internal.source.RootBindingContextBuilder; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContextImpl; +import org.hibernate.metamodel.source.internal.annotations.util.EntityHierarchyBuilder; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.source.spi.EntityHierarchySource; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; + +import org.jboss.jandex.IndexView; + +/** + * @author Hardy Ferentschik + */ +public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase { + private StandardServiceRegistry serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + } + + public Set createEntityHierarchies(Class... clazz) { + IndexView index = JandexHelper.indexForClass( + serviceRegistry.getService( ClassLoaderService.class ), + clazz + ); + AnnotationBindingContext context = new AnnotationBindingContextImpl( + RootBindingContextBuilder.buildBindingContext( serviceRegistry, index ) + ); + return EntityHierarchyBuilder.createEntityHierarchies( context ); + } + +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchySourceTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchySourceTest.java new file mode 100644 index 000000000000..288bddf21229 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/EntityHierarchySourceTest.java @@ -0,0 +1,269 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import java.util.Iterator; +import java.util.Set; +import javax.persistence.Embeddable; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.MappedSuperclass; + +import org.hibernate.metamodel.source.spi.EntityHierarchySource; +import org.hibernate.metamodel.source.spi.EntitySource; +import org.hibernate.metamodel.source.spi.IdentifiableTypeSource; +import org.hibernate.metamodel.source.spi.MappingException; +import org.hibernate.metamodel.spi.binding.InheritanceType; + +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +/** + * @author Hardy Ferentschik + */ +public class EntityHierarchySourceTest extends BaseAnnotationIndexTestCase { + + @Test + public void testSingleEntity() { + @Entity + class Foo { + @Id + @GeneratedValue + private int id; + } + + Set hierarchies = createEntityHierarchies( Foo.class ); + assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); + + EntityHierarchySource hierarchy = hierarchies.iterator().next(); + assertEquals( + "wrong entity name", + Foo.class.getName(), + hierarchy.getRoot().getEntityName() + ); + } + + @Test + public void testSimpleInheritance() { + @Entity + class A { + @Id + @GeneratedValue + private int id; + } + + @Entity + class B extends A { + private String name; + } + Set hierarchies = createEntityHierarchies( B.class, A.class ); + assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); + + EntityHierarchySource hierarchy = hierarchies.iterator().next(); + EntitySource rootSource = hierarchy.getRoot(); + assertEquals( + "wrong entity name", + A.class.getName(), + rootSource.getEntityName() + ); + + Iterator itr = rootSource.getSubTypes().iterator(); + assertTrue( "There should be a subclass entity source", itr.hasNext() ); + assertEquals( "wrong class", B.class.getName(), itr.next().getTypeName() ); + assertFalse( "There should be no more subclass entity sources", itr.hasNext() ); + } + + @Test + public void testMultipleHierarchies() { + @Entity + class Foo { + @Id + @GeneratedValue + private int id; + } + + @Entity + class A { + @Id + @GeneratedValue + private int id; + } + + @Entity + class B extends A { + private String name; + } + Set hierarchies = createEntityHierarchies( B.class, Foo.class, A.class ); + assertEquals( "There should be only one hierarchy", 2, hierarchies.size() ); + } + + @Test + public void testMappedSuperClass() { + @MappedSuperclass + class MappedSuperClass { + @Id + @GeneratedValue + private int id; + } + + class UnmappedSubClass extends MappedSuperClass { + private String unmappedProperty; + } + + @Entity + class MappedSubClass extends UnmappedSubClass { + private String mappedProperty; + } + + Set hierarchies = createEntityHierarchies( + MappedSubClass.class, + MappedSuperClass.class, + UnmappedSubClass.class + ); + assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); + + EntityHierarchySource hierarchy = hierarchies.iterator().next(); + assertEquals( + "wrong entity name", + MappedSubClass.class.getName(), + hierarchy.getRoot().getEntityName() + ); + } + +// @Test(expected = AnnotationException.class) + @Test + public void testEntityAndMappedSuperClassAnnotations() { + @Entity + @MappedSuperclass + class EntityAndMappedSuperClass { + } + + createEntityHierarchies( EntityAndMappedSuperClass.class ); + } + + @Test(expected = MappingException.class) + public void testEntityAndEmbeddableAnnotations() { + @Entity + @Embeddable + class EntityAndEmbeddable { + } + + createEntityHierarchies( EntityAndEmbeddable.class ); + } + + @Test(expected = MappingException.class) + public void testNoIdAnnotation() { + @Entity + class A { + String id; + } + + @Entity + class B extends A { + } + + createEntityHierarchies( B.class, A.class ); + } + + @Test + public void testDefaultInheritanceStrategy() { + @Entity + class A { + @Id + String id; + } + + @Entity + class B extends A { + } + + Set hierarchies = createEntityHierarchies( B.class, A.class ); + assertEquals( "There should be exactly one hierarchy", 1, hierarchies.size() ); + + EntityHierarchySource hierarchy = hierarchies.iterator().next(); + assertEquals( + "wrong entity name", + A.class.getName(), + hierarchy.getRoot().getEntityName() + ); + assertEquals( "Wrong inheritance type", InheritanceType.SINGLE_TABLE, hierarchy.getHierarchyInheritanceType() ); + } + + @Test + public void testExplicitInheritanceStrategy() { + @MappedSuperclass + class MappedSuperClass { + + } + + @Entity + @Inheritance(strategy = javax.persistence.InheritanceType.JOINED) + class A extends MappedSuperClass { + @Id + String id; + } + + @Entity + class B extends A { + } + + Set hierarchies = createEntityHierarchies( + B.class, + MappedSuperClass.class, + A.class + ); + + EntityHierarchySource hierarchy = hierarchies.iterator().next(); + assertEquals( + "wrong entity name", + A.class.getName(), + hierarchy.getRoot().getEntityName() + ); + assertEquals( "Wrong inheritance type", InheritanceType.JOINED, hierarchy.getHierarchyInheritanceType() ); + } + + @Test(expected = MappingException.class) + public void testMultipleConflictingInheritanceDefinitions() { + + @Entity + @Inheritance(strategy = javax.persistence.InheritanceType.JOINED) + class A { + String id; + } + + @Entity + @Inheritance(strategy = javax.persistence.InheritanceType.TABLE_PER_CLASS) + class B extends A { + } + + createEntityHierarchies( B.class, A.class ); + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/GenericTypeDiscoveryTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/GenericTypeDiscoveryTest.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/GenericTypeDiscoveryTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/GenericTypeDiscoveryTest.java index 4d29116a9196..4d9101dfe232 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/GenericTypeDiscoveryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/GenericTypeDiscoveryTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -47,10 +47,10 @@ public void testGenericClassHierarchy() { // assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); // // Iterator iter = hierarchies.iterator().next().iterator(); -// ConfiguredClass configuredClass = iter.next(); +// ManagedTypeMetadata configuredClass = iter.next(); // ClassInfo info = configuredClass.getClassInfo(); // assertEquals( "wrong class", DotName.createSimple( Stuff.class.getName() ), info.name() ); -// MappedAttribute property = configuredClass.getMappedAttribute( "value" ); +// PersistentAttribute property = configuredClass.getMappedAttribute( "value" ); // assertEquals( Price.class, property.getJavaType() ); // // assertTrue( iter.hasNext() ); @@ -250,4 +250,4 @@ public void setState(T state) { this.state = state; } } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelperTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelperTest.java new file mode 100644 index 000000000000..aa06c9477cf6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/JandexHelperTest.java @@ -0,0 +1,238 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.util; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.persistence.AttributeOverride; +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.LockModeType; +import javax.persistence.NamedQuery; + +import org.hibernate.AssertionFailure; +import org.hibernate.annotations.NamedNativeQuery; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; + +import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +/** + * Tests for the helper class {@link org.hibernate.metamodel.source.internal.annotations.util.JandexHelper}. + * + * @author Hardy Ferentschik + */ +public class JandexHelperTest extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + private ClassLoaderService classLoaderService; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + @Test + public void testGetMemberAnnotations() { + class Foo { + @Column + @Basic + private String bar; + private String fubar; + } + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + + ClassInfo classInfo = index.getClassByName( DotName.createSimple( Foo.class.getName() ) ); + Map> memberAnnotations = JandexHelper.getMemberAnnotations( + classInfo, "bar", serviceRegistry + ); + assertTrue( + "property bar should defines @Column annotation", + memberAnnotations.containsKey( DotName.createSimple( Column.class.getName() ) ) + ); + assertTrue( + "property bar should defines @Basic annotation", + memberAnnotations.containsKey( DotName.createSimple( Basic.class.getName() ) ) + ); + + memberAnnotations = JandexHelper.getMemberAnnotations( classInfo, "fubar", serviceRegistry ); + assertTrue( "there should be no annotations in fubar", memberAnnotations.isEmpty() ); + } + + @Test + public void testGettingNestedAnnotation() { + @AttributeOverride(name = "foo", column = @Column(name = "FOO")) + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + // try to retrieve the name + String name = JandexHelper.getValue( annotationInstance, "name", String.class, classLoaderService ); + assertEquals( "Wrong nested annotation", "foo", name ); + + // try to retrieve the nested column annotation instance + AnnotationInstance columnAnnotationInstance = JandexHelper.getValue( + annotationInstance, + "column", + AnnotationInstance.class, + classLoaderService + ); + assertNotNull( columnAnnotationInstance ); + assertEquals( + "Wrong nested annotation", + "javax.persistence.Column", + columnAnnotationInstance.name().toString() + ); + } + + @Test(expected = AssertionFailure.class) + public void testTryingToRetrieveWrongType() { + @AttributeOverride(name = "foo", column = @Column(name = "FOO")) + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + JandexHelper.getValue( annotationInstance, "name", Float.class, + classLoaderService); + } + + @Test + public void testRetrieveDefaultEnumElement() { + @NamedQuery(name = "foo", query = "fubar") + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class, + classLoaderService ); + assertEquals( "Wrong lock mode", LockModeType.NONE, lockMode ); + } + + @Test + public void testRetrieveExplicitEnumElement() { + @NamedQuery(name = "foo", query = "bar", lockMode = LockModeType.OPTIMISTIC) + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class, + classLoaderService ); + assertEquals( "Wrong lock mode", LockModeType.OPTIMISTIC, lockMode ); + } + + @Test(expected = AssertionFailure.class) + public void testRetrieveClassParameterAsClass() { + @NamedNativeQuery(name = "foo", query = "bar", resultClass = Foo.class) + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + JandexHelper.getValue( annotationInstance, "resultClass", Class.class, classLoaderService ); + } + + @Test + public void testRetrieveClassParameterAsString() { + @NamedNativeQuery(name = "foo", query = "bar", resultClass = Foo.class) + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + String fqcn = JandexHelper.getValue( annotationInstance, "resultClass", String.class, classLoaderService ); + assertEquals( "Wrong class names", Foo.class.getName(), fqcn ); + } + + @Test + public void testRetrieveUnknownParameter() { + @Entity + class Foo { + } + + IndexView index = JandexHelper.indexForClass( classLoaderService, Foo.class ); + Collection annotationInstances = index.getAnnotations( JPADotNames.ENTITY ); + assertTrue( annotationInstances.size() == 1 ); + AnnotationInstance annotationInstance = annotationInstances.iterator().next(); + + try { + JandexHelper.getValue( annotationInstance, "foo", String.class, classLoaderService ); + fail(); + } + catch ( AssertionFailure e ) { + assertTrue( + e.getMessage() + .startsWith( "The annotation javax.persistence.Entity does not define a parameter 'foo'" ) + ); + } + } + +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/TypeDiscoveryTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/TypeDiscoveryTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/TypeDiscoveryTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/TypeDiscoveryTest.java index 2d2753440d50..933079e71199 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/TypeDiscoveryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/util/TypeDiscoveryTest.java @@ -21,15 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.util; +package org.hibernate.metamodel.internal.source.annotations.util; import javax.persistence.Id; -import org.junit.Test; - import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Type; +import org.junit.Test; + /** * @author Hardy Ferentschik */ @@ -41,9 +41,9 @@ public void testImplicitAndExplicitType() { // assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); // // Iterator iter = hierarchies.iterator().next().iterator(); -// ConfiguredClass configuredClass = iter.next(); +// ManagedTypeMetadata configuredClass = iter.next(); // -// MappedAttribute property = configuredClass.getMappedAttribute( "id" ); +// PersistentAttribute property = configuredClass.getMappedAttribute( "id" ); // assertEquals( "Unexpected property type", int.class, property.getJavaType() ); // // property = configuredClass.getMappedAttribute( "string" ); @@ -64,4 +64,4 @@ class Entity { @Type(type = "my.custom.Type", parameters = { @Parameter(name = "foo", value = "bar") }) private String customString; } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Father.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Father.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Father.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Father.java index 76f829b9d77b..e4b950ac057c 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Father.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Father.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.internal.source.annotations.xml; /** * @author Hardy Ferentschik diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/OrmXmlParserTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/OrmXmlParserTests.java similarity index 78% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/OrmXmlParserTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/OrmXmlParserTests.java index e31cea2ea4a0..ceb64d198200 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/OrmXmlParserTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/OrmXmlParserTests.java @@ -21,18 +21,19 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; - -import static junit.framework.Assert.assertNotNull; +package org.hibernate.metamodel.internal.source.annotations.xml; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MappingException; -import org.hibernate.metamodel.source.internal.MetadataImpl; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.source.spi.InvalidMappingException; +import org.hibernate.metamodel.spi.binding.EntityBinding; + import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; +import static junit.framework.Assert.assertNotNull; + /** * @author Hardy Ferentschik */ @@ -40,7 +41,7 @@ public class OrmXmlParserTests extends BaseUnitTestCase { @Test public void testSimpleOrmVersion2() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addResource( "org/hibernate/metamodel/source/annotations/xml/orm-father.xml" ); + sources.addResource( "org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml" ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); EntityBinding binding = metadata.getEntityBinding( Father.class.getName() ); @@ -50,17 +51,16 @@ public void testSimpleOrmVersion2() { @Test public void testSimpleOrmVersion1() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addResource( "org/hibernate/metamodel/source/annotations/xml/orm-star.xml" ); + sources.addResource( "org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml" ); MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); - EntityBinding binding = metadata.getEntityBinding( Star.class.getName() ); assertNotNull( binding ); } - @Test(expected = MappingException.class) + @Test(expected = InvalidMappingException.class) public void testInvalidOrmXmlThrowsException() { MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - sources.addResource( "org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml" ); + sources.addResource( "org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml" ); sources.buildMetadata(); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Star.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Star.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Star.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Star.java index 5131a0a31929..b6af84a86440 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/Star.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/Star.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml; +package org.hibernate.metamodel.internal.source.annotations.xml; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMockerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java index 4b9f23a99928..c9571b4e15cb 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/AbstractMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java @@ -21,13 +21,25 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.JAXBException; + +import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.source.internal.jandex.EntityMappingsMocker; +import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.xml.internal.jaxb.MappingXmlBinder; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +import org.hibernate.testing.ServiceRegistryBuilder; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; @@ -36,13 +48,6 @@ import org.jboss.jandex.Index; import org.jboss.jandex.Indexer; -import org.hibernate.AnnotationException; -import org.hibernate.HibernateException; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntityMappings; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.testing.ServiceRegistryBuilder; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -52,7 +57,7 @@ public abstract class AbstractMockerTest { private static final String ORM1_MAPPING_XSD = "org/hibernate/jpa/orm_1_0.xsd"; private static final String ORM2_MAPPING_XSD = "org/hibernate/jpa/orm_2_0.xsd"; - + private static final String ORM2_1_MAPPING_XSD = "org/hibernate/jpa/orm_2_1.xsd"; private IndexBuilder indexBuilder; private Index index; private ServiceRegistry serviceRegistry; @@ -67,26 +72,15 @@ protected IndexBuilder getIndexBuilder() { } protected EntityMappingsMocker getEntityMappingsMocker(String... mappingFiles) { + MappingXmlBinder processor = new MappingXmlBinder( getServiceRegistry() ); ClassLoaderService classLoaderService = getServiceRegistry().getService( ClassLoaderService.class ); List xmlEntityMappingsList = new ArrayList(); for ( String fileName : mappingFiles ) { - JaxbEntityMappings entityMappings; - try { - entityMappings = XmlHelper.unmarshallXml( - packagePrefix + fileName, ORM2_MAPPING_XSD, JaxbEntityMappings.class, classLoaderService - ).getRoot(); - } - catch ( JAXBException orm2Exception ) { - // if we cannot parse against orm_2_0.xsd we try orm_1_0.xsd for backwards compatibility - try { - entityMappings = XmlHelper.unmarshallXml( - packagePrefix + fileName, ORM1_MAPPING_XSD, JaxbEntityMappings.class, classLoaderService - ).getRoot(); - } - catch ( JAXBException orm1Exception ) { - throw new AnnotationException( "Unable to parse xml configuration.", orm1Exception ); - } - } + BindResult bindResult = processor.bind( + classLoaderService.locateResourceStream( packagePrefix + fileName ), + new Origin( SourceType.FILE, packagePrefix + fileName ) + ); + JaxbEntityMappings entityMappings = (JaxbEntityMappings) bindResult.getRoot(); xmlEntityMappingsList.add( entityMappings ); } return new EntityMappingsMocker( xmlEntityMappingsList, getIndex(), getServiceRegistry() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Author.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Author.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Author.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Author.java index 0a2868d18dc8..169e6e2bdc83 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Author.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Author.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.List; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMockerTest.java similarity index 85% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMockerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMockerTest.java index f53b4f231473..ef48aac9ed94 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/BasicMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/BasicMockerTest.java @@ -21,19 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jandex.EntityMappingsMocker; +import org.hibernate.metamodel.source.internal.jandex.EntityMocker; +import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbGeneratedValue; +import org.hibernate.metamodel.source.internal.jaxb.JaxbId; + +import org.junit.Test; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; -import org.junit.Test; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbAttributes; -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.internal.jaxb.mapping.orm.JaxbGeneratedValue; -import org.hibernate.internal.jaxb.mapping.orm.JaxbId; -import org.hibernate.metamodel.source.annotations.JPADotNames; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Book.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Book.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Book.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Book.java index ccfebfa64efa..2cdfb3986547 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Book.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Book.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.ArrayList; import java.util.Date; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java index 2a5e913c73f7..6b1010e8056f 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/DefaultConfigurationHelperTest.java @@ -1,4 +1,4 @@ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.HashMap; import java.util.HashSet; @@ -13,13 +13,16 @@ import javax.persistence.SecondaryTable; import javax.persistence.SecondaryTables; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jandex.DefaultConfigurationHelper; +import org.hibernate.metamodel.source.internal.jandex.EntityMappingsMocker; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; + +import org.junit.Test; + import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; -import org.junit.Test; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.metamodel.source.annotations.JPADotNames; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -54,8 +57,7 @@ public void applyDefaultToEntity() { assertNull( entity.getTable().getCatalog() ); assertTrue( entity.isMetadataComplete() ); assertEquals( "org.test.Entity", entity.getClazz() ); - DefaultConfigurationHelper.INSTANCE - .applyDefaults( new SchemaAware.TableSchemaAware( entity.getTable() ), defaults ); + DefaultConfigurationHelper.INSTANCE.applyDefaults( entity.getTable(), defaults ); assertEquals( "schema", entity.getTable().getSchema() ); assertNull( entity.getTable().getCatalog() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityListenerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityListenerTest.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityListenerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityListenerTest.java index 392e5430fffe..ffd8bdf03f83 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/EntityListenerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/EntityListenerTest.java @@ -21,15 +21,16 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jandex.PseudoJpaDotNames; + +import org.junit.Test; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; -import org.junit.Test; - -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; import static org.junit.Assert.assertEquals; @@ -56,7 +57,5 @@ public void basicEntityListenerMockTest() { assertHasAnnotation( index, PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS ); assertHasAnnotation( index, PseudoJpaDotNames.DEFAULT_PRE_PERSIST ); assertHasAnnotation( index, PseudoJpaDotNames.DEFAULT_POST_PERSIST ); - - } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilderTest.java new file mode 100644 index 000000000000..6b79b41bf59b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/IndexBuilderTest.java @@ -0,0 +1,15 @@ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; + +import org.junit.Test; + +/** + * @author Strong Liu + */ +public class IndexBuilderTest extends AbstractMockerTest { + @Test + public void test() { + IndexBuilder builder = getIndexBuilder(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Item.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Item.java new file mode 100644 index 000000000000..70c811018cf6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Item.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc.. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; + +/** + * @author Strong Liu + */ +public class Item { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/ItemListener.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ItemListener.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/ItemListener.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ItemListener.java index dc1852b0b63b..ad56f70aa174 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/ItemListener.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/ItemListener.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; /** * @author Strong Liu diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/OverrideTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OverrideTest.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/OverrideTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OverrideTest.java index 2f796486de0b..b1d63cf288c0 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/OverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/OverrideTest.java @@ -21,19 +21,23 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.util.List; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.jandex.EntityMappingsMocker; +import org.hibernate.metamodel.source.internal.jandex.EntityMocker; +import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; + +import org.junit.Test; + import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; -import org.junit.Test; - -import org.hibernate.internal.jaxb.mapping.orm.JaxbEntity; -import org.hibernate.metamodel.source.annotations.JPADotNames; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java index 0086b8975eb4..23ac195e4aad 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/PersistenceMetadataMockerTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import javax.persistence.AccessType; @@ -29,7 +29,7 @@ import org.jboss.jandex.Index; import org.junit.Test; -import org.hibernate.metamodel.source.annotations.xml.PseudoJpaDotNames; +import org.hibernate.metamodel.source.internal.jandex.PseudoJpaDotNames; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Topic.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Topic.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Topic.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Topic.java index cf74904525d2..fbf335b67e52 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Topic.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/Topic.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import javax.persistence.Embeddable; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/XmlHelper.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/XmlHelper.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java index e7cc270ade7e..063aa9f70cda 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/XmlHelper.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.xml.mocker; +package org.hibernate.metamodel.internal.source.annotations.xml.mocker; import java.io.InputStream; import java.net.URL; @@ -36,10 +36,10 @@ import org.jboss.logging.Logger; import org.xml.sax.SAXException; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.jaxb.JaxbRoot; -import org.hibernate.internal.jaxb.Origin; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; /** * @author Hardy Ferentschik @@ -50,7 +50,7 @@ public class XmlHelper { private XmlHelper() { } - public static JaxbRoot unmarshallXml(String fileName, String schemaName, Class clazz, ClassLoaderService classLoaderService) + public static BindResult unmarshallXml(String fileName, String schemaName, Class clazz, ClassLoaderService classLoaderService) throws JAXBException { Schema schema = getMappingSchema( schemaName, classLoaderService ); InputStream in = classLoaderService.locateResourceStream( fileName ); @@ -60,7 +60,7 @@ public static JaxbRoot unmarshallXml(String fileName, String schemaName, StreamSource stream = new StreamSource( in ); JAXBElement elem = unmarshaller.unmarshal( stream, clazz ); Origin origin = new Origin( null, fileName ); - return new JaxbRoot( elem.getValue(), origin ); + return new BindResult( elem.getValue(), origin ); } private static Schema getMappingSchema(String schemaVersion, ClassLoaderService classLoaderService) { diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/package-info.java new file mode 100644 index 000000000000..510a09e45d6b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/package-info.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +@FetchProfile(name = "package-configured-profile", fetchOverrides = { + @FetchProfile.FetchOverride(entity = Foo.class, association = "bars", mode = FetchMode.JOIN) +}) +package org.hibernate.metamodel.internal.source; + +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.FetchProfile; + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java deleted file mode 100644 index d974b8d942d8..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import org.junit.Test; - -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.H2Dialect; -import org.hibernate.testing.env.TestingDatabaseInfo; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Steve Ebersole - */ -public class ObjectNameTests extends BaseUnitTestCase { - @Test - public void testMissingName() { - try { - new ObjectName( (String)null, null, null ); - fail(); - } - catch ( IllegalIdentifierException ignore ) { - } - - try { - new ObjectName( "schema", "catalog", null ); - fail(); - } - catch ( IllegalIdentifierException ignore ) { - } - } - - @Test - public void testIdentifierBuilding() { - Dialect dialect = TestingDatabaseInfo.DIALECT; - ObjectName on = new ObjectName( "schema", "catalog", "name" ); - assertEquals( "schema.catalog.name", on.toText() ); - on = new ObjectName( "schema", null, "name" ); - assertEquals( "schema.name", on.toText() ); - assertEquals( "schema.name", on.toText( dialect ) ); - on = new ObjectName( "`schema`", "`catalog`", "`name`" ); - assertEquals( "`schema`.`catalog`.`name`", on.toText() ); - assertEquals( "\"schema\".\"catalog\".\"name\"", on.toText( dialect ) ); - on = new ObjectName( "`schema`", null, "`name`" ); - assertEquals( "`schema`.`name`", on.toText() ); - assertEquals( "\"schema\".\"name\"", on.toText( dialect ) ); - } -} - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java deleted file mode 100644 index 69fdc683b4b1..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.relational; - -import java.sql.Types; - -import org.junit.Test; - -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.H2Dialect; -import org.hibernate.testing.env.TestingDatabaseInfo; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Steve Ebersole - */ -public class TableManipulationTests extends BaseUnitTestCase { - public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); - public static final Datatype INTEGER = new Datatype( Types.INTEGER, "INTEGER", Long.class ); - - @Test - public void testTableCreation() { - Schema schema = new Schema( null, null ); - Table table = schema.createTable( Identifier.toIdentifier( "my_table" ) ); - assertNull( table.getSchema().getName().getSchema() ); - assertNull( table.getSchema().getName().getCatalog() ); - assertEquals( "my_table", table.getTableName().toString() ); - assertEquals( "my_table", table.getExportIdentifier() ); - assertNull( table.getPrimaryKey().getName() ); - assertFalse( table.values().iterator().hasNext() ); - - Column idColumn = table.locateOrCreateColumn( "id" ); - idColumn.setDatatype( INTEGER ); - idColumn.setSize( Size.precision( 18, 0 ) ); - table.getPrimaryKey().addColumn( idColumn ); - table.getPrimaryKey().setName( "my_table_pk" ); - assertEquals( "my_table_pk", table.getPrimaryKey().getName() ); - assertEquals( "my_table.PK", table.getPrimaryKey().getExportIdentifier() ); - - Column col_1 = table.locateOrCreateColumn( "col_1" ); - col_1.setDatatype( VARCHAR ); - col_1.setSize( Size.length( 512 ) ); - - for ( Value value : table.values() ) { - assertTrue( Column.class.isInstance( value ) ); - Column column = ( Column ) value; - if ( column.getColumnName().getName().equals( "id" ) ) { - assertEquals( INTEGER, column.getDatatype() ); - assertEquals( 18, column.getSize().getPrecision() ); - assertEquals( 0, column.getSize().getScale() ); - assertEquals( -1, column.getSize().getLength() ); - assertNull( column.getSize().getLobMultiplier() ); - } - else { - assertEquals( "col_1", column.getColumnName().getName() ); - assertEquals( VARCHAR, column.getDatatype() ); - assertEquals( -1, column.getSize().getPrecision() ); - assertEquals( -1, column.getSize().getScale() ); - assertEquals( 512, column.getSize().getLength() ); - assertNull( column.getSize().getLobMultiplier() ); - } - } - } - - @Test - public void testTableSpecificationCounter() { - Schema schema = new Schema( null, null ); - Table table = schema.createTable( Identifier.toIdentifier( "my_table" ) ); - InLineView inLineView = schema.createInLineView( "my_inlineview", "subselect" ); - InLineView otherInLineView = schema.createInLineView( "my_other_inlineview", "other subselect" ); - Table otherTable = schema.createTable( Identifier.toIdentifier( "my_other_table" ) ); - - int firstTableNumber = table.getTableNumber(); - assertEquals( firstTableNumber, table.getTableNumber() ); - assertEquals( firstTableNumber + 1, inLineView.getTableNumber() ); - assertEquals( firstTableNumber + 2, otherInLineView.getTableNumber() ); - assertEquals( firstTableNumber + 3, otherTable.getTableNumber() ); - } - - @Test - public void testBasicForeignKeyDefinition() { - Schema schema = new Schema( null, null ); - Table book = schema.createTable( Identifier.toIdentifier( "BOOK" ) ); - - Column bookId = book.locateOrCreateColumn( "id" ); - bookId.setDatatype( INTEGER ); - bookId.setSize( Size.precision( 18, 0 ) ); - book.getPrimaryKey().addColumn( bookId ); - book.getPrimaryKey().setName( "BOOK_PK" ); - - Table page = schema.createTable( Identifier.toIdentifier( "PAGE" ) ); - - Column pageId = page.locateOrCreateColumn( "id" ); - pageId.setDatatype( INTEGER ); - pageId.setSize( Size.precision( 18, 0 ) ); - page.getPrimaryKey().addColumn( pageId ); - page.getPrimaryKey().setName( "PAGE_PK" ); - - Column pageBookId = page.locateOrCreateColumn( "BOOK_ID" ); - pageId.setDatatype( INTEGER ); - pageId.setSize( Size.precision( 18, 0 ) ); - ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK" ); - pageBookFk.addColumn( pageBookId ); - - assertEquals( page, pageBookFk.getSourceTable() ); - assertEquals( book, pageBookFk.getTargetTable() ); - } - - @Test - public void testQualifiedName() { - Dialect dialect = TestingDatabaseInfo.DIALECT; - Schema schema = new Schema( Identifier.toIdentifier( "schema" ), Identifier.toIdentifier( "`catalog`" ) ); - Table table = schema.createTable( Identifier.toIdentifier( "my_table" ) ); - assertEquals( "my_table", table.getTableName().getName() ); - assertEquals( "my_table", table.getTableName().toString() ); - assertEquals( "schema.\"catalog\".my_table", table.getQualifiedName( dialect ) ); - - table = schema.createTable( Identifier.toIdentifier( "`my_table`" ) ); - assertEquals( "my_table", table.getTableName().getName() ); - assertEquals( "`my_table`", table.getTableName().toString() ); - assertEquals( "schema.\"catalog\".\"my_table\"", table.getQualifiedName( dialect ) ); - - InLineView inLineView = schema.createInLineView( "my_inlineview", "select ..." ); - assertEquals( "( select ... )", inLineView.getQualifiedName( dialect ) ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/AccessBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/AccessBindingTest.java deleted file mode 100644 index bfbe32b9f3d5..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/AccessBindingTest.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Entity; -import javax.persistence.Id; - -import org.junit.Test; - -import org.hibernate.AnnotationException; -import org.hibernate.metamodel.binding.EntityBinding; - -import static junit.framework.Assert.assertEquals; - -/** - * Tests for different types of attribute access - * - * @author Hardy Ferentschik - */ - -public class AccessBindingTest extends BaseAnnotationBindingTestCase { - @Entity - class FieldAccess { - @Id - private int id; - } - - @Test - @Resources(annotatedClasses = { FieldAccess.class }) - public void testDefaultFieldAccess() { - EntityBinding binding = getEntityBinding( FieldAccess.class ); - assertEquals( "Wrong access type", "field", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); - } - - @Entity - class PropertyAccess { - private int id; - - @Id - public int getId() { - return id; - } - } - - @Test - @Resources(annotatedClasses = { PropertyAccess.class }) - public void testDefaultPropertyAccess() { - EntityBinding binding = getEntityBinding( PropertyAccess.class ); - assertEquals( "Wrong access type", "property", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); - } - - - @Entity - class NoAccess { - private int id; - - public int getId() { - return id; - } - } - - @Test(expected = AnnotationException.class) - @Resources(annotatedClasses = { NoAccess.class }) - public void testNoAccess() { - // actual error happens when the binding gets created - } - - @Entity - class MixedAccess { - @Id - private int id; - - private String name; - - @Access(AccessType.PROPERTY) - public String getName() { - return name; - } - } - - @Test - @Resources(annotatedClasses = { MixedAccess.class }) - public void testMixedAccess() { - EntityBinding binding = getEntityBinding( MixedAccess.class ); - assertEquals( "Wrong access type", "field", binding.locateAttributeBinding( "id" ).getPropertyAccessorName() ); - assertEquals( - "Wrong access type", - "property", - binding.locateAttributeBinding( "name" ).getPropertyAccessorName() - ); - } - - @Entity - class Base { - @Id - int id; - } - - @Entity - @Access(AccessType.PROPERTY) - class ClassConfiguredAccess extends Base { - private String name; - - public String getName() { - return name; - } - } - - @Test - @Resources(annotatedClasses = { ClassConfiguredAccess.class, Base.class }) - public void testExplicitClassConfiguredAccess() { - EntityBinding binding = getEntityBinding( Base.class ); - assertEquals( - "Wrong access type", - "field", - binding.locateAttributeBinding( "id" ).getPropertyAccessorName() - ); - - - binding = getEntityBinding( ClassConfiguredAccess.class ); - assertEquals( - "Wrong access type", - "property", - binding.locateAttributeBinding( "name" ).getPropertyAccessorName() - ); - } - -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BaseAnnotationBindingTestCase.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BaseAnnotationBindingTestCase.java deleted file mode 100644 index 52a040af396c..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BaseAnnotationBindingTestCase.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2012, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.MetadataBuilder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.Statement; - -/** - * @author Hardy Ferentschik - */ -public abstract class BaseAnnotationBindingTestCase extends BaseUnitTestCase { - protected MetadataSources sources; - protected MetadataImpl meta; - - @Rule - public MethodRule buildMetaData = new MethodRule() { - @Override - public Statement apply(final Statement statement, FrameworkMethod frameworkMethod, Object o) { - return new KeepSetupFailureStatement( statement, frameworkMethod ); - } - }; - - @After - public void tearDown() { - sources = null; - meta = null; - } - - public EntityBinding getEntityBinding(Class clazz) { - return meta.getEntityBinding( clazz.getName() ); - } - - public EntityBinding getRootEntityBinding(Class clazz) { - return meta.getRootEntityBinding( clazz.getName() ); - } - - class KeepSetupFailureStatement extends Statement { - private final Statement origStatement; - private final FrameworkMethod origFrameworkMethod; - private Throwable setupError; - private boolean expectedException; - - KeepSetupFailureStatement(Statement statement, FrameworkMethod frameworkMethod) { - this.origStatement = statement; - this.origFrameworkMethod = frameworkMethod; - } - - @Override - public void evaluate() throws Throwable { - try { - createBindings(); - origStatement.evaluate(); - if ( setupError != null ) { - throw setupError; - } - } - catch ( Throwable t ) { - if ( setupError == null ) { - throw t; - } - else { - if ( !expectedException ) { - throw setupError; - } - } - } - } - - private void createBindings() { - try { - sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - MetadataBuilder metadataBuilder = sources.getMetadataBuilder(); - Resources resourcesAnnotation = origFrameworkMethod.getAnnotation( Resources.class ); - if ( resourcesAnnotation != null ) { - metadataBuilder.with( resourcesAnnotation.cacheMode() ); - - for ( Class annotatedClass : resourcesAnnotation.annotatedClasses() ) { - sources.addAnnotatedClass( annotatedClass ); - } - if ( !resourcesAnnotation.ormXmlPath().isEmpty() ) { - sources.addResource( resourcesAnnotation.ormXmlPath() ); - } - } - - meta = ( MetadataImpl ) metadataBuilder.build(); - } - catch ( final Throwable t ) { - setupError = t; - Test testAnnotation = origFrameworkMethod.getAnnotation( Test.class ); - Class expected = testAnnotation.expected(); - if ( t.getClass().equals( expected ) ) { - expectedException = true; - } - } - } - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java deleted file mode 100644 index 6a0099d3c071..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddableBindingTest.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.AttributeOverride; -import javax.persistence.AttributeOverrides; -import javax.persistence.Column; -import javax.persistence.Embeddable; -import javax.persistence.Embedded; -import javax.persistence.Entity; -import javax.persistence.Id; - -import org.junit.Test; - -import org.hibernate.annotations.Parent; -import org.hibernate.annotations.Target; -import org.hibernate.metamodel.binding.BasicAttributeBinding; -import org.hibernate.metamodel.binding.ComponentAttributeBinding; -import org.hibernate.metamodel.binding.EntityBinding; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; - -/** - * Tests for {@code javax.persistence.Embeddable}. - * - * @author Hardy Ferentschik - */ -public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { - @Entity - class User { - @Id - private int id; - - @Embedded - private Phone phone; - } - - @Embeddable - class Phone { - String countryCode; - String areaCode; - String number; - } - - @Test - @Resources(annotatedClasses = { User.class, Phone.class }) - public void testEmbeddable() { - EntityBinding binding = getEntityBinding( User.class ); - - final String componentName = "phone"; - assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - componentName - ); - - // todo - is this really correct? Does the path start w/ the class name - assertEquals( - "Wrong path", - "org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.phone", - componentBinding.getPathBase() - ); - - assertNotNull( componentBinding.locateAttributeBinding( "countryCode" ) ); - assertNotNull( componentBinding.locateAttributeBinding( "areaCode" ) ); - assertNotNull( componentBinding.locateAttributeBinding( "number" ) ); - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - @Entity - @AttributeOverride(name = "embedded.name", column = @Column(name = "FUBAR", length = 42)) - class BaseEntity { - @Id - private int id; - - @Embedded - private EmbeddedEntity embedded; - } - - @Embeddable - class EmbeddedEntity { - String name; - } - - @Test - @Resources(annotatedClasses = { BaseEntity.class, EmbeddedEntity.class }) - public void testEmbeddableWithAttributeOverride() { - EntityBinding binding = getEntityBinding( BaseEntity.class ); - - final String componentName = "embedded"; - assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - componentName - ); - - assertNotNull( componentBinding.locateAttributeBinding( "name" ) ); - BasicAttributeBinding nameAttribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "name" ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); - assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getName() ); - assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() ); - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - @Embeddable - public class Address { - protected String street; - protected String city; - protected String state; - @Embedded - protected Zipcode zipcode; - } - - @Embeddable - public class Zipcode { - protected String zip; - protected String plusFour; - } - - @Entity - public class Customer { - @Id - protected Integer id; - protected String name; - @AttributeOverrides( { - @AttributeOverride(name = "state", - column = @Column(name = "ADDR_STATE")), - @AttributeOverride(name = "zipcode.zip", - column = @Column(name = "ADDR_ZIP")) - }) - @Embedded - protected Address address; - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - @Test - @Resources(annotatedClasses = { Zipcode.class, Address.class, Customer.class }) - public void testNestedEmbeddable() { - EntityBinding binding = getEntityBinding( Customer.class ); - - final String addressComponentName = "address"; - assertNotNull( binding.locateAttributeBinding( addressComponentName ) ); - assertTrue( binding.locateAttributeBinding( addressComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding attributeComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - addressComponentName - ); - - assertNotNull( attributeComponentBinding.locateAttributeBinding( "street" ) ); - assertNotNull( attributeComponentBinding.locateAttributeBinding( "city" ) ); - assertNotNull( attributeComponentBinding.locateAttributeBinding( "state" ) ); - - BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeComponentBinding.locateAttributeBinding( - "state" - ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) stateAttribute.getValue(); - assertEquals( - "Attribute override specifies a custom column name", - "ADDR_STATE", - column.getColumnName().getName() - ); - - - final String zipComponentName = "zipcode"; - assertNotNull( attributeComponentBinding.locateAttributeBinding( zipComponentName ) ); - assertTrue( attributeComponentBinding.locateAttributeBinding( zipComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding zipComponentBinding = (ComponentAttributeBinding) attributeComponentBinding.locateAttributeBinding( - zipComponentName - ); - - BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipComponentBinding.locateAttributeBinding( "zip" ); - column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); - assertEquals( - "Attribute override specifies a custom column name", - "ADDR_ZIP", - column.getColumnName().getName() - ); - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - @Embeddable - public class A { - @Embedded - @AttributeOverrides( { - @AttributeOverride(name = "foo", column = @Column(name = "BAR")), - @AttributeOverride(name = "fubar", column = @Column(name = "A_WINS")) - }) - private B b; - - public B getB() { - return b; - } - } - - @Embeddable - public class B { - private String foo; - private String fubar; - - public String getFoo() { - return foo; - } - - public String getFubar() { - return fubar; - } - } - - @Entity - public class C { - @Id - int id; - - @Embedded - @AttributeOverride(name = "b.fubar", column = @Column(name = "C_WINS")) - protected A a; - - public int getId() { - return id; - } - - public A getA() { - return a; - } - } - - @Test - @Resources(annotatedClasses = { A.class, B.class, C.class }) - public void testAttributeOverrideInEmbeddable() { - EntityBinding binding = getEntityBinding( C.class ); - - final String aComponentName = "a"; - assertNotNull( binding.locateAttributeBinding( aComponentName ) ); - assertTrue( binding.locateAttributeBinding( aComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding aComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - aComponentName - ); - - final String bComponentName = "b"; - assertNotNull( aComponentBinding.locateAttributeBinding( bComponentName ) ); - assertTrue( aComponentBinding.locateAttributeBinding( bComponentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding bComponentBinding = (ComponentAttributeBinding) aComponentBinding.locateAttributeBinding( - bComponentName - ); - - BasicAttributeBinding attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "foo" ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) attribute.getValue(); - assertEquals( - "Attribute override specifies a custom column name", - "BAR", - column.getColumnName().getName() - ); - - attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "fubar" ); - column = (org.hibernate.metamodel.relational.Column) attribute.getValue(); - assertEquals( - "Attribute override specifies a custom column name", - "C_WINS", - column.getColumnName().getName() - ); - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - @Embeddable - public class EmbeddableEntity { - private String test; - @Parent - private MainEntity parent; - } - - @Entity - public class MainEntity { - @Id - private int id; - - @Embedded - private EmbeddableEntity embedded; - } - - @Test - @Resources(annotatedClasses = { MainEntity.class, EmbeddableEntity.class }) - public void testParentReferencingAttributeName() { - EntityBinding binding = getEntityBinding( MainEntity.class ); - - final String componentName = "embedded"; - assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - componentName - ); - - assertEquals( "Wrong parent reference name", "parent", componentBinding.getParentReference().getName() ); - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - public interface Car { - int getHorsePower(); - } - - @Embeddable - public class CarImpl implements Car { - @Override - public int getHorsePower() { - return 0; - } - } - - @Entity - public class Owner { - private int id; - private Car car; - - @Id - public int getId() { - return id; - } - - @Embedded - @Target(CarImpl.class) - public Car getCar() { - return car; - } - } - - @Test - @Resources(annotatedClasses = { Owner.class, CarImpl.class, Car.class }) - public void testTargetAnnotationWithEmbeddable() { - EntityBinding binding = getEntityBinding( Owner.class ); - - final String componentName = "car"; - assertNotNull( binding.locateAttributeBinding( componentName ) ); - assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); - ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( - componentName - ); - - BasicAttributeBinding attribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "horsePower" ); - assertTrue( attribute.getAttribute().isTypeResolved() ); - assertEquals( - "Wrong resolved type", - "int", - attribute.getAttribute().getSingularAttributeType().getClassName() - ); - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddedIdTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddedIdTest.java deleted file mode 100644 index 7ec16508b5bf..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/EmbeddedIdTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Embeddable; -import javax.persistence.EmbeddedId; -import javax.persistence.Entity; - -import org.junit.Test; - -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.EntityIdentifier; -import org.hibernate.testing.FailureExpected; - -import static junit.framework.Assert.assertTrue; - -/** - * @author Strong Liu - */ -@FailureExpected(jiraKey = "HHH-6447", message = "Work in progress") -public class EmbeddedIdTest extends BaseAnnotationBindingTestCase { - @Test -// @Resources(annotatedClasses = { User.class, Address.class }) - public void testEmbeddable() { - EntityBinding binding = getEntityBinding( User.class ); - EntityIdentifier identifier = binding.getHierarchyDetails().getEntityIdentifier(); - assertTrue( identifier.isEmbedded() ); - } - - @Entity - @Access( AccessType.FIELD ) - class User { - private String name; - @EmbeddedId - private Address address; - } - - @Embeddable - class Address { - String street; - String city; - String postCode; - } -} - - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTest.java deleted file mode 100644 index a35651e39fc8..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.AttributeOverride; -import javax.persistence.AttributeOverrides; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; - -import org.junit.Test; - -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.SingularAttributeBinding; -import org.hibernate.metamodel.domain.NonEntity; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.testing.FailureExpected; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; - -/** - * Tests for {@link javax.persistence.MappedSuperclass} {@link javax.persistence.AttributeOverrides} - * and {@link javax.persistence.AttributeOverride}. - * - * @author Hardy Ferentschik - */ -@FailureExpected(jiraKey = "HHH-6447", message = "Work in progress") -public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { - @Test -// @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) - public void testSimpleAttributeOverrideInMappedSuperclass() { - EntityBinding binding = getEntityBinding( MyEntity.class ); - SingularAttributeBinding nameBinding = (SingularAttributeBinding) binding.locateAttributeBinding( "name" ); - assertNotNull( "the name attribute should be bound to MyEntity", nameBinding ); - - Column column = (Column) nameBinding.getValue(); - assertEquals( "Wrong column name", "MY_NAME", column.getColumnName().toString() ); - } - - @Test -// @Resources(annotatedClasses = { MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class }) - public void testLastAttributeOverrideWins() { - EntityBinding binding = getEntityBinding( MyEntity.class ); - SingularAttributeBinding fooBinding = (SingularAttributeBinding) binding.locateAttributeBinding( "foo" ); - assertNotNull( "the foo attribute should be bound to MyEntity", fooBinding ); - - Column column = (Column) fooBinding.getValue(); - assertEquals( "Wrong column name", "MY_FOO", column.getColumnName().toString() ); - } - - @Test -// @Resources(annotatedClasses = { SubclassOfNoEntity.class, NoEntity.class }) - public void testNonEntityBaseClass() { - EntityBinding binding = getEntityBinding( SubclassOfNoEntity.class ); - assertEquals( "Wrong entity name", SubclassOfNoEntity.class.getName(), binding.getEntity().getName() ); - assertEquals( "Wrong entity name", NoEntity.class.getName(), binding.getEntity().getSuperType().getName() ); - assertTrue( binding.getEntity().getSuperType() instanceof NonEntity ); - } - - @MappedSuperclass - class MyMappedSuperClassBase { - @Id - private int id; - String foo; - } - - @MappedSuperclass - @AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "SUPER_FOO")) - class MyMappedSuperClass extends MyMappedSuperClassBase { - String name; - } - - @Entity - @AttributeOverrides( { - @AttributeOverride(name = "name", column = @javax.persistence.Column(name = "MY_NAME")), - @AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "MY_FOO")) - }) - class MyEntity extends MyMappedSuperClass { - private Long count; - - } - - class NoEntity { - String name; - int age; - } - - @Entity - class SubclassOfNoEntity extends NoEntity { - @Id - private int id; - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/QuotedIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/QuotedIdentifierTest.java deleted file mode 100644 index c8b95b2afd78..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/QuotedIdentifierTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; - -import org.junit.Test; - -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.relational.Identifier; - -import static org.junit.Assert.assertEquals; - -/** - * @author Strong Liu - */ -public class QuotedIdentifierTest extends BaseAnnotationBindingTestCase { - private final String ormPath = "org/hibernate/metamodel/source/annotations/xml/orm-quote-identifier.xml"; - - @Test - @Resources(annotatedClasses = { Item.class, Item2.class, Item3.class, Item4.class }, ormXmlPath = ormPath) - public void testDelimitedIdentifiers() { - EntityBinding item = getEntityBinding( Item.class ); - assertIdentifierEquals( "`QuotedIdentifierTest$Item`", item ); - - item = getEntityBinding( Item2.class ); - assertIdentifierEquals( "`TABLE_ITEM2`", item ); - - item = getEntityBinding( Item3.class ); - assertIdentifierEquals( "`TABLE_ITEM3`", item ); - - item = getEntityBinding( Item4.class ); - assertIdentifierEquals( "`TABLE_ITEM4`", item ); - } - - //todo check if the column names are quoted - - private void assertIdentifierEquals(String expected, EntityBinding realValue) { - org.hibernate.metamodel.relational.Table table = (org.hibernate.metamodel.relational.Table) realValue.getPrimaryTable(); - assertEquals( Identifier.toIdentifier( expected ), table.getTableName() ); - } - - @Entity - private static class Item { - @Id - Long id; - } - - @Entity - @Table(name = "TABLE_ITEM2") - private static class Item2 { - @Id - Long id; - } - - @Entity - @Table(name = "`TABLE_ITEM3`") - private static class Item3 { - @Id - Long id; - } - - @Entity - @Table(name = "\"TABLE_ITEM4\"") - private static class Item4 { - @Id - Long id; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SecondaryTableTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SecondaryTableTest.java deleted file mode 100644 index 2ba3cd1168a4..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/SecondaryTableTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.entity; - -import java.util.Iterator; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.SecondaryTable; - -import org.junit.Test; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.relational.SimpleValue; -import org.hibernate.metamodel.relational.Table; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.fail; - -/** - * @author Hardy Ferentschik - */ -public class SecondaryTableTest extends BaseAnnotationBindingTestCase { - @Entity - @SecondaryTable(name = "SECOND_TABLE") - class EntityWithSecondaryTable { - @Id - private long id; - - @Column(table = "SECOND_TABLE") - private String name; - } - - @Test - @Resources(annotatedClasses = EntityWithSecondaryTable.class) - public void testSecondaryTableExists() { - EntityBinding binding = getEntityBinding( EntityWithSecondaryTable.class ); - Table table = (Table) binding.locateTable( "SECOND_TABLE" ); - assertEquals( "The secondary table should exist", "SECOND_TABLE", table.getTableName().getName() ); - - Iterator valueIterator = table.values().iterator(); - assertTrue( valueIterator.hasNext() ); - org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) valueIterator.next(); - assertEquals( "Wrong column name", "name", column.getColumnName().getName() ); - assertFalse( valueIterator.hasNext() ); - } - - @Test - @Resources(annotatedClasses = EntityWithSecondaryTable.class) - public void testRetrievingUnknownTable() { - EntityBinding binding = getEntityBinding( EntityWithSecondaryTable.class ); - try { - binding.locateTable( "FOO" ); - fail(); - } - catch ( AssertionFailure e ) { - assertTrue( e.getMessage().startsWith( "Unable to find table" ) ); - } - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java deleted file mode 100644 index bccbc2ecc765..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/UniqueConstraintBindingTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ - -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; - -import org.junit.Test; - -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.relational.Column; -import org.hibernate.metamodel.relational.TableSpecification; -import org.hibernate.metamodel.relational.UniqueKey; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; - -/** - * test for {@link javax.persistence.UniqueConstraint} - * - * @author Strong Liu - */ -public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase { - @Test - @Resources(annotatedClasses = TableWithUniqueConstraint.class) - public void testTableUniqueConstraints() { - EntityBinding binding = getEntityBinding( TableWithUniqueConstraint.class ); - TableSpecification table = binding.getPrimaryTable(); - Iterable uniqueKeyIterable = table.getUniqueKeys(); - assertNotNull( uniqueKeyIterable ); - int i = 0; - for ( UniqueKey key : uniqueKeyIterable ) { - i++; - assertEquals( "u1", key.getName() ); - assertTrue( table == key.getTable() ); - assertNotNull( key.getColumns() ); - int j = 0; - for ( Column column : key.getColumns() ) { - j++; - } - assertEquals( "There should be two columns in the unique constraint", 2, j ); - } - assertEquals( "There should only be one unique constraint", 1, i ); - } - - @Entity - @Table(uniqueConstraints = { @UniqueConstraint(name = "u1", columnNames = { "name", "age" }) }) - class TableWithUniqueConstraint { - @Id - int id; - String name; - int age; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/WhereClauseTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/WhereClauseTest.java deleted file mode 100644 index 6b3702e75484..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/WhereClauseTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.hibernate.metamodel.source.annotations.entity; - -import javax.persistence.Entity; -import javax.persistence.Id; - -import org.junit.Test; - -import org.hibernate.annotations.Where; -import org.hibernate.metamodel.binding.EntityBinding; - -import static junit.framework.Assert.assertEquals; - -/** - * @author Hardy Ferentschik - */ -public class WhereClauseTest extends BaseAnnotationBindingTestCase { - @Test - @Resources(annotatedClasses = Foo.class) - public void testWhereFilter() { - EntityBinding binding = getEntityBinding( Foo.class ); - assertEquals( "Wrong where filter", "1=1", binding.getWhereFilter() ); - } - - @Entity - @Where(clause = "1=1") - class Foo { - @Id - private long id; - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinderTest.java deleted file mode 100644 index a686f1b03e0b..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/global/FetchProfileBinderTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.global; - -import java.util.Iterator; - -import org.jboss.jandex.Index; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.MappingException; -import org.hibernate.annotations.FetchMode; -import org.hibernate.annotations.FetchProfile; -import org.hibernate.annotations.FetchProfiles; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContextImpl; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static junit.framework.Assert.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Hardy Ferentschik - */ -public class FetchProfileBinderTest extends BaseUnitTestCase { - - private StandardServiceRegistryImpl serviceRegistry; - private ClassLoaderService service; - private MetadataImpl meta; - - @Before - public void setUp() { - serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); - service = serviceRegistry.getService( ClassLoaderService.class ); - meta = (MetadataImpl) new MetadataSources( serviceRegistry ).buildMetadata(); - } - - @After - public void tearDown() { - serviceRegistry.destroy(); - } - - @Test - public void testSingleFetchProfile() { - @FetchProfile(name = "foo", fetchOverrides = { - @FetchProfile.FetchOverride(entity = Foo.class, association = "bar", mode = FetchMode.JOIN) - }) - class Foo { - } - Index index = JandexHelper.indexForClass( service, Foo.class ); - - FetchProfileBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); - - Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); - assertTrue( mappedFetchProfiles.hasNext() ); - org.hibernate.metamodel.binding.FetchProfile profile = mappedFetchProfiles.next(); - assertEquals( "Wrong fetch profile name", "foo", profile.getName() ); - org.hibernate.metamodel.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); - assertEquals( "Wrong association name", "bar", fetch.getAssociation() ); - assertEquals( "Wrong association type", Foo.class.getName(), fetch.getEntity() ); - } - - @Test - public void testFetchProfiles() { - Index index = JandexHelper.indexForClass( service, FooBar.class ); - FetchProfileBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); - - Iterator mappedFetchProfiles = meta.getFetchProfiles().iterator(); - assertTrue( mappedFetchProfiles.hasNext() ); - org.hibernate.metamodel.binding.FetchProfile profile = mappedFetchProfiles.next(); - assertProfiles( profile ); - - assertTrue( mappedFetchProfiles.hasNext() ); - profile = mappedFetchProfiles.next(); - assertProfiles( profile ); - } - - private void assertProfiles(org.hibernate.metamodel.binding.FetchProfile profile) { - if ( profile.getName().equals( "foobar" ) ) { - org.hibernate.metamodel.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); - assertEquals( "Wrong association name", "foobar", fetch.getAssociation() ); - assertEquals( "Wrong association type", FooBar.class.getName(), fetch.getEntity() ); - } - else if ( profile.getName().equals( "fubar" ) ) { - org.hibernate.metamodel.binding.FetchProfile.Fetch fetch = profile.getFetches().iterator().next(); - assertEquals( "Wrong association name", "fubar", fetch.getAssociation() ); - assertEquals( "Wrong association type", FooBar.class.getName(), fetch.getEntity() ); - } - else { - fail( "Wrong fetch name:" + profile.getName() ); - } - } - - @Test(expected = MappingException.class) - public void testNonJoinFetchThrowsException() { - @FetchProfile(name = "foo", fetchOverrides = { - @FetchProfile.FetchOverride(entity = Foo.class, association = "bar", mode = FetchMode.SELECT) - }) - class Foo { - } - Index index = JandexHelper.indexForClass( service, Foo.class ); - - FetchProfileBinder.bind( new AnnotationBindingContextImpl( meta, index ) ); - } - - @FetchProfiles( { - @FetchProfile(name = "foobar", fetchOverrides = { - @FetchProfile.FetchOverride(entity = FooBar.class, association = "foobar", mode = FetchMode.JOIN) - }), - @FetchProfile(name = "fubar", fetchOverrides = { - @FetchProfile.FetchOverride(entity = FooBar.class, association = "fubar", mode = FetchMode.JOIN) - }) - }) - class FooBar { - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/BaseAnnotationIndexTestCase.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/BaseAnnotationIndexTestCase.java deleted file mode 100644 index fd57f6d3fe8a..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/BaseAnnotationIndexTestCase.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.util; - -import java.util.Set; -import javax.persistence.AccessType; - -import org.jboss.jandex.Index; -import org.junit.After; -import org.junit.Before; - -import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; -import org.hibernate.metamodel.source.annotations.AnnotationBindingContextImpl; -import org.hibernate.metamodel.source.annotations.EntityHierarchyBuilder; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.entity.EmbeddableHierarchy; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.internal.MetadataImpl; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -/** - * @author Hardy Ferentschik - */ -public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase { - private MetadataImpl meta; - - @Before - public void setUp() { - MetadataSources sources = new MetadataSources( new StandardServiceRegistryBuilder().build() ); - meta = (MetadataImpl) sources.buildMetadata(); - } - - @After - public void tearDown() { - } - - public Set createEntityHierarchies(Class... clazz) { - Index index = JandexHelper.indexForClass( - meta.getServiceRegistry().getService( ClassLoaderService.class ), - clazz - ); - AnnotationBindingContext context = new AnnotationBindingContextImpl( meta, index ); - return EntityHierarchyBuilder.createEntityHierarchies( context ); - } - - public EmbeddableHierarchy createEmbeddableHierarchy(AccessType accessType, Class... configuredClasses) { - Index index = JandexHelper.indexForClass( - meta.getServiceRegistry().getService( ClassLoaderService.class ), - configuredClasses - ); - AnnotationBindingContext context = new AnnotationBindingContextImpl( meta, index ); - return EmbeddableHierarchy.createEmbeddableHierarchy( configuredClasses[0], "", accessType, context ); - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EmbeddableHierarchyTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EmbeddableHierarchyTest.java deleted file mode 100644 index deae20dbd71f..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EmbeddableHierarchyTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.util; - -import java.util.Iterator; -import javax.persistence.AccessType; -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.junit.Ignore; -import org.junit.Test; - -import org.hibernate.AssertionFailure; -import org.hibernate.metamodel.source.annotations.entity.EmbeddableClass; -import org.hibernate.metamodel.source.annotations.entity.EmbeddableHierarchy; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static org.junit.Assert.assertFalse; - -/** - * @author Hardy Ferentschik - */ -@Ignore("fails on openjdk") -public class EmbeddableHierarchyTest extends BaseAnnotationIndexTestCase { - @Test - @Ignore("HHH-6606 ignore for now") - public void testEmbeddableHierarchy() { - @Embeddable - class A { - String foo; - } - - class B extends A { - } - - @Embeddable - class C extends B { - String bar; - } - - EmbeddableHierarchy hierarchy = createEmbeddableHierarchy( - AccessType.FIELD, - C.class, - A.class, - B.class - ); - Iterator iter = hierarchy.iterator(); - ClassInfo info = iter.next().getClassInfo(); - assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() ); - info = iter.next().getClassInfo(); - assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() ); - info = iter.next().getClassInfo(); - assertEquals( "wrong class", DotName.createSimple( C.class.getName() ), info.name() ); - assertFalse( iter.hasNext() ); - assertNotNull( hierarchy ); - } - - @Test(expected = AssertionFailure.class) - public void testEmbeddableHierarchyWithNotAnnotatedEntity() { - class NonAnnotatedEmbeddable { - } - - createEmbeddableHierarchy( AccessType.FIELD, NonAnnotatedEmbeddable.class ); - } - - @Entity - public class Foo { - @Id - @GeneratedValue - private int id; - } - - @Entity - public class A { - @Id - @GeneratedValue - private int id; - } - - @Entity - public class B extends A { - private String name; - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EntityHierarchyTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EntityHierarchyTest.java deleted file mode 100644 index 202a0acbdde9..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/EntityHierarchyTest.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.util; - -import java.util.Iterator; -import java.util.Set; -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.MappedSuperclass; - -import org.junit.Test; - -import org.hibernate.AnnotationException; -import org.hibernate.metamodel.binding.InheritanceType; -import org.hibernate.metamodel.source.binder.EntityHierarchy; -import org.hibernate.metamodel.source.binder.RootEntitySource; -import org.hibernate.metamodel.source.binder.SubclassEntitySource; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -/** - * @author Hardy Ferentschik - */ -public class EntityHierarchyTest extends BaseAnnotationIndexTestCase { - - @Test - public void testSingleEntity() { - @Entity - class Foo { - @Id - @GeneratedValue - private int id; - } - - Set hierarchies = createEntityHierarchies( Foo.class ); - assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); - - EntityHierarchy hierarchy = hierarchies.iterator().next(); - assertEquals( - "wrong entity name", - Foo.class.getName(), - hierarchy.getRootEntitySource().getEntityName() - ); - } - - @Test - public void testSimpleInheritance() { - @Entity - class A { - @Id - @GeneratedValue - private int id; - } - - @Entity - class B extends A { - private String name; - } - Set hierarchies = createEntityHierarchies( B.class, A.class ); - assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); - - EntityHierarchy hierarchy = hierarchies.iterator().next(); - RootEntitySource rootSource = hierarchy.getRootEntitySource(); - assertEquals( - "wrong entity name", - A.class.getName(), - rootSource.getEntityName() - ); - - Iterator iter = rootSource.subclassEntitySources().iterator(); - assertTrue( "There should be a subclass entity source", iter.hasNext() ); - assertEquals( "wrong class", B.class.getName(), iter.next().getEntityName() ); - assertFalse( "There should be no more subclass entity sources", iter.hasNext() ); - } - - @Test - public void testMultipleHierarchies() { - @Entity - class Foo { - @Id - @GeneratedValue - private int id; - } - - @Entity - class A { - @Id - @GeneratedValue - private int id; - } - - @Entity - class B extends A { - private String name; - } - Set hierarchies = createEntityHierarchies( B.class, Foo.class, A.class ); - assertEquals( "There should be only one hierarchy", 2, hierarchies.size() ); - } - - @Test - public void testMappedSuperClass() { - @MappedSuperclass - class MappedSuperClass { - @Id - @GeneratedValue - private int id; - } - - class UnmappedSubClass extends MappedSuperClass { - private String unmappedProperty; - } - - @Entity - class MappedSubClass extends UnmappedSubClass { - private String mappedProperty; - } - - Set hierarchies = createEntityHierarchies( - MappedSubClass.class, - MappedSuperClass.class, - UnmappedSubClass.class - ); - assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); - - EntityHierarchy hierarchy = hierarchies.iterator().next(); - assertEquals( - "wrong entity name", - MappedSubClass.class.getName(), - hierarchy.getRootEntitySource().getEntityName() - ); - } - - @Test(expected = AnnotationException.class) - public void testEntityAndMappedSuperClassAnnotations() { - @Entity - @MappedSuperclass - class EntityAndMappedSuperClass { - } - - createEntityHierarchies( EntityAndMappedSuperClass.class ); - } - - @Test(expected = AnnotationException.class) - public void testEntityAndEmbeddableAnnotations() { - @Entity - @Embeddable - class EntityAndEmbeddable { - } - - createEntityHierarchies( EntityAndEmbeddable.class ); - } - - @Test(expected = AnnotationException.class) - public void testNoIdAnnotation() { - @Entity - class A { - String id; - } - - @Entity - class B extends A { - } - - createEntityHierarchies( B.class, A.class ); - } - - @Test - public void testDefaultInheritanceStrategy() { - @Entity - class A { - @Id - String id; - } - - @Entity - class B extends A { - } - - Set hierarchies = createEntityHierarchies( B.class, A.class ); - assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); - - EntityHierarchy hierarchy = hierarchies.iterator().next(); - assertEquals( - "wrong entity name", - A.class.getName(), - hierarchy.getRootEntitySource().getEntityName() - ); - assertEquals( "Wrong inheritance type", InheritanceType.SINGLE_TABLE, hierarchy.getHierarchyInheritanceType() ); - } - - @Test - public void testExplicitInheritanceStrategy() { - @MappedSuperclass - class MappedSuperClass { - - } - - @Entity - @Inheritance(strategy = javax.persistence.InheritanceType.JOINED) - class A extends MappedSuperClass { - @Id - String id; - } - - @Entity - class B extends A { - } - - Set hierarchies = createEntityHierarchies( - B.class, - MappedSuperClass.class, - A.class - ); - - EntityHierarchy hierarchy = hierarchies.iterator().next(); - assertEquals( - "wrong entity name", - A.class.getName(), - hierarchy.getRootEntitySource().getEntityName() - ); - assertEquals( "Wrong inheritance type", InheritanceType.JOINED, hierarchy.getHierarchyInheritanceType() ); - } - - @Test(expected = AnnotationException.class) - public void testMultipleConflictingInheritanceDefinitions() { - - @Entity - @Inheritance(strategy = javax.persistence.InheritanceType.JOINED) - class A { - String id; - } - - @Entity - @Inheritance(strategy = javax.persistence.InheritanceType.TABLE_PER_CLASS) - class B extends A { - } - - createEntityHierarchies( B.class, A.class ); - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java deleted file mode 100644 index 10edc54a4410..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/util/JandexHelperTest.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.util; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; -import java.util.Map; -import javax.persistence.AttributeConverter; -import javax.persistence.AttributeOverride; -import javax.persistence.Basic; -import javax.persistence.Column; -import javax.persistence.Converter; -import javax.persistence.Entity; -import javax.persistence.LockModeType; -import javax.persistence.NamedQuery; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.Index; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.AssertionFailure; -import org.hibernate.HibernateException; -import org.hibernate.annotations.NamedNativeQuery; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.metamodel.source.annotations.HibernateDotNames; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static junit.framework.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -/** - * Tests for the helper class {@link JandexHelper}. - * - * @author Hardy Ferentschik - */ -public class JandexHelperTest extends BaseUnitTestCase { - private StandardServiceRegistryImpl serviceRegistry; - private ClassLoaderService classLoaderService; - - @Before - public void setUp() { - serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); - classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - } - - @After - public void tearDown() { - serviceRegistry.destroy(); - } - - @Test - public void testGetMemberAnnotations() { - class Foo { - @Column - @Basic - private String bar; - private String fubar; - } - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - - ClassInfo classInfo = index.getClassByName( DotName.createSimple( Foo.class.getName() ) ); - Map> memberAnnotations = JandexHelper.getMemberAnnotations( - classInfo, "bar" - ); - assertTrue( - "property bar should defines @Column annotation", - memberAnnotations.containsKey( DotName.createSimple( Column.class.getName() ) ) - ); - assertTrue( - "property bar should defines @Basic annotation", - memberAnnotations.containsKey( DotName.createSimple( Basic.class.getName() ) ) - ); - - memberAnnotations = JandexHelper.getMemberAnnotations( classInfo, "fubar" ); - assertTrue( "there should be no annotations in fubar", memberAnnotations.isEmpty() ); - } - - @Test - public void testGettingNestedAnnotation() { - @AttributeOverride(name = "foo", column = @Column(name = "FOO")) - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - // try to retrieve the name - String name = JandexHelper.getValue( annotationInstance, "name", String.class ); - assertEquals( "Wrong nested annotation", "foo", name ); - - // try to retrieve the nested column annotation instance - AnnotationInstance columnAnnotationInstance = JandexHelper.getValue( - annotationInstance, - "column", - AnnotationInstance.class - ); - assertNotNull( columnAnnotationInstance ); - assertEquals( - "Wrong nested annotation", - "javax.persistence.Column", - columnAnnotationInstance.name().toString() - ); - } - - @Test(expected = AssertionFailure.class) - public void testTryingToRetrieveWrongType() { - @AttributeOverride(name = "foo", column = @Column(name = "FOO")) - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.ATTRIBUTE_OVERRIDE ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - JandexHelper.getValue( annotationInstance, "name", Float.class ); - } - - @Test - public void testRetrieveDefaultEnumElement() { - @NamedQuery(name = "foo", query = "fubar") - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class ); - assertEquals( "Wrong lock mode", LockModeType.NONE, lockMode ); - } - - @Test - public void testRetrieveExplicitEnumElement() { - @NamedQuery(name = "foo", query = "bar", lockMode = LockModeType.OPTIMISTIC) - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.NAMED_QUERY ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - LockModeType lockMode = JandexHelper.getEnumValue( annotationInstance, "lockMode", LockModeType.class ); - assertEquals( "Wrong lock mode", LockModeType.OPTIMISTIC, lockMode ); - } - - @Test - public void testRetrieveStringArray() { - class Foo { - @org.hibernate.annotations.Index(name = "index", columnNames = { "a", "b", "c" }) - private String foo; - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( HibernateDotNames.INDEX ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - String[] columnNames = JandexHelper.getValue( annotationInstance, "columnNames", String[].class ); - Assert.assertTrue( columnNames.length == 3 ); - } - - @Test(expected = AssertionFailure.class) - public void testRetrieveClassParameterAsClass() { - @NamedNativeQuery(name = "foo", query = "bar", resultClass = Foo.class) - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - JandexHelper.getValue( annotationInstance, "resultClass", Class.class ); - } - - @Test - public void testRetrieveClassParameterAsString() { - @NamedNativeQuery(name = "foo", query = "bar", resultClass = Foo.class) - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( HibernateDotNames.NAMED_NATIVE_QUERY ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - String fqcn = JandexHelper.getValue( annotationInstance, "resultClass", String.class ); - assertEquals( "Wrong class names", Foo.class.getName(), fqcn ); - } - - @Test - public void testRetrieveUnknownParameter() { - @Entity - class Foo { - } - - Index index = JandexHelper.indexForClass( classLoaderService, Foo.class ); - List annotationInstances = index.getAnnotations( JPADotNames.ENTITY ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - try { - JandexHelper.getValue( annotationInstance, "foo", String.class ); - fail(); - } - catch ( AssertionFailure e ) { - assertTrue( - e.getMessage() - .startsWith( "The annotation javax.persistence.Entity does not define a parameter 'foo'" ) - ); - } - } - - - @Test - public void testPrimitiveAnnotationAttributeTypes() { - @Converter( autoApply = true ) - class MyConverter implements AttributeConverter { - - @Override - public String convertToDatabaseColumn(URL attribute) { - return attribute.toExternalForm(); - } - - @Override - public URL convertToEntityAttribute(String dbData) { - try { - return new URL( dbData ); - } - catch (MalformedURLException e) { - throw new HibernateException( "Could not convert string [" + dbData + "] to url", e ); - } - } - } - - Index index = JandexHelper.indexForClass( classLoaderService, MyConverter.class ); - List annotationInstances = index.getAnnotations( JPADotNames.CONVERTER ); - assertTrue( annotationInstances.size() == 1 ); - AnnotationInstance annotationInstance = annotationInstances.get( 0 ); - - boolean value = JandexHelper.getValue( annotationInstance, "autoApply", boolean.class ); - Assert.assertTrue( value ); - } -} - - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilderTest.java deleted file mode 100644 index 52d118924176..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/IndexBuilderTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -import org.junit.Test; - -/** - * @author Strong Liu - */ -public class IndexBuilderTest extends AbstractMockerTest { - @Test - public void test() { - IndexBuilder builder = getIndexBuilder(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Item.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Item.java deleted file mode 100644 index fa5be30fc4ea..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/xml/mocker/Item.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc.. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.annotations.xml.mocker; - -/** - * @author Strong Liu - */ -public class Item { - private Long id; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SimpleEntity.java deleted file mode 100644 index c6f1c5c76302..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/SimpleEntity.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.source.internal; - -import javax.persistence.Entity; -import javax.persistence.Id; - -/** - * @author Steve Ebersole - */ -@Entity -public class SimpleEntity { - @Id - private Long id; - private String name; - - public SimpleEntity() { - } - - public SimpleEntity(String name) { - this.name = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/package-info.java deleted file mode 100644 index cf82afd1f11c..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/internal/package-info.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -@FetchProfile(name = "package-configured-profile", fetchOverrides = { - @FetchProfile.FetchOverride(entity = Foo.class, association = "bar", mode = FetchMode.JOIN) -}) -package org.hibernate.metamodel.source.internal; - -import org.hibernate.annotations.FetchMode; -import org.hibernate.annotations.FetchProfile; - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java new file mode 100644 index 000000000000..7f19074fe50e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java @@ -0,0 +1,317 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.sql.Types; +import java.util.List; + +import org.hibernate.FetchMode; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.domain.Aggregate; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.BasicType; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.type.LongType; +import org.hibernate.type.StringType; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Basic tests of {@code hbm.xml} and annotation binding code + * + * @author Steve Ebersole + * @author Hardy Ferentschik + */ +public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + @Test + public void testSimpleEntityMapping() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSimpleEntityBinding( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); + assertRoot( metadata, entityBinding ); + assertIdAndSimpleProperty( entityBinding ); + + assertNull( entityBinding.getHierarchyDetails().getEntityVersion() ); + } + + @Test + public void testSimpleVersionedEntityMapping() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSimpleVersionedEntityBinding( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( SimpleVersionedEntity.class.getName() ); + assertIdAndSimpleProperty( entityBinding ); + + assertNotNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding().getAttribute() ); + + final BasicAttributeBinding versionAttributeBinding = + entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding(); + assertEquals( "does not have 1 relational binding", 1, versionAttributeBinding.getRelationalValueBindings().size() ); + assertEquals( "version is nullable", false, versionAttributeBinding.getRelationalValueBindings().get( 0 ).isNullable() ); + } + + protected void testEntityWithManyToOneMapping(String defaultManyToOneColumnReferencingId) { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSimpleEntityBinding( sources ); + addSourcesForManyToOne( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + + final String simpleEntityClassName = SimpleEntity.class.getName(); + EntityBinding simpleEntityBinding = metadata.getEntityBinding( simpleEntityClassName ); + assertIdAndSimpleProperty( simpleEntityBinding ); + + EntityBinding entityWithManyToOneBinding = metadata.getEntityBinding( EntityWithManyToOnes.class.getName() ); + AttributeBinding attributeBinding = entityWithManyToOneBinding.locateAttributeBinding( "simpleEntity" ); + checkManyToOneAttributeBinding( + metadata, + entityWithManyToOneBinding, + attributeBinding, + SingularAttributeBinding.class.cast( + simpleEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() + ), + defaultManyToOneColumnReferencingId, + false + ); + + checkManyToOneAttributeBinding( + metadata, + entityWithManyToOneBinding, + entityWithManyToOneBinding.locateAttributeBinding( "simpleEntityFromPropertyRef" ), + SingularAttributeBinding.class.cast( simpleEntityBinding.locateAttributeBinding( "name" ) ), + "simplename", + true + ); + } + + private void checkManyToOneAttributeBinding( + MetadataImplementor metadata, + EntityBinding entityWithManyToOneBinding, + AttributeBinding attributeBinding, + SingularAttributeBinding referencedAttributeBinding, + String manyToOneColumnName, + boolean expectedNullable) { + final EntityBinding referencedEntityBinding = referencedAttributeBinding.getContainer().seekEntityBinding(); + final String referencedEntityName = referencedEntityBinding.getEntityName(); + assertTrue( SingularAttributeBinding.class.isInstance( referencedAttributeBinding ) ); + assertEquals( 1, SingularAttributeBinding.class.cast( referencedAttributeBinding ).getRelationalValueBindings().size() ); + final Value referencedValue = + SingularAttributeBinding.class.cast( referencedAttributeBinding ) + .getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( Column.class.isInstance( referencedValue ) ); + final JdbcDataType referencedJdbcDataType = Column.class.cast( referencedValue ).getJdbcDataType(); + + // binding model + assertTrue( attributeBinding.isAssociation() ); + assertTrue( ManyToOneAttributeBinding.class.isInstance( attributeBinding ) ); + ManyToOneAttributeBinding manyToOneAttributeBinding = (ManyToOneAttributeBinding) attributeBinding; + assertEquals( referencedEntityName, manyToOneAttributeBinding.getReferencedEntityName() ); + assertSame( referencedEntityBinding, manyToOneAttributeBinding.getReferencedEntityBinding() ); + assertSame( CascadeStyles.NONE, manyToOneAttributeBinding.getCascadeStyle() ); + assertTrue( manyToOneAttributeBinding.isLazy() ); + assertSame( FetchMode.SELECT, manyToOneAttributeBinding.getFetchMode() ); + assertSame( FetchTiming.DELAYED, manyToOneAttributeBinding.getFetchTiming() ); + assertSame( entityWithManyToOneBinding, manyToOneAttributeBinding.getContainer() ); + Assert.assertEquals( "property", manyToOneAttributeBinding.getPropertyAccessorName() ); + assertTrue( manyToOneAttributeBinding.isIncludedInOptimisticLocking() ); + assertFalse( manyToOneAttributeBinding.isAlternateUniqueKey() ); + assertEquals( expectedNullable, manyToOneAttributeBinding.isNullable() ); + HibernateTypeDescriptor hibernateTypeDescriptor = manyToOneAttributeBinding.getHibernateTypeDescriptor(); + Assert.assertNull( hibernateTypeDescriptor.getExplicitTypeName() ); + Assert.assertEquals( + referencedEntityName, + hibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString() + ); + assertTrue( hibernateTypeDescriptor.isToOne() ); + assertTrue( hibernateTypeDescriptor.getTypeParameters().isEmpty() ); + + // domain model + Attribute simpleEntityAttribute= entityWithManyToOneBinding.getEntity().locateAttribute( "simpleEntity" ); + assertEquals( "simpleEntity", simpleEntityAttribute.getName() ); + Assert.assertSame( entityWithManyToOneBinding.getEntity(), simpleEntityAttribute.getAttributeContainer() ) ; + Assert.assertTrue( simpleEntityAttribute.isSingular() ); + SingularAttribute simpleEntitySingularAttribute = ( SingularAttribute ) simpleEntityAttribute; + assertTrue( simpleEntitySingularAttribute.isTypeResolved() ); + assertSame( + metadata.getEntityBinding( referencedEntityName ).getEntity(), + simpleEntitySingularAttribute.getSingularAttributeType() + ); + Entity simpleEntityAttributeType = (Entity) simpleEntitySingularAttribute.getSingularAttributeType(); + assertEquals( referencedEntityName, simpleEntityAttributeType.getName() ); + Assert.assertEquals( + referencedEntityName, + simpleEntityAttributeType.getDescriptor().getName().toString() + ); + Assert.assertTrue( simpleEntityAttributeType.isAssociation() ); + assertFalse( simpleEntityAttributeType.isAggregate() ); + + // relational + List relationalValueBindings = manyToOneAttributeBinding.getRelationalValueBindings(); + Assert.assertEquals( 1, relationalValueBindings.size() ); + RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 ); + assertFalse( relationalValueBinding.isDerived() ); + assertTrue( relationalValueBinding.isIncludeInInsert() ); + assertTrue( relationalValueBinding.isIncludeInUpdate() ); + assertEquals( expectedNullable, relationalValueBinding.isNullable() ); + assertTrue( relationalValueBinding.getValue() instanceof Column ); + Column column = ( Column ) relationalValueBinding.getValue(); + Assert.assertEquals( Identifier.toIdentifier( manyToOneColumnName ), column.getColumnName() ); + JdbcDataType jdbcDataType = column.getJdbcDataType(); + assertEquals( referencedJdbcDataType.getTypeCode(), jdbcDataType.getTypeCode() ); + assertEquals( referencedJdbcDataType.getJavaType(), jdbcDataType.getJavaType() ); + assertEquals( referencedJdbcDataType.getTypeName(), jdbcDataType.getTypeName() ); + + // locate the foreignKey + boolean sourceColumnFound = false; + for ( ForeignKey fk : relationalValueBinding.getTable().getForeignKeys() ) { + for ( Column sourceColumn : fk.getSourceColumns() ) { + if ( sourceColumn == column ) { + assertFalse( "source column not found in more than one foreign key", sourceColumnFound ); + sourceColumnFound = true; + assertEquals( 1, fk.getTargetColumns().size() ); + assertSame( + referencedAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(), + fk.getTargetColumns().get( 0 ) + ); + } + } + } + assertTrue( "foreign key with specified source column found", sourceColumnFound ); + } + + @Test + public void testSimpleEntityWithSimpleComponentMapping() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForComponentBinding( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntityWithSimpleComponent.class.getName() ); + assertRoot( metadata, entityBinding ); + assertIdAndSimpleProperty( entityBinding ); + + EmbeddedAttributeBinding embeddedAttributeBinding = + (EmbeddedAttributeBinding) entityBinding.locateAttributeBinding( "simpleComponent" ); + assertNotNull( embeddedAttributeBinding ); + assertSame( embeddedAttributeBinding.getAttribute().getSingularAttributeType(), embeddedAttributeBinding.getEmbeddableBinding().getAttributeContainer() ); + assertEquals( "simpleComponent", embeddedAttributeBinding.getAttributePath().getFullPath() ); + assertEquals( "simpleComponent", embeddedAttributeBinding.getEmbeddableBinding().getPathBase().getFullPath() ); + assertSame( entityBinding, embeddedAttributeBinding.getEmbeddableBinding().seekEntityBinding() ); + assertTrue( embeddedAttributeBinding.getAttribute().getSingularAttributeType() instanceof Aggregate ); + } + + public abstract void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources); + + public abstract void addSourcesForSimpleEntityBinding(MetadataSources sources); + + public abstract void addSourcesForManyToOne(MetadataSources sources); + + public abstract void addSourcesForComponentBinding(MetadataSources sources); + + protected void assertIdAndSimpleProperty(EntityBinding entityBinding) { + assertNotNull( entityBinding ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + + AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" ); + assertNotNull( idAttributeBinding ); + assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); + + assertTrue( idAttributeBinding.getAttribute().isSingular() ); + assertNotNull( idAttributeBinding.getAttribute() ); + SingularAttributeBinding singularIdAttributeBinding = (SingularAttributeBinding) idAttributeBinding; + assertFalse( singularIdAttributeBinding.isNullable() ); + SingularAttribute singularIdAttribute = ( SingularAttribute ) idAttributeBinding.getAttribute(); + BasicType basicIdAttributeType = ( BasicType ) singularIdAttribute.getSingularAttributeType(); + assertEquals( Long.class.getName(), basicIdAttributeType.getDescriptor().getName().toString() ); + + assertTrue( singularIdAttributeBinding.getRelationalValueBindings().size() == 1 ); + Value value = singularIdAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( value instanceof Column ); + JdbcDataType idDataType = value.getJdbcDataType(); + assertSame( Long.class, idDataType.getJavaType() ); + assertSame( Types.BIGINT, idDataType.getTypeCode() ); + assertSame( LongType.INSTANCE.getName(), idDataType.getTypeName() ); + + assertNotNull( entityBinding.locateAttributeBinding( "name" ) ); + assertNotNull( entityBinding.locateAttributeBinding( "name" ).getAttribute() ); + assertTrue( entityBinding.locateAttributeBinding( "name" ).getAttribute().isSingular() ); + + SingularAttributeBinding nameBinding = (SingularAttributeBinding) entityBinding.locateAttributeBinding( "name" ); + assertTrue( nameBinding.isNullable() ); + assertSame( StringType.INSTANCE, nameBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); + assertNotNull( nameBinding.getAttribute() ); + assertNotNull( nameBinding.getRelationalValueBindings().size() ); + SingularAttribute singularNameAttribute = nameBinding.getAttribute(); + BasicType basicNameAttributeType = (BasicType) singularNameAttribute.getSingularAttributeType(); + assertEquals( String.class.getName(), basicNameAttributeType.getDescriptor().getName().toString() ); + Assert.assertEquals( 1, nameBinding.getRelationalValueBindings().size() ); + Value nameValue = nameBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( nameValue instanceof Column ); + JdbcDataType nameDataType = nameValue.getJdbcDataType(); + assertSame( String.class, nameDataType.getJavaType() ); + assertSame( Types.VARCHAR, nameDataType.getTypeCode() ); + assertSame( StringType.INSTANCE.getName(), nameDataType.getTypeName() ); + } + + protected void assertRoot(MetadataImplementor metadata, EntityBinding entityBinding) { + assertTrue( entityBinding.isRoot() ); + assertSame( entityBinding, metadata.getRootEntityBinding( entityBinding.getEntityName() ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java new file mode 100644 index 000000000000..0c5828449100 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractUnsavedValueTests.java @@ -0,0 +1,209 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.sql.Timestamp; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; + +/** + * "Unsaved" value tests of {@code hbm.xml} and annotation binding code + * + * @author Gail Badner + */ +public abstract class AbstractUnsavedValueTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + protected ServiceRegistry basicServiceRegistry() { + return serviceRegistry; + } + + @Test + public void testAssignedSimpleIdDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForAssignedIdDefaultUnsavedValue( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() ); + // Generator is explicitly "assigned", so unsaved ID value should be "undefined" + assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testIncrementSimpleIdDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSequenceIdDefaultUnsavedValue( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() ); + // Generator is explicitly "increment", so unsaved ID value should be null + assertEquals( null, entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testDefaultUnsavedVersion() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForDefaultUnsavedVersion( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithVersion.class.getName() ); + // Generator is explicitly "assigned", so unsaved ID value should be "undefined" + assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testDefaultUnsavedTimestamp() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForDefaultUnsavedTimestamp( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithTimestamp.class.getName() ); + // Generator is explicitly "assigned", so unsaved ID value should be "undefined" + assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + public abstract void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources); + + public abstract void addSourcesForSequenceIdDefaultUnsavedValue(MetadataSources sources); + + public abstract void addSourcesForDefaultUnsavedVersion(MetadataSources sources); + + public abstract void addSourcesForDefaultUnsavedTimestamp(MetadataSources sources); + + @Entity + public static class EntityWithAssignedId { + @Id + private Long id; + + public EntityWithAssignedId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithSequenceId { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + + public EntityWithSequenceId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithVersion { + @Id + private Long id; + + @Version + private Integer version; + + public EntityWithVersion() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + } + + @Entity + public static class EntityWithTimestamp { + @Id + private Long id; + + @Version + @Temporal( value = TemporalType.TIMESTAMP ) + private Timestamp timestamp; + + public EntityWithTimestamp() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Timestamp getTimestamp() { + return timestamp; + } + + public void setTimestamp(Timestamp timestamp) { + this.timestamp = timestamp; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicAnnotationBindingTests.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicAnnotationBindingTests.java index 50d9a9068e8e..eef0449cc4c3 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicAnnotationBindingTests.java @@ -21,7 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; + +import org.junit.Test; import org.hibernate.metamodel.MetadataSources; @@ -31,6 +33,7 @@ * @author Hardy Ferentschik */ public class BasicAnnotationBindingTests extends AbstractBasicBindingTests { + @Override public void addSourcesForSimpleEntityBinding(MetadataSources sources) { sources.addAnnotatedClass( SimpleEntity.class ); @@ -43,7 +46,7 @@ public void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources) { @Override public void addSourcesForManyToOne(MetadataSources sources) { - sources.addAnnotatedClass( ManyToOneEntity.class ); + sources.addAnnotatedClass( EntityWithManyToOnes.class ); } @Override @@ -51,4 +54,9 @@ public void addSourcesForComponentBinding(MetadataSources sources) { sources.addAnnotatedClass( SimpleEntityWithSimpleComponent.class ); sources.addAnnotatedClass( SimpleEntityWithSimpleComponent.SimpleComponent.class ); } + + @Test + public void testEntityWithManyToOneMapping() { + super.testEntityWithManyToOneMapping( "simpleEntity_id"); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicHbmBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicHbmBindingTests.java new file mode 100644 index 000000000000..1440769cf036 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicHbmBindingTests.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; + +/** + * Basic tests of {@code hbm.xml} binding code + * + * @author Steve Ebersole + */ +public class BasicHbmBindingTests extends AbstractBasicBindingTests { + + @Override + public void addSourcesForSimpleEntityBinding(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml" ); + } + + @Override + public void addSourcesForSimpleVersionedEntityBinding(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml" ); + } + + @Override + public void addSourcesForManyToOne(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml" ); + } + + @Override + public void addSourcesForComponentBinding(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml" ); + } + + @Test + public void testEntityWithManyToOneMapping() { + super.testEntityWithManyToOneMapping( "simpleEntity" ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BindingHelper.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BindingHelper.java new file mode 100644 index 000000000000..006b7b5667a4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BindingHelper.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertNotNull; + +/** + * @author Steve Ebersole + */ +public class BindingHelper { + /** + * Help to get an attribute binding that we are fully expecting to exist. + *

    + * Helpful because it validates that the attribute exists and manages checking the + * specific type and casting. + * + * @param attributeContainer The container for the attribute + * @param attributeName The name of the attribute to get + * @param expectedType The specific AttributeBinding sub-type we are expecting + * @param The generic representation of `expectedType` + * + * @return The typed attribute binding + */ + public static T locateAttributeBinding( + AttributeBindingContainer attributeContainer, + String attributeName, + Class expectedType) { + AttributeBinding attributeBinding = attributeContainer.locateAttributeBinding( attributeName ); + assertNotNull( "Could not locate attribute named " + attributeName, attributeBinding ); + return assertTyping( expectedType, attributeBinding ); + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.java new file mode 100644 index 000000000000..99debcceba73 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.java @@ -0,0 +1,97 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +/** + * @author Gail Badner + */ +@Entity +public class EntityWithManyToOnes { + private Long id; + private String theName; + SimpleEntity simpleEntity; + SimpleEntity simpleEntityFromPropertyRef; + + public EntityWithManyToOnes() { + } + + public EntityWithManyToOnes(String name) { + this.theName = name; + } + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return theName; + } + + public void setName(String name) { + this.theName = name; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(nullable = false) + public SimpleEntity getSimpleEntity() { + return simpleEntity; + } + + public void setSimpleEntity(SimpleEntity simpleEntity) { + this.simpleEntity = simpleEntity; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "simplename", referencedColumnName = "name") + public SimpleEntity getSimpleEntityFromPropertyRef() { + return simpleEntityFromPropertyRef; + } + + public void setSimpleEntityFromPropertyRef(SimpleEntity simpleEntityFromPropertyRef) { + this.simpleEntityFromPropertyRef = simpleEntityFromPropertyRef; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "EntityWithManyToOnes" ); + sb.append( "{id=" ).append( id ); + sb.append( ", theName='" ).append( theName ).append( '\'' ); + sb.append( ", simpleEntity=" ).append( simpleEntity ); + sb.append( ", simpleEntityFromPropertyRef=" ).append( simpleEntityFromPropertyRef ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToMany.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToMany.java new file mode 100644 index 000000000000..fc75b9dac44f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToMany.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +/** + * @author Gail Badner + */ +@Entity +public class EntityWithUnidirectionalManyToMany { + private Long id; + private String name; + private Collection theBag = new ArrayList(); + private Set theSet = new HashSet(); + private Collection thePropertyRefBag = new ArrayList(); + + public EntityWithUnidirectionalManyToMany() { + } + + public EntityWithUnidirectionalManyToMany(String name) { + this.name = name; + } + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @ManyToMany + public Collection getTheBag() { + return theBag; + } + + public void setTheBag(Collection theBag) { + this.theBag = theBag; + } + + @ManyToMany + public Set getTheSet() { + return theSet; + } + + public void setTheSet(Set theSet) { + this.theSet = theSet; + } + + @ManyToMany + public Collection getThePropertyRefSet() { + return thePropertyRefBag; + } + + public void setThePropertyRefSet(Set thePropertyRefSet) { + this.thePropertyRefBag = thePropertyRefSet; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java new file mode 100644 index 000000000000..518ca094cd3c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/JoinedSubclassBindingTests.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public class JoinedSubclassBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + @Test + public void testJoinedSubclassBindingGeneratesForeignKey() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + sources.addAnnotatedClass( Sub.class ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + + EntityBinding entityBinding = metadata.getEntityBinding( Sub.class.getName() ); + assertTrue( entityBinding.getPrimaryTable().getForeignKeys().iterator().hasNext() ); + } + + @Entity + @Inheritance( strategy = InheritanceType.JOINED ) + public static class Base { + @Id + private Long id; + } + + @Entity + public static class Sub extends Base { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntity.java new file mode 100644 index 000000000000..8f987096f6eb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntity.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Steve Ebersole + */ +@Entity +public class SimpleEntity { + @Id + private Long id; + private String name; + + public SimpleEntity() { + } + + public SimpleEntity(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntitySubClass.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntitySubClass.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntitySubClass.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntitySubClass.java index 29c6c3149164..ba08f5b844c7 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntitySubClass.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntitySubClass.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.java index 1fb5ec985422..211eb48839d4 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Embeddable; import javax.persistence.Embedded; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java new file mode 100644 index 000000000000..7f94de27fe56 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import java.sql.Types; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.internal.ClassLoaderAccessImpl; +import org.hibernate.metamodel.reflite.internal.JavaTypeDescriptorRepositoryImpl; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository; +import org.hibernate.metamodel.source.internal.annotations.JandexAccessImpl; +import org.hibernate.metamodel.spi.NaturalIdMutability; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Size; +import org.hibernate.metamodel.spi.relational.Table; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertSame; + +/** + * Basic binding "smoke" tests + * + * @author Steve Ebersole + */ +public class SimpleValueBindingTests extends BaseUnitTestCase { + public static final JdbcDataType BIGINT = new JdbcDataType( Types.BIGINT, "BIGINT", Long.class ); + public static final JdbcDataType VARCHAR = new JdbcDataType( Types.VARCHAR, "VARCHAR", String.class ); + + private static final ClassLoaderService classLoaderService = new ClassLoaderServiceImpl(); + + + @Test + public void testBasicMiddleOutBuilding() { + final Identifier tableName = Identifier.toIdentifier( "the_table" ); + Table table = new Table( new Schema( null, null ), tableName, tableName ); + Column idColumn = table.locateOrCreateColumn( "id" ); + idColumn.setJdbcDataType( BIGINT ); + idColumn.setSize( Size.precision( 18, 0 ) ); + table.getPrimaryKey().addColumn( idColumn ); + table.getPrimaryKey().setName( Identifier.toIdentifier( "my_table_pk" ) ); + + Entity entity = new Entity( makeJavaType( "NoSuchClass" ), null ); + HierarchyDetails hierarchyDetails = new HierarchyDetails.Builder().createHierarchyDetails(); + EntityBinding entityBinding = hierarchyDetails.getRootEntityBinding(); + entityBinding.setEntity( entity ); + entityBinding.setPrimaryTable( table ); + + List valueBindings = new ArrayList(); + valueBindings.add( + new RelationalValueBinding( + table, + idColumn, + true, + true + ) + ); + SingularAttribute idAttribute = entity.createSingularAttribute( "id" ); + BasicAttributeBinding attributeBinding = entityBinding.makeBasicAttributeBinding( + idAttribute, + valueBindings, + "property", + true, + false, + NaturalIdMutability.NOT_NATURAL_ID, + null, + entityBinding.getRoleBase().append( "id" ), + entityBinding.getPathBase().append( "id" ), + PropertyGeneration.NEVER + ); + attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" ); + assertSame( idAttribute, attributeBinding.getAttribute() ); + + entityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier( + attributeBinding, + new IdentifierGeneratorDefinition( "assigned", "assigned", Collections.emptyMap() ), + "null", + null, + null + ); + } + + private final ClassLoaderAccessImpl classLoaderAccess = new ClassLoaderAccessImpl( null, classLoaderService ); + private final JavaTypeDescriptorRepository javaTypeDescriptorRepository = new JavaTypeDescriptorRepositoryImpl( + new JandexAccessImpl( null, classLoaderAccess ), + classLoaderAccess + ); + + JavaTypeDescriptor makeJavaType(final String name) { + return javaTypeDescriptorRepository.getType( javaTypeDescriptorRepository.buildName( name ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.java rename to hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.java index 2c7eacd515ab..4458bbb85c55 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.binding; +package org.hibernate.metamodel.spi.binding; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnidirectionalManyToManyBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnidirectionalManyToManyBindingTests.java new file mode 100644 index 000000000000..42ede4038ec9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnidirectionalManyToManyBindingTests.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSourceProcessingOrder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Gail Badner + */ +public class UnidirectionalManyToManyBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + +// @Test +// public void testAnnotations() { +// doTest( MetadataSourceProcessingOrder.ANNOTATIONS_FIRST ); +// } + + @Test + @TestForIssue( jiraKey = "HHH-7436" ) + public void testHbm() { + doTest( MetadataSourceProcessingOrder.HBM_FIRST ); + } + + private void doTest(MetadataSourceProcessingOrder processingOrder) { + MetadataSources sources = new MetadataSources( serviceRegistry ); + sources.addResource( "org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml" ); + MetadataImpl metadata = (MetadataImpl) sources.getMetadataBuilder().with( processingOrder ).build(); + + final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithUnidirectionalManyToMany.class.getName() ); + final EntityBinding simpleEntityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() ); + assertNotNull( entityBinding ); + + assertEquals( + Identifier.toIdentifier( "SimpleEntity" ), + simpleEntityBinding.getPrimaryTable().getLogicalName() + ); + assertEquals( 1, simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() ); + Column simpleEntityIdColumn = simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ); + assertEquals( Identifier.toIdentifier( "id" ) , simpleEntityIdColumn.getColumnName() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java new file mode 100644 index 000000000000..4f90171e4533 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueAnnotationsTests.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.MetadataSources; + +/** + * "Unsaved" value tests annotation binding code + * + * @author Gail Badner + */ +public class UnsavedValueAnnotationsTests extends AbstractUnsavedValueTests { + + public void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithAssignedId.class ); + } + + public void addSourcesForSequenceIdDefaultUnsavedValue(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithSequenceId.class ); + } + + public void addSourcesForDefaultUnsavedVersion(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithVersion.class ); + } + + public void addSourcesForDefaultUnsavedTimestamp(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithTimestamp.class ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java new file mode 100644 index 000000000000..7936275918ad --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/UnsavedValueHbmTests.java @@ -0,0 +1,108 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; + +import static org.junit.Assert.assertEquals; + +/** + * "Unsaved" value tests of {@code hbm.xml} binding code + * + * @author Gail Badner + */ +public class UnsavedValueHbmTests extends AbstractUnsavedValueTests { + + @Test + public void testAssignedSimpleIdNonDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() ); + // unsaved-value was mapped as "any"; that should be used, regardless of ID generator. + assertEquals( "any", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testIncrementSimpleIdNonDefaultUnsavedValue() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() ); + // unsaved-value was mapped as "null"; that should be used, regardless of ID generator. + assertEquals( "null", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() ); + } + + @Test + public void testNonDefaultUnsavedVersion() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithVersion.class.getName() ); + // version unsaved-value was mapped as "negative". + assertEquals( "negative", entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue() ); + } + + @Test + public void testNonDefaultUnsavedTimestamp() { + MetadataSources sources = new MetadataSources( basicServiceRegistry() ); + addNonDefaultSources( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithTimestamp.class.getName() ); + // version unsaved-value was mapped as "null". + assertEquals( "null", entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue() ); + } + + + public void addSourcesForDefaultSimpleIdDefaultUnsavedValue(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForSequenceIdDefaultUnsavedValue(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForDefaultUnsavedVersion(MetadataSources sources) { + addDefaultSources( sources ); + } + + public void addSourcesForDefaultUnsavedTimestamp(MetadataSources sources) { + addDefaultSources( sources ); + } + + private void addDefaultSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml" ); + } + + private void addNonDefaultSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml" ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java new file mode 100644 index 000000000000..f19d926c1a45 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AbstractBasicCollectionBindingTests.java @@ -0,0 +1,242 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.basiccollections; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.FetchTiming; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.type.BagType; +import org.hibernate.type.CollectionType; +import org.hibernate.type.SetType; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + private MetadataImpl metadata; + + @Before + public void setUp() { + serviceRegistry = ( StandardServiceRegistryImpl ) new StandardServiceRegistryBuilder().build(); + MetadataSources metadataSources = new MetadataSources( serviceRegistry ); + addSources( metadataSources ); + metadata = ( MetadataImpl ) metadataSources.getMetadataBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + public abstract void addSources(MetadataSources sources); + + @Test + public void testBasicCollections() { + final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithBasicCollections.class.getName() ); + final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier(); + assertNotNull( entityBinding ); + + // TODO: this will fail until HHH-7121 is fixed + //assertTrue( entityBinding.getPrimaryTable().locateColumn( "`name`" ).isUnique() ); + + assertBasicCollectionBinding( + entityBinding, + metadata.getCollection( EntityWithBasicCollections.class.getName() + "#theBag" ), + BagType.class, + Collection.class, + String.class, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "EntityWithBasicCollections_theBag" ), + Identifier.toIdentifier( "owner_id" ), + FetchTiming.IMMEDIATE, + true + ); + + assertBasicCollectionBinding( + entityBinding, + metadata.getCollection( EntityWithBasicCollections.class.getName() + "#theSet" ), + SetType.class, + Set.class, + String.class, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "EntityWithBasicCollections_theSet" ), + Identifier.toIdentifier( "pid" ), + FetchTiming.EXTRA_LAZY, + true + ); + + assertBasicCollectionBinding( + entityBinding, + metadata.getCollection( EntityWithBasicCollections.class.getName() + "#thePropertyRefSet" ), + SetType.class, + Set.class, + Integer.class, + ( SingularAttributeBinding ) entityBinding.locateAttributeBinding( "name" ), + Identifier.toIdentifier( "EntityWithBasicCollections_thePropertyRefSet" ), + Identifier.toIdentifier( "pid" ), + FetchTiming.DELAYED, + false + ); + } + + private void assertBasicCollectionBinding( + EntityBinding collectionOwnerBinding, + PluralAttributeBinding collectionBinding, + Class expectedCollectionTypeClass, + Class expectedCollectionJavaClass, + Class expectedElementJavaClass, + SingularAttributeBinding expectedKeyTargetAttributeBinding, + Identifier expectedCollectionTableName, + Identifier expectedKeySourceColumnName, + FetchTiming expectedFetchTiming, + boolean expectedElementNullable) { + assertNotNull( collectionBinding ); + assertSame( + collectionBinding, + collectionOwnerBinding.locateAttributeBinding( collectionBinding.getAttribute().getName() ) + ); + assertSame( collectionOwnerBinding, collectionBinding.getContainer().seekEntityBinding() ); + + TableSpecification collectionTable = collectionBinding.getPluralAttributeKeyBinding().getCollectionTable(); + assertNotNull( collectionTable ); + assertEquals( expectedCollectionTableName, collectionTable.getLogicalName() ); + PluralAttributeKeyBinding keyBinding = collectionBinding.getPluralAttributeKeyBinding(); + assertSame( collectionBinding, keyBinding.getPluralAttributeBinding() ); + HibernateTypeDescriptor collectionHibernateTypeDescriptor = collectionBinding.getHibernateTypeDescriptor(); + assertNull( collectionHibernateTypeDescriptor.getExplicitTypeName() ); + assertEquals( + expectedCollectionJavaClass.getName(), + collectionHibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString() + ); + assertTrue( collectionHibernateTypeDescriptor.getTypeParameters().isEmpty() ); + assertTrue( expectedCollectionTypeClass.isInstance( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ) ); + assertFalse( collectionHibernateTypeDescriptor.getResolvedTypeMapping().isComponentType() ); + final String role = collectionBinding.getAttribute().getRole(); + assertEquals( + role, + collectionOwnerBinding.getEntityName() + "." + collectionBinding.getAttribute().getName() + ); + assertEquals( + role, + expectedCollectionTypeClass.cast( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ).getRole() + ); + + assertEquals( expectedFetchTiming, collectionBinding.getFetchTiming() ); + assertEquals( expectedFetchTiming != FetchTiming.IMMEDIATE, collectionBinding.isLazy() ); + + List keyRelationalValueBindings = keyBinding.getRelationalValueBindings(); + assertNotNull( keyRelationalValueBindings ); + for( RelationalValueBinding keyRelationalValueBinding : keyRelationalValueBindings ) { + assertSame( collectionTable, keyRelationalValueBinding.getTable() ); + } + assertEquals( 1, keyRelationalValueBindings.size() ); + assertEquals( 1, expectedKeyTargetAttributeBinding.getRelationalValueBindings().size() ); + Value expectedFKTargetValue = expectedKeyTargetAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertFalse( keyRelationalValueBindings.get( 0 ).isDerived() ); + assertEquals( expectedKeySourceColumnName, ( (Column) keyRelationalValueBindings.get( 0 ).getValue() ).getColumnName() ); + assertEquals( expectedFKTargetValue.getJdbcDataType(), keyRelationalValueBindings.get( 0 ).getValue().getJdbcDataType() ); + + assertFalse( keyBinding.isCascadeDeleteEnabled() ); + checkEquals( + expectedKeyTargetAttributeBinding.getHibernateTypeDescriptor(), + keyBinding.getHibernateTypeDescriptor() + ); + assertFalse( keyBinding.isInverse() ); + Assert.assertEquals( + PluralAttributeElementNature.BASIC, + collectionBinding.getPluralAttributeElementBinding().getNature() + ); + assertEquals( + expectedElementJavaClass.getName(), + collectionBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeDescriptor().getName().toString() + ); + assertEquals( + expectedElementJavaClass, + collectionBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getResolvedTypeMapping().getReturnedClass() + + ); + assertEquals( 1, + collectionBinding.getPluralAttributeElementBinding() + .getRelationalValueContainer() + .relationalValueBindings() + .size() + ); + RelationalValueBinding elementRelationalValueBinding = collectionBinding.getPluralAttributeElementBinding().getRelationalValueContainer().relationalValueBindings().get( 0 ); + assertEquals( expectedElementNullable, elementRelationalValueBinding.isNullable() ); + if ( collectionBinding.getAttribute().getPluralAttributeNature() == PluralAttributeNature.BAG ) { + assertEquals( 0, collectionTable.getPrimaryKey().getColumnSpan() ); + } + else if ( collectionBinding.getAttribute().getPluralAttributeNature() == PluralAttributeNature.SET ) { + if ( expectedElementNullable ) { + assertEquals( 0, collectionTable.getPrimaryKey().getColumnSpan() ); + } + else { + assertEquals( 2, collectionTable.getPrimaryKey().getColumnSpan() ); + assertSame( keyRelationalValueBindings.get( 0 ).getValue(), collectionTable.getPrimaryKey().getColumns().get( 0 ) ); + assertSame( elementRelationalValueBinding.getValue(), collectionTable.getPrimaryKey().getColumns().get( 1 ) ); + } + } + } + + private void checkEquals(HibernateTypeDescriptor expected, HibernateTypeDescriptor actual) { + assertEquals( expected.getExplicitTypeName(), actual.getExplicitTypeName() ); + assertEquals( expected.getJavaTypeDescriptor(), actual.getJavaTypeDescriptor() ); + assertEquals( expected.getTypeParameters(), actual.getTypeParameters() ); + assertEquals( expected.getResolvedTypeMapping(), actual.getResolvedTypeMapping() ); + assertEquals( expected.isToOne(), actual.isToOne() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java new file mode 100644 index 000000000000..30566b601cdb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/AnnotationBasicCollectionBindingTests.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.basiccollections; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; + +/** + * @author Hardy Ferentschik + */ +public class AnnotationBasicCollectionBindingTests extends AbstractBasicCollectionBindingTests { + public void addSources(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithBasicCollections.class ); + } + + @Test + public void testBasicCollections() { + super.testBasicCollections(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java new file mode 100644 index 000000000000..f38415242961 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.basiccollections; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; + +/** + * @author Gail Badner + * @author Steve Ebersole + */ +@Entity +public class EntityWithBasicCollections { + private Long id; + private String name; + private Collection theBag = new ArrayList(); + private Set theSet = new HashSet(); + private Set thePropertyRefSet = new HashSet(); + private List theList = new ArrayList(); + private Map theMap = new HashMap(); + + public EntityWithBasicCollections() { + } + + public EntityWithBasicCollections(String name) { + this.name = name; + } + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Column(unique = true) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @ElementCollection(fetch = FetchType.EAGER) + @JoinColumn(name = "owner_id") + public Collection getTheBag() { + return theBag; + } + + public void setTheBag(Collection theBag) { + this.theBag = theBag; + } + + @ElementCollection + @LazyCollection(value = LazyCollectionOption.EXTRA) + @JoinColumn(name = "pid") + public Set getTheSet() { + return theSet; + } + + public void setTheSet(Set theSet) { + this.theSet = theSet; + } + + @ElementCollection + @JoinColumn(name = "pid", referencedColumnName = "name") + @Column(name="property_ref_set_stuff", nullable = false) + public Set getThePropertyRefSet() { + return thePropertyRefSet; + } + + public void setThePropertyRefSet(Set thePropertyRefSet) { + this.thePropertyRefSet = thePropertyRefSet; + } + + @ElementCollection + public List getTheList() { + return theList; + } + + public void setTheList(List theList) { + this.theList = theList; + } + + @ElementCollection + public Map getTheMap() { + return theMap; + } + + public void setTheMap(Map theMap) { + this.theMap = theMap; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java new file mode 100644 index 000000000000..2dd51780b28c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/basiccollections/HbmBasicCollectionBindingTests.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.basiccollections; + +import org.hibernate.metamodel.MetadataSources; + +/** + * @author Hardy Ferentschik + */ +public class HbmBasicCollectionBindingTests extends AbstractBasicCollectionBindingTests { + public void addSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml" ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/cid/BasicEmbeddedIdTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/cid/BasicEmbeddedIdTest.java new file mode 100644 index 000000000000..d5865daabdf2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/cid/BasicEmbeddedIdTest.java @@ -0,0 +1,132 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.cid; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; + +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static org.hibernate.metamodel.spi.binding.BindingHelper.locateAttributeBinding; +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +/** + * Assertions about the metamodel interpretations of basic {@link javax.persistence.EmbeddedId} usage. + * + * @author Steve Ebersole + * + * @see org.hibernate.metamodel.spi.binding.cid.BasicIdClassTest + */ +public class BasicEmbeddedIdTest extends BaseAnnotationBindingTestCase { + @Embeddable + public static class CoursePK { + @Column( name = "dept" ) + public String department; + public String code; + } + + @Entity + public static class Course { + @EmbeddedId + private CoursePK key; + private String title; + } + + @Test + @Resources( annotatedClasses = {CoursePK.class, Course.class} ) + public void testBasicUsage() { + // get the Course entity binding + EntityBinding courseBinding = getEntityBinding( Course.class ); + assertNotNull( courseBinding ); + assertEquals( + EntityIdentifierNature.AGGREGATED_COMPOSITE, + courseBinding.getHierarchyDetails().getEntityIdentifier().getNature() + ); + assertNull( + courseBinding.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().getIdClassType() + ); + + // Course should be interpreted as defining 2 attributes: `key` and `title` + assertEquals( 2, courseBinding.getAttributeBindingClosureSpan() ); + + // just make sure `title` is one of them + locateAttributeBinding( courseBinding, "title", BasicAttributeBinding.class ); + + // locate the attribute binding for `key` which is the EmbeddedId attribute + EmbeddedAttributeBinding keyBinding = locateAttributeBinding( + courseBinding, + "key", + EmbeddedAttributeBinding.class + ); + SingularAttributeBinding identifierAttribute = courseBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + // NOTE : assertSame() does '==' + assertSame( keyBinding, identifierAttribute ); + + // the Embeddable for `key` (CoursePK) should also define 2 attributes: `department` and `code` + assertEquals( 2, keyBinding.getEmbeddableBinding().attributeBindingSpan() ); + + BasicAttributeBinding deptAttribute = locateAttributeBinding( + keyBinding.getEmbeddableBinding(), + "department", + BasicAttributeBinding.class + ); + assertEquals( 1, deptAttribute.getRelationalValueBindings().size() ); + RelationalValueBinding deptColumnBinding = deptAttribute.getRelationalValueBindings().get( 0 ); + org.hibernate.metamodel.spi.relational.Column deptColumn = assertTyping( + org.hibernate.metamodel.spi.relational.Column.class, + deptColumnBinding.getValue() + ); + assertEquals( "dept", deptColumn.getColumnName().getText() ); + + BasicAttributeBinding codeAttribute = locateAttributeBinding( + keyBinding.getEmbeddableBinding(), + "code", + BasicAttributeBinding.class + ); + assertEquals( 1, codeAttribute.getRelationalValueBindings().size() ); + RelationalValueBinding codeColumnBinding = codeAttribute.getRelationalValueBindings().get( 0 ); + org.hibernate.metamodel.spi.relational.Column codeColumn = assertTyping( + org.hibernate.metamodel.spi.relational.Column.class, + codeColumnBinding.getValue() + ); + assertEquals( "code", codeColumn.getColumnName().getText() ); + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/cid/BasicIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/cid/BasicIdClassTest.java new file mode 100644 index 000000000000..664871d339a3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/cid/BasicIdClassTest.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.cid; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; + +import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase; +import org.hibernate.testing.junit4.Resources; +import org.junit.Test; + +import static org.hibernate.metamodel.spi.binding.BindingHelper.locateAttributeBinding; +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Assertions about the metamodel interpretations of basic {@link javax.persistence.IdClass} usage. + * + * @author Steve Ebersole + * + * @see org.hibernate.metamodel.spi.binding.cid.BasicEmbeddedIdTest + */ +public class BasicIdClassTest extends BaseAnnotationBindingTestCase { + public static class CoursePK { + public String department; + public String code; + } + + @Entity + @IdClass( CoursePK.class ) + public static class Course { + @Id + @Column( name = "dept" ) + public String department; + @Id + public String code; + private String title; + } + + @Test + @Resources( annotatedClasses = Course.class ) + public void testBasicUsage() { + // get the Course entity binding + EntityBinding courseBinding = getEntityBinding( Course.class ); + assertNotNull( courseBinding ); + assertEquals( + EntityIdentifierNature.NON_AGGREGATED_COMPOSITE, + courseBinding.getHierarchyDetails().getEntityIdentifier().getNature() + ); + Class idClassClass = courseBinding.getHierarchyDetails().getEntityIdentifier() + .getLookupClassBinding() + .getIdClassType(); + assertNotNull( idClassClass ); + + // Course should be interpreted as defining 3 attributes: `department`, `code` and `title` + assertEquals( 3, courseBinding.getAttributeBindingClosureSpan() ); + + // just make sure `title` is one of them + locateAttributeBinding( courseBinding, "title", BasicAttributeBinding.class ); + + BasicAttributeBinding deptAttribute = locateAttributeBinding( + courseBinding, + "department", + BasicAttributeBinding.class + ); + assertEquals( 1, deptAttribute.getRelationalValueBindings().size() ); + RelationalValueBinding deptColumnBinding = deptAttribute.getRelationalValueBindings().get( 0 ); + org.hibernate.metamodel.spi.relational.Column deptColumn = assertTyping( + org.hibernate.metamodel.spi.relational.Column.class, + deptColumnBinding.getValue() + ); + assertEquals( "dept", deptColumn.getColumnName().getText() ); + + BasicAttributeBinding codeAttribute = locateAttributeBinding( + courseBinding, + "code", + BasicAttributeBinding.class + ); + RelationalValueBinding codeColumnBinding = codeAttribute.getRelationalValueBindings().get( 0 ); + org.hibernate.metamodel.spi.relational.Column codeColumn = assertTyping( + org.hibernate.metamodel.spi.relational.Column.class, + codeColumnBinding.getValue() + ); + assertEquals( "code", codeColumn.getColumnName().getText() ); + + + assertTrue( + courseBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( + deptAttribute + ) + ); + + assertTrue( + courseBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( + codeAttribute + ) + ); + + // get the virtual (non-aggregated composite) id attribute + EmbeddedAttributeBinding identifierAttribute = (EmbeddedAttributeBinding) courseBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding(); + assertNotNull( identifierAttribute ); + // NOTE : assertSame() does `==` + + EmbeddableBinding virtualEmbeddable = identifierAttribute.getEmbeddableBinding(); + assertEquals( 2, virtualEmbeddable.attributeBindingSpan() ); + + for ( AttributeBinding subAttributeBinding : virtualEmbeddable.attributeBindings() ) { + assertTrue( + subAttributeBinding == deptAttribute + || subAttributeBinding == codeAttribute + ); + } + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java new file mode 100644 index 000000000000..2166b83d4d43 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AbstractUnidirectionalOneToManyBindingTests.java @@ -0,0 +1,261 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.FetchTiming; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.type.BagType; +import org.hibernate.type.CollectionType; +import org.hibernate.type.ListType; +import org.hibernate.type.MapType; +import org.hibernate.type.SetType; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * @author Gail Badner + */ +public abstract class AbstractUnidirectionalOneToManyBindingTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + private MetadataImpl metadata; + + @Before + public void setUp() { + serviceRegistry = ( StandardServiceRegistryImpl ) new StandardServiceRegistryBuilder().build(); + MetadataSources metadataSources = new MetadataSources( serviceRegistry ); + addSources( metadataSources ); + metadata = ( MetadataImpl ) metadataSources.getMetadataBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + public abstract void addSources(MetadataSources sources); + + @Test + public void testOneToMany() { + final EntityBinding entityBinding = metadata.getEntityBinding( EntityWithUnidirectionalOneToMany.class.getName() ); + final EntityBinding simpleEntityBinding = metadata.getEntityBinding( ReferencedEntity.class.getName() ); + assertNotNull( entityBinding ); + + assertEquals( + Identifier.toIdentifier( "ReferencedEntity" ), + simpleEntityBinding.getPrimaryTable().getLogicalName() + ); + assertEquals( 1, simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumnSpan() ); + Column simpleEntityIdColumn = simpleEntityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ); + assertEquals( Identifier.toIdentifier( "id" ), simpleEntityIdColumn.getColumnName() ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + "#theBag" ), + BagType.class, + Collection.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theBagOwner" ), + FetchTiming.DELAYED, + true + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + "#theSet" ), + SetType.class, + Set.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theSetOwner" ), + FetchTiming.IMMEDIATE, + false + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + "#theList" ), + ListType.class, + List.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theListOwner" ), + FetchTiming.IMMEDIATE, + false + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + "#theMap" ), + MapType.class, + Map.class, + simpleEntityBinding, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), + Identifier.toIdentifier( "theMapOwner" ), + FetchTiming.DELAYED, + false + ); + + checkResult( + entityBinding, + metadata.getCollection( EntityWithUnidirectionalOneToMany.class.getName() + "#thePropertyRefSet" ), + BagType.class, + Collection.class, + simpleEntityBinding, + ( SingularAttributeBinding ) entityBinding.locateAttributeBinding( "name" ), + Identifier.toIdentifier( "ownerName" ), + FetchTiming.EXTRA_LAZY, + false + ); + } + + private void checkResult( + EntityBinding collectionOwnerBinding, + PluralAttributeBinding collectionBinding, + Class expectedCollectionTypeClass, + Class expectedCollectionJavaType, + EntityBinding expectedElementEntityBinding, + SingularAttributeBinding expectedKeyTargetAttributeBinding, + Identifier expectedKeySourceColumnName, + FetchTiming expectedFetchTiming, + boolean expectedNullableCollectionKey) { + Assert.assertEquals( + PluralAttributeElementNature.ONE_TO_MANY, + collectionBinding.getPluralAttributeElementBinding().getNature() + ); + assertSame( + collectionBinding, + collectionOwnerBinding.locateAttributeBinding( collectionBinding.getAttribute().getName() ) + ); + assertEquals( expectedFetchTiming, collectionBinding.getFetchTiming() ); + assertEquals( expectedFetchTiming != FetchTiming.IMMEDIATE, collectionBinding.isLazy() ); + + final String role = collectionBinding.getAttribute().getRole(); + assertEquals( + role, + collectionOwnerBinding.getEntityName() + "." + collectionBinding.getAttribute().getName() + ); + + final PluralAttributeKeyBinding keyBinding = collectionBinding.getPluralAttributeKeyBinding(); + assertSame( expectedElementEntityBinding.getPrimaryTable(), keyBinding.getCollectionTable() ); + assertSame( collectionBinding, keyBinding.getPluralAttributeBinding() ); + assertFalse( keyBinding.isInverse() ); + + final HibernateTypeDescriptor collectionHibernateTypeDescriptor = collectionBinding.getHibernateTypeDescriptor(); + assertNull( collectionHibernateTypeDescriptor.getExplicitTypeName() ); + assertEquals( expectedCollectionJavaType.getName(), + collectionHibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString() + ); + assertEquals( + expectedCollectionJavaType.getName(), + collectionHibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString() + ); + assertTrue( collectionHibernateTypeDescriptor.getTypeParameters().isEmpty() ); + assertTrue( expectedCollectionTypeClass.isInstance( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ) ); + assertFalse( collectionHibernateTypeDescriptor.getResolvedTypeMapping().isComponentType() ); + assertEquals( + role, + expectedCollectionTypeClass.cast( collectionHibernateTypeDescriptor.getResolvedTypeMapping() ).getRole() + ); + + List keyRelationalValueBinding = keyBinding.getRelationalValueBindings(); + assertNotNull( keyRelationalValueBinding ); + assertFalse( keyBinding.isCascadeDeleteEnabled() ); + + assertSame( expectedElementEntityBinding.getPrimaryTable(), keyBinding.getCollectionTable() ); + assertEquals( 1, keyRelationalValueBinding.size() ); + + SingularAttributeBinding keySourceAttributeBinding = + ( SingularAttributeBinding ) expectedElementEntityBinding.locateAttributeBinding( + "_" + role + "BackRef" + ); + assertEquals( "expected "+keyBinding.getPluralAttributeBinding() +" has a " + expectedNullableCollectionKey +" collection key",expectedNullableCollectionKey, keyBinding.isNullable() ); + if ( keyBinding.isNullable() ) { + assertNull( keySourceAttributeBinding ); + } + else { + assertEquals( 1, keySourceAttributeBinding.getRelationalValueBindings().size() ); + Value keySourceValue = keySourceAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( keySourceValue instanceof Column ); + Column keySourceColumn = ( Column ) keySourceValue; + assertEquals( expectedKeySourceColumnName, keySourceColumn.getColumnName() ); + } + + assertEquals( 1, expectedKeyTargetAttributeBinding.getRelationalValueBindings().size() ); + assertEquals( + expectedKeyTargetAttributeBinding.getRelationalValueBindings().get( 0 ).getValue().getJdbcDataType(), + keyRelationalValueBinding.get( 0 ).getValue().getJdbcDataType() + ); + + checkEquals( + expectedKeyTargetAttributeBinding.getHibernateTypeDescriptor(), + keyBinding.getHibernateTypeDescriptor() + ); + + assertEquals( + expectedElementEntityBinding.getEntityName(), + collectionBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeDescriptor().getName().toString() + ); + } + + private void checkEquals(HibernateTypeDescriptor expected, HibernateTypeDescriptor actual) { + assertEquals( expected.getExplicitTypeName(), actual.getExplicitTypeName() ); + assertEquals( + expected.getJavaTypeDescriptor().getName(), + actual.getJavaTypeDescriptor().getName() + ); + assertEquals( expected.getTypeParameters(), actual.getTypeParameters() ); + assertEquals( expected.getResolvedTypeMapping(), actual.getResolvedTypeMapping() ); + assertEquals( expected.isToOne(), actual.isToOne() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java new file mode 100644 index 000000000000..173c2694c263 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/AnnotationUnidirectionalOneToManyBindingTests.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import org.hibernate.metamodel.MetadataSources; + +/** + * @author Hardy Ferentschik + */ +public class AnnotationUnidirectionalOneToManyBindingTests extends AbstractUnidirectionalOneToManyBindingTests { + @Override + public void addSources(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithUnidirectionalOneToMany.class ); + sources.addAnnotatedClass( ReferencedEntity.class ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java new file mode 100644 index 000000000000..c0c5cecc71bd --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.java @@ -0,0 +1,106 @@ +package org.hibernate.metamodel.spi.binding.onetomany; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +/** + * @author Gail Badner + */ +@Entity +public class EntityWithUnidirectionalOneToMany { + private Long id; + private String name; + + private Collection theBag = new ArrayList(); + private Set theSet = new HashSet(); + private List theList = new ArrayList(); + private Map theMap = new HashMap(); + private Collection thePropertyRefBag = new ArrayList(); + + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @OneToMany + @JoinColumn + public Collection getTheBag() { + return theBag; + } + + public void setTheBag(Collection theBag) { + this.theBag = theBag; + } + + @OneToMany(fetch = FetchType.EAGER) + @JoinColumn(name = "theSetOwner", nullable = false) + public Set getTheSet() { + return theSet; + } + + public void setTheSet(Set theSet) { + this.theSet = theSet; + } + + @OneToMany(fetch = FetchType.EAGER) + @JoinColumn(name = "theListOwner", nullable = false) + @OrderColumn( name = "list_index") + public List getTheList() { + return theList; + } + + public void setTheList(List theList) { + this.theList = theList; + } + + @OneToMany + @JoinColumn(name = "theMapOwner", nullable = false) + public Map getTheMap() { + return theMap; + } + + public void setTheMap(Map theMap) { + this.theMap = theMap; + } + + @OneToMany + @JoinColumn(name = "ownerName", nullable = false, referencedColumnName = "name") + @LazyCollection( LazyCollectionOption.EXTRA ) + public Collection getThePropertyRefSet() { + return thePropertyRefBag; + } + + public void setThePropertyRefSet(Set thePropertyRefSet) { + this.thePropertyRefBag = thePropertyRefSet; + } + +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java new file mode 100644 index 000000000000..f723da3fec4e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/HbmUnidirectionalOneToManyBindingTests.java @@ -0,0 +1,37 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import org.hibernate.metamodel.MetadataSources; + +/** + * @author Hardy Ferentschik + */ +public class HbmUnidirectionalOneToManyBindingTests extends AbstractUnidirectionalOneToManyBindingTests { + @Override + public void addSources(MetadataSources sources) { + sources.addResource( "org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml" ); + sources.addResource( "org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml" ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java new file mode 100644 index 000000000000..9b57369e4a0b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding.onetomany; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Hardy Ferentschik + */ +@Entity +public class ReferencedEntity { + @Id + private Long id; + private String name; + + public ReferencedEntity() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java new file mode 100644 index 000000000000..bfc294ca736f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/package-info.java @@ -0,0 +1,4 @@ +@GenericGenerator(name = "myGenerator", strategy = "sequence") +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.annotations.GenericGenerator; \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java new file mode 100644 index 000000000000..f1f2548f93ea --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/AbstractGeneratedIdColumnTests.java @@ -0,0 +1,187 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; + +/** + * Identity column tests of {@code hbm.xml} and annotation binding code + * + * @author Gail Badner + */ +public abstract class AbstractGeneratedIdColumnTests extends BaseUnitTestCase { + private StandardServiceRegistryImpl serviceRegistry; + + @Before + public void setUp() { + serviceRegistry = (StandardServiceRegistryImpl) new StandardServiceRegistryBuilder().build(); + } + + @After + public void tearDown() { + serviceRegistry.destroy(); + } + + protected ServiceRegistry basicServiceRegistry() { + return serviceRegistry; + } + + @Test + public void testNativeId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForNativeId( sources ); + // use old identifier generators so that strategy=GenerationType.AUTO maps to "native" ID generator + sources.getMetadataBuilder().withNewIdentifierGeneratorsEnabled( false ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithNativeId.class.getName() ); + assertEquals( + serviceRegistry.getService( JdbcServices.class ).getDialect().supportsIdentityColumns(), + entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() + ); + } + + @Test + public void testSequenceId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForSequenceId( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() ); + assertEquals( false, entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() ); + } + + @Test + public void testIdentityId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForIdentityId( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithIdentityId.class.getName() ); + assertEquals( true, entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() ); + } + + @Test + public void testAssignedId() { + MetadataSources sources = new MetadataSources( serviceRegistry ); + addSourcesForAssignedId( sources ); + MetadataImpl metadata = (MetadataImpl) sources.buildMetadata(); + EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() ); + assertEquals( false, entityBinding.getPrimaryTable().getPrimaryKey().getColumns().get( 0 ).isIdentity() ); + } + + public abstract void addSourcesForNativeId(MetadataSources sources); + + public abstract void addSourcesForSequenceId(MetadataSources sources); + + public abstract void addSourcesForIdentityId(MetadataSources sources); + + public abstract void addSourcesForAssignedId(MetadataSources sources); + + @Entity + public static class EntityWithNativeId { + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + private Long id; + + public EntityWithNativeId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithSequenceId { + @Id + @GeneratedValue(strategy=GenerationType.SEQUENCE) + private Long id; + + public EntityWithSequenceId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithIdentityId { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + public EntityWithIdentityId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + public static class EntityWithAssignedId { + @Id + private Long id; + + public EntityWithAssignedId() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java new file mode 100644 index 000000000000..af36f0273e9b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ColumnAliasTest.java @@ -0,0 +1,278 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.hibernate.dialect.Dialect; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * + * NOTE: the table number is automatically statically incremented every time + * a table is created. Because of this, it is impossible to predict how + * large the table number can get when running the suite of unit tests. + * Since we don't know how large the table number is, we don't know how + * many characters to allot in the resulting alias for the table number. + * + * To workaround this unknown, Dialect instances are created + * to control whether the test will need to truncate the column + * name when creating the alias. + * + * @author Gail Badner + */ +public class ColumnAliasTest extends BaseUnitTestCase { + + private Schema schema; + private Table table0; + private Table table1; + + @Before + public void setUp() { + schema = new Schema( null, null ); + table0 = new Table( + schema, + Identifier.toIdentifier( "table0" ), + Identifier.toIdentifier( "table0" ) + ); + table1 = new Table( + schema, + Identifier.toIdentifier( "table1" ), + Identifier.toIdentifier( "table1" ) + ); + } + + @After + public void tearDown() { + schema = null; + table0 = null; + table1 = null; + } + + @Test + public void testNoCharactersInNameNoTruncation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "1" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`1`" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + public void testNameStartsWithNonCharacterNoTruncation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "1abc" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "1abc`" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "_abc" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`_abc`" ); + assertEquals( "column" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + @Test + public void testNameStartsWithNonCharacterTruncation() { + Column column = table0.createColumn( "1" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + // create dialect with maximum alias length that will force truncation. + Dialect dialect = createDialect( expectedSuffix.length() + "column".length() - 1 ); + String nameTruncated = "column".substring( 0, dialect.getMaxAliasLength() - expectedSuffix.length() ); + assertTrue( nameTruncated.length() < "column".length() ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix , alias ); + } + + @Test + public void testNameIncludingNonCharacter() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 10 ); + + Column column = table0.createColumn( "a1" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + column = table0.createColumn( "`a1`" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "a1b" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`a1b`" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "ab1" ); + assertEquals( "ab" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`ab1`" ); + assertEquals( "ab" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "a1b2" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`a1b2`" ); + assertEquals( "a" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + @Test + public void testUseNameAsIs() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "abc" ); + assertEquals( "abc" + getExpectedSuffix( column, table1 ) , column.getAlias( dialect, table1 ) ); + } + + @Test + public void testUseNameAsIsWithMaxLength() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 10 ); + String name = "abcdef"; + Column column = table0.createColumn( name ); + assertEquals( name + getExpectedSuffix( column, table0 ) , column.getAlias( dialect, table0 ) ); + } + + @Test + public void testQuotedNameAllCharactersNoTrucation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 10 ); + + String name = "`abc`"; + Column column = table0.createColumn( name ); + assertEquals( column.getColumnName().getText() + getExpectedSuffix( column, table0 ), column.getAlias( + dialect, + table0 + ) ); + assertEquals( column.getColumnName().getText() + getExpectedSuffix( column, table1 ), column.getAlias( dialect, table1 ) ); + } + + @Test + public void testRowIdNameNoTruncation() { + // create dialect with a large enough max alias length so there is no trucation. + final Dialect dialect = createDialect( 25 ); + + Column column = table0.createColumn( "RowId" ); + assertEquals( "RowId" + getExpectedSuffix( column, table1 ), column.getAlias( dialect, table1 ) ); + + column = table0.createColumn( "`rowid`" ); + assertEquals( "rowid" + getExpectedSuffix( column, table1 ), column.getAlias( dialect, table1 ) ); + } + + @Test + public void testRowIdNameTruncation() { + Column column = table0.createColumn( "RowId" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + Dialect dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + String nameTruncated = "RowId".substring( 0, dialect.getMaxAliasLength() - expectedSuffix.length() ); + assertTrue( nameTruncated.length() < "RowId".length() ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + + expectedSuffix = getExpectedSuffix( column, table1 ); + dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + nameTruncated = "RowId".substring( 0, dialect.getMaxAliasLength() - expectedSuffix.length() ); + assertTrue( nameTruncated.length() < "column".length() ); + alias = column.getAlias( dialect, table1 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix , alias ); + } + + @Test + public void testTruncatedName() { + Column column = table0.createColumn( "abcdefghijk" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + // Force max alias length to be less than the column name to that + // the name is not used as is (and the expected suffix will be used). + Dialect dialect = createDialect( column.getColumnName().getText().length() - 1 ); + + String nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + + expectedSuffix = getExpectedSuffix( column, table1 ); + dialect = createDialect( column.getColumnName().getText().length() - 1 ); + nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + alias = column.getAlias( dialect, table1 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + } + + @Test + public void testTruncatedQuotedName() { + Column column = table0.createColumn( "`abcdefghijk`" ); + String expectedSuffix = getExpectedSuffix( column, table0 ); + Dialect dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + String nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + String alias = column.getAlias( dialect, table0 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + + expectedSuffix = getExpectedSuffix( column, table1 ); + dialect = createDialect( column.getColumnName().getText().length() + expectedSuffix.length() - 1 ); + nameTruncated = + column.getColumnName().getText().substring( + 0, + dialect.getMaxAliasLength() - expectedSuffix.length() + ); + alias = column.getAlias( dialect, table1 ); + assertEquals( dialect.getMaxAliasLength(), alias.length() ); + assertEquals( nameTruncated + expectedSuffix, alias ); + } + + private Dialect createDialect(final int maxAliasLength) { + return new Dialect() { + public int getMaxAliasLength() { + return maxAliasLength; + } + }; + } + + private String getExpectedSuffix(Column column, TableSpecification table) { + return String.valueOf( column.getPosition() ) + "_" + String.valueOf( table.getTableNumber() ) + "_" ; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java new file mode 100644 index 000000000000..e429eaad26e9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnAnnotationsTests.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.junit.Test; + +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.testing.FailureExpected; + +/** + * Identity column tests of annotations binding code + * + * @author Gail Badner + */ +public class GeneratedIdColumnAnnotationsTests extends AbstractGeneratedIdColumnTests { + + @Test + @FailureExpected( jiraKey = "HHH-7400" ) + public void testNativeId() { + super.testNativeId(); + } + + @Override + public void addSourcesForNativeId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithAssignedId.class ); + } + + @Override + public void addSourcesForSequenceId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithSequenceId.class ); + } + + @Override + public void addSourcesForIdentityId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithIdentityId.class ); + } + + @Override + public void addSourcesForAssignedId(MetadataSources sources) { + sources.addAnnotatedClass( EntityWithAssignedId.class ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java new file mode 100644 index 000000000000..bc40092d6f60 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/GeneratedIdColumnHbmTests.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.hibernate.metamodel.MetadataSources; + +/** + * Identity column tests of {@code hbm.xml} binding code + * + * @author Gail Badner + */ +public class GeneratedIdColumnHbmTests extends AbstractGeneratedIdColumnTests { + private static String FILENAME = "org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml"; + + @Override + public void addSourcesForNativeId(MetadataSources sources) { + sources.addResource( FILENAME ); + } + + @Override + public void addSourcesForSequenceId(MetadataSources sources) { + sources.addResource( FILENAME ); + } + + @Override + public void addSourcesForIdentityId(MetadataSources sources) { + sources.addResource( FILENAME ); + } + + @Override + public void addSourcesForAssignedId(MetadataSources sources) { + sources.addResource( FILENAME ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ObjectNameTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ObjectNameTests.java new file mode 100644 index 000000000000..145d7e4f7b11 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/ObjectNameTests.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import org.junit.Test; + +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Steve Ebersole + */ +public class ObjectNameTests extends BaseUnitTestCase { + @Test + public void testMissingName() { + try { + new ObjectName( null, (String)null, null ); + fail(); + } + catch ( IllegalIdentifierException ignore ) { + } + + try { + new ObjectName( "catalog", "schema", null ); + fail(); + } + catch ( IllegalIdentifierException ignore ) { + } + } + + @Test + public void testIdentifierBuilding() { + Dialect dialect = new H2Dialect(); + ObjectName on = new ObjectName( "catalog", "schema", "name" ); + assertEquals( "catalog.schema.name", on.toText() ); + on = new ObjectName( null, "schema", "name" ); + assertEquals( "schema.name", on.toText() ); + assertEquals( "schema.name", on.toText( dialect ) ); + on = new ObjectName( "`catalog`", "`schema`", "`name`" ); + assertEquals( "`catalog`.`schema`.`name`", on.toText() ); + assertEquals( "\"catalog\".\"schema\".\"name\"", on.toText( dialect ) ); + on = new ObjectName( null, "`schema`", "`name`" ); + assertEquals( "`schema`.`name`", on.toText() ); + assertEquals( "\"schema\".\"name\"", on.toText( dialect ) ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java new file mode 100644 index 000000000000..87594d636181 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java @@ -0,0 +1,178 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.relational; + +import java.sql.Types; + +import org.junit.Test; + +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public class TableManipulationTests extends BaseUnitTestCase { + public static final JdbcDataType VARCHAR = new JdbcDataType( Types.VARCHAR, "VARCHAR", String.class ); + public static final JdbcDataType INTEGER = new JdbcDataType( Types.INTEGER, "INTEGER", Long.class ); + + @Test + public void testTableCreation() { + Schema schema = new Schema( null, null ); + Table table = schema.createTable( Identifier.toIdentifier( "my_table" ), Identifier.toIdentifier( "my_table" ) ); + assertNull( table.getSchema().getName().getSchema() ); + assertNull( table.getSchema().getName().getCatalog() ); + assertEquals( "my_table", table.getPhysicalName().toString() ); + assertEquals( "my_table", table.getExportIdentifier() ); + assertNull( table.getPrimaryKey().getName() ); + assertFalse( table.values().iterator().hasNext() ); + + Column idColumn = table.locateOrCreateColumn( "id" ); + idColumn.setJdbcDataType( INTEGER ); + idColumn.setSize( Size.precision( 18, 0 ) ); + table.getPrimaryKey().addColumn( idColumn ); + table.getPrimaryKey().setName( Identifier.toIdentifier( "my_table_pk" ) ); + assertEquals( "my_table_pk", table.getPrimaryKey().getName().toString() ); + assertEquals( "my_table.PK", table.getPrimaryKey().getExportIdentifier() ); + + Column col_1 = table.locateOrCreateColumn( "col_1" ); + col_1.setJdbcDataType( VARCHAR ); + col_1.setSize( Size.length( 512 ) ); + + for ( Value value : table.values() ) { + assertTrue( Column.class.isInstance( value ) ); + Column column = ( Column ) value; + if ( column.getColumnName().getText().equals( "id" ) ) { + assertEquals( INTEGER, column.getJdbcDataType() ); + assertEquals( 18, column.getSize().getPrecision() ); + assertEquals( 0, column.getSize().getScale() ); + assertEquals( -1, column.getSize().getLength() ); + assertNull( column.getSize().getLobMultiplier() ); + } + else { + assertEquals( "col_1", column.getColumnName().getText() ); + assertEquals( VARCHAR, column.getJdbcDataType() ); + assertEquals( -1, column.getSize().getPrecision() ); + assertEquals( -1, column.getSize().getScale() ); + assertEquals( 512, column.getSize().getLength() ); + assertNull( column.getSize().getLobMultiplier() ); + } + } + } + + @Test + public void testBasicForeignKeyDefinition() { + Schema schema = new Schema( null, null ); + Table book = schema.createTable( Identifier.toIdentifier( "BOOK" ), Identifier.toIdentifier( "BOOK" ) ); + + Column bookId = book.locateOrCreateColumn( "id" ); + bookId.setJdbcDataType( INTEGER ); + bookId.setSize( Size.precision( 18, 0 ) ); + book.getPrimaryKey().addColumn( bookId ); + book.getPrimaryKey().setName( Identifier.toIdentifier( "BOOK_PK" ) ); + + Table page = schema.createTable( Identifier.toIdentifier( "PAGE" ), Identifier.toIdentifier( "PAGE" ) ); + + Column pageId = page.locateOrCreateColumn( "id" ); + pageId.setJdbcDataType( INTEGER ); + pageId.setSize( Size.precision( 18, 0 ) ); + page.getPrimaryKey().addColumn( pageId ); + page.getPrimaryKey().setName( Identifier.toIdentifier( "PAGE_PK" ) ); + + Column pageBookId = page.locateOrCreateColumn( "BOOK_ID" ); + pageId.setJdbcDataType( INTEGER ); + pageId.setSize( Size.precision( 18, 0 ) ); + ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK", true ); + pageBookFk.addColumn( pageBookId ); + + assertEquals( page, pageBookFk.getSourceTable() ); + assertEquals( book, pageBookFk.getTargetTable() ); + + assertEquals( 1, pageBookFk.getColumnSpan() ); + assertEquals( 1, pageBookFk.getColumns().size() ); + assertEquals( 1, pageBookFk.getSourceColumns().size() ); + assertEquals( 1, pageBookFk.getTargetColumns().size() ); + assertSame( pageBookId, pageBookFk.getColumns().get( 0 ) ); + assertSame( pageBookId, pageBookFk.getSourceColumns().get( 0 ) ); + assertSame( bookId, pageBookFk.getTargetColumns().get( 0 ) ); + } + + @Test + public void testQualifiedName() { + Dialect dialect = new H2Dialect(); + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + Table table = schema.createTable( Identifier.toIdentifier( "my_table" ), Identifier.toIdentifier( "my_table" ) ); + assertEquals( "my_table", table.getPhysicalName().getText() ); + assertEquals( "my_table", table.getPhysicalName().toString() ); + assertEquals( "\"catalog\".schema.my_table", table.getQualifiedName( dialect ) ); + + table = schema.createTable( Identifier.toIdentifier( "`my_table`" ), Identifier.toIdentifier( "`my_table`" ) ); + assertEquals( "my_table", table.getPhysicalName().getText() ); + assertEquals( "`my_table`", table.getPhysicalName().toString() ); + assertEquals( "\"catalog\".schema.\"my_table\"", table.getQualifiedName( dialect ) ); + + InLineView inLineView = schema.createInLineView( Identifier.toIdentifier( "my_inlineview" ), "select ..." ); + assertEquals( "( select ... )", inLineView.getQualifiedName( dialect ) ); + } + + @Test + public void testTableIdentifier() { + Identifier tableIdentifier = Identifier.toIdentifier( "my_table" ); + assertEquals( "my_table", tableIdentifier.getText() ); + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + Table table = schema.createTable( tableIdentifier, tableIdentifier ); + assertSame( tableIdentifier, table.getPhysicalName() ); + assertSame( table, schema.locateTable( Identifier.toIdentifier( "my_table" ) ) ); + assertEquals( "my_table", table.getLogicalName().getText() ); + } + + @Test + public void testQuotedTableIdentifier() { + Identifier tableIdentifier = Identifier.toIdentifier( "`my_table`" ); + assertEquals( "my_table", tableIdentifier.getText() ); + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + Table table = schema.createTable( tableIdentifier, tableIdentifier ); + assertSame( tableIdentifier, table.getPhysicalName() ); + assertSame( table, schema.locateTable( Identifier.toIdentifier( "`my_table`" ) ) ); + assertEquals( "my_table", table.getLogicalName().getText() ); + assertTrue( table.getLogicalName().isQuoted() ); + assertNull( schema.locateTable( Identifier.toIdentifier( "my_table" ) ) ); + } + + @Test + public void testInLineViewLogicalName() { + Schema schema = new Schema( Identifier.toIdentifier( "`catalog`" ), Identifier.toIdentifier( "schema" ) ); + InLineView view = schema.createInLineView( Identifier.toIdentifier( "my_view" ), "select" ); + assertEquals( "my_view", view.getLogicalName().getText() ); + assertEquals( "select", view.getSelect() ); + assertSame( view, schema.getInLineView( view.getLogicalName() ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java b/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java index 0d63c9ce08d7..8d4dfca4b63b 100644 --- a/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/serialization/SessionFactorySerializationTest.java @@ -24,11 +24,13 @@ package org.hibernate.serialization; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + import javax.naming.Reference; import javax.naming.StringRefAddr; -import org.junit.Test; - import org.hibernate.SessionFactory; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; @@ -36,10 +38,7 @@ import org.hibernate.internal.util.SerializationHelper; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.SerializationException; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; +import org.junit.Test; /** * @author Steve Ebersole diff --git a/hibernate-core/src/test/java/org/hibernate/service/internal/ConcurrentServiceBindingTest.java b/hibernate-core/src/test/java/org/hibernate/service/internal/ConcurrentServiceBindingTest.java new file mode 100644 index 000000000000..56e9dd58673a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/service/internal/ConcurrentServiceBindingTest.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.service.internal; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator; +import org.hibernate.service.spi.ServiceBinding; +import org.hibernate.testing.TestForIssue; +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit Test for ConcurrentServiceBinding + * + * @author Sanne Grinovero + */ +@TestForIssue(jiraKey="HHH-8947") +public class ConcurrentServiceBindingTest { + + private Class[] testTypes = new Class[]{ String.class, Integer.class, ServiceBinding.class, ConnectionProviderInitiator.class, HashMap.class, + ConcurrentServiceBindingTest.class, Long.class, Test.class, Set.class, HashSet.class }; + + @Test + public void normalImplementationTest() { + final ConcurrentServiceBinding binder = new ConcurrentServiceBinding(); + verifyBehaviour( binder ); + } + + @Test + public void allKeysCollisions() { + final ConcurrentServiceBinding binder = new ConcurrentServiceBinding() { + protected int hashKey(final Class key) { + return 15; + } + }; + verifyBehaviour( binder ); + } + + @Test + public void someKeysCollisions() { + final Set collidingClasses = new HashSet(); + collidingClasses.add( String.class ); + collidingClasses.add( ServiceBinding.class ); + collidingClasses.add( ConnectionProviderInitiator.class ); + final Set classedWhichHit = new HashSet(); + final ConcurrentServiceBinding binder = new ConcurrentServiceBinding() { + protected int hashKey(final Class key) { + if ( collidingClasses.contains( key ) ) { + classedWhichHit.add( key ); + return 15; + } + else { + return System.identityHashCode( key ); + } + } + }; + verifyBehaviour( binder ); + Assert.assertEquals( 3, classedWhichHit.size() );//to verify the test is being applied as expected + } + + private void verifyBehaviour(ConcurrentServiceBinding binder) { + isEmpty( binder ); + HashSet addedTypes = new HashSet(); + for ( Class newtype : testTypes ) { + addedTypes.add( newtype ); + binder.put( newtype, newtype.toString() ); + containsExactly( binder, addedTypes ); + } + binder.clear(); + isEmpty( binder ); + } + + private void containsExactly(ConcurrentServiceBinding binder, HashSet addedTypes) { + for ( Class knownType : addedTypes ) { + final String value = binder.get( knownType ); + Assert.assertNotNull( value ); + Assert.assertEquals( knownType.toString(), value ); + int countElements = 0; + boolean present = false; + for ( String each : binder.values() ) { + countElements++; + if ( each.equals( knownType.toString() ) ) { + Assert.assertFalse( "should have been unique", present ); + present = true; + } + } + Assert.assertEquals( addedTypes.size(), countElements ); + Assert.assertTrue( present ); + } + } + + private void isEmpty(ConcurrentServiceBinding binder) { + for ( String value : binder.values() ) { + Assert.fail( "Expected it to be empty" ); + } + for ( Class type : testTypes ) { + Assert.assertNull( binder.get( type ) ); + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/service/internal/ServiceRegistryClosingCascadeTest.java b/hibernate-core/src/test/java/org/hibernate/service/internal/ServiceRegistryClosingCascadeTest.java new file mode 100644 index 000000000000..7eb792620f3d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/service/internal/ServiceRegistryClosingCascadeTest.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.service.internal; + +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Steve Ebersole + */ +public class ServiceRegistryClosingCascadeTest extends BaseUnitTestCase { + @Test + public void testSessionFactoryClosing() { + BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + assertTrue( ( (BootstrapServiceRegistryImpl) bsr ).isActive() ); + MetadataSources metadataSources = new MetadataSources( bsr ); + SessionFactory sf = metadataSources.buildMetadata().buildSessionFactory(); + + sf.close(); + assertFalse( ( (BootstrapServiceRegistryImpl) bsr ).isActive() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java index 82feda4e7e71..f118d4b31148 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/abstractembeddedcomponents/propertyref/AbstractComponentPropertyRefTest.java @@ -23,17 +23,19 @@ */ package org.hibernate.test.abstractembeddedcomponents.propertyref; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertNotNull; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-7242", message = "property-ref" ) public class AbstractComponentPropertyRefTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "abstractembeddedcomponents/propertyref/Mappings.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/ConfigurationTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/ConfigurationTest.java deleted file mode 100644 index 2f3cd0d40d13..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/ConfigurationTest.java +++ /dev/null @@ -1,164 +0,0 @@ -//$Id$ -package org.hibernate.test.annotations; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Emmanuel Bernard - */ -public class ConfigurationTest { - private ServiceRegistry serviceRegistry; - @Before - public void setUp() { - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() ); - } - @After - public void tearDown() { - if ( serviceRegistry != null ) { - ServiceRegistryBuilder.destroy( serviceRegistry ); - } - } - @Test - public void testDeclarativeMix() throws Exception { - Configuration cfg = new Configuration(); - cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - SessionFactory sf = cfg.buildSessionFactory( serviceRegistry ); - assertNotNull( sf ); - Session s = sf.openSession(); - Transaction tx = s.beginTransaction(); - Query q = s.createQuery( "from Boat" ); - assertEquals( 0, q.list().size() ); - q = s.createQuery( "from Plane" ); - assertEquals( 0, q.list().size() ); - tx.commit(); - s.close(); - sf.close(); - } - @Test - public void testIgnoringHbm() throws Exception { - Configuration cfg = new Configuration(); - cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - cfg.setProperty( Configuration.ARTEFACT_PROCESSING_ORDER, "class" ); - SessionFactory sf = cfg.buildSessionFactory( serviceRegistry ); - assertNotNull( sf ); - Session s = sf.openSession(); - Transaction tx = s.beginTransaction(); - Query q; - try { - s.createQuery( "from Boat" ).list(); - fail( "Boat should not be mapped" ); - } - catch (HibernateException e) { - //all good - } - q = s.createQuery( "from Plane" ); - assertEquals( 0, q.list().size() ); - tx.commit(); - s.close(); - sf.close(); - } - @Test - public void testPrecedenceHbm() throws Exception { - Configuration cfg = new Configuration(); - cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - cfg.addAnnotatedClass( Boat.class ); - SessionFactory sf = cfg.buildSessionFactory( serviceRegistry ); - assertNotNull( sf ); - Session s = sf.openSession(); - s.getTransaction().begin(); - Boat boat = new Boat(); - boat.setSize( 12 ); - boat.setWeight( 34 ); - s.persist( boat ); - s.getTransaction().commit(); - s.clear(); - Transaction tx = s.beginTransaction(); - boat = (Boat) s.get( Boat.class, boat.getId() ); - assertTrue( "Annotation has precedence", 34 != boat.getWeight() ); - s.delete( boat ); - //s.getTransaction().commit(); - tx.commit(); - s.close(); - sf.close(); - } - @Test - public void testPrecedenceAnnotation() throws Exception { - Configuration cfg = new Configuration(); - cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - cfg.setProperty( Configuration.ARTEFACT_PROCESSING_ORDER, "class, hbm" ); - cfg.addAnnotatedClass( Boat.class ); - SessionFactory sf = cfg.buildSessionFactory( serviceRegistry ); - assertNotNull( sf ); - Session s = sf.openSession(); - s.getTransaction().begin(); - Boat boat = new Boat(); - boat.setSize( 12 ); - boat.setWeight( 34 ); - s.persist( boat ); - s.getTransaction().commit(); - s.clear(); - Transaction tx = s.beginTransaction(); - boat = (Boat) s.get( Boat.class, boat.getId() ); - assertTrue( "Annotation has precedence", 34 == boat.getWeight() ); - s.delete( boat ); - tx.commit(); - s.close(); - sf.close(); - } - @Test - public void testHbmWithSubclassExtends() throws Exception { - Configuration cfg = new Configuration(); - cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); - cfg.addClass( Ferry.class ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - SessionFactory sf = cfg.buildSessionFactory( serviceRegistry ); - assertNotNull( sf ); - Session s = sf.openSession(); - Transaction tx = s.beginTransaction(); - Query q = s.createQuery( "from Ferry" ); - assertEquals( 0, q.list().size() ); - q = s.createQuery( "from Plane" ); - assertEquals( 0, q.list().size() ); - tx.commit(); - s.close(); - sf.close(); - } - @Test - public void testAnnReferencesHbm() throws Exception { - Configuration cfg = new Configuration(); - cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); - cfg.addAnnotatedClass( Port.class ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - SessionFactory sf = cfg.buildSessionFactory( serviceRegistry ); - assertNotNull( sf ); - Session s = sf.openSession(); - Transaction tx = s.beginTransaction(); - Query q = s.createQuery( "from Boat" ); - assertEquals( 0, q.list().size() ); - q = s.createQuery( "from Port" ); - assertEquals( 0, q.list().size() ); - tx.commit(); - s.close(); - sf.close(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/Customer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/Customer.java index ce8b4b6af16b..f950ec9a31b0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/Customer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/Customer.java @@ -1,8 +1,11 @@ //$Id$ package org.hibernate.test.annotations; +import static org.hibernate.annotations.CascadeType.ALL; + import java.io.Serializable; import java.util.Collection; import java.util.SortedSet; + import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -13,10 +16,7 @@ import javax.persistence.OneToOne; import org.hibernate.annotations.Cascade; -import org.hibernate.annotations.Sort; -import org.hibernate.annotations.SortType; - -import static org.hibernate.annotations.CascadeType.ALL; +import org.hibernate.annotations.SortComparator; /** @@ -55,7 +55,7 @@ public void setName(String string) { @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinColumn(name = "CUST_ID") - @Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class) + @SortComparator(TicketComparator.class) public SortedSet getTickets() { return tickets; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java index 5f80af32402d..4a92bed35004 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/EntityTest.java @@ -30,21 +30,21 @@ import java.util.List; import java.util.TimeZone; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.StaleStateException; import org.hibernate.Transaction; import org.hibernate.dialect.Oracle10gDialect; -import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.type.StandardBasicTypes; +import org.hibernate.testing.SkipForDialect; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -59,7 +59,10 @@ public class EntityTest extends BaseCoreFunctionalTestCase { @Test public void testLoad() throws Exception { //put an object in DB - assertEquals( "Flight", configuration().getClassMapping( Flight.class.getName() ).getTable().getName() ); + assertEquals( + "Flight", + metadata().getEntityBinding( Flight.class.getName() ).getPrimaryTableName() + ); Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -314,7 +317,11 @@ public void testFieldAccess() throws Exception { @Test public void testEntityName() throws Exception { - assertEquals( "Corporation", configuration().getClassMapping( Company.class.getName() ).getTable().getName() ); + assertEquals( + "Corporation", + metadata().getEntityBinding( Company.class.getName() ).getPrimaryTableName() + ); + Session s = openSession(); Transaction tx = s.beginTransaction(); Company comp = new Company(); @@ -436,7 +443,7 @@ public void runCreateSchema() { } private SchemaExport schemaExport() { - return new SchemaExport( serviceRegistry(), configuration() ); + return new SchemaExport( metadata() ); } @After diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java index eed70d2ea935..b93230ebc5bd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java @@ -23,15 +23,15 @@ */ package org.hibernate.test.annotations; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.annotations.inheritance.Carrot; import org.hibernate.test.annotations.inheritance.Tomato; import org.hibernate.test.annotations.inheritance.Vegetable; import org.hibernate.test.annotations.inheritance.VegetablePk; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -127,6 +127,7 @@ protected Class[] getAnnotatedClasses() { AmericaCupClass.class, Country.class, Vegetable.class, + VegetablePk.class, Carrot.class, Tomato.class }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java index 71e4d1748ec3..26ddc8ef51e5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/AccessTest.java @@ -23,11 +23,11 @@ */ package org.hibernate.test.annotations.access; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; + import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -74,6 +74,7 @@ public void testSuperclassNonOverriding() throws Exception { tx.commit(); s.close(); } + @Test public void testPropertyOverriding() throws Exception { Furniture fur = new Furniture(); @@ -90,6 +91,7 @@ public void testPropertyOverriding() throws Exception { tx.commit(); s.close(); } + @Test public void testNonOverridenSubclass() throws Exception { Chair chair = new Chair(); @@ -106,6 +108,7 @@ public void testNonOverridenSubclass() throws Exception { tx.commit(); s.close(); } + @Test public void testOverridenSubclass() throws Exception { BigBed bed = new BigBed(); @@ -124,6 +127,7 @@ public void testOverridenSubclass() throws Exception { tx.commit(); s.close(); } + @Test public void testFieldsOverriding() throws Exception { Gardenshed gs = new Gardenshed(); @@ -141,6 +145,7 @@ public void testFieldsOverriding() throws Exception { tx.commit(); s.close(); } + @Override protected Class[] getAnnotatedClasses() { return new Class[] { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Bed.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Bed.java index 62e72decff75..cb347c2db935 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Bed.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Bed.java @@ -1,15 +1,15 @@ //$Id$ package org.hibernate.test.annotations.access; +import javax.persistence.Access; +import javax.persistence.AccessType; import javax.persistence.Entity; import javax.persistence.Transient; -import org.hibernate.annotations.AccessType; - /** * @author Emmanuel Bernard */ @Entity -@AccessType("property") +@Access(AccessType.PROPERTY) public class Bed extends Furniture { String quality; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java index 229525fb5b15..1a5aea19512e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Closet.java @@ -22,7 +22,7 @@ * @author Hardy Ferentschik */ @Embeddable -public class Closet extends Furniture { +public class Closet extends Woody { int numberOfDoors; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Furniture.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Furniture.java index e423d71c0cbb..3ede33e6789a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Furniture.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Furniture.java @@ -1,17 +1,17 @@ //$Id$ package org.hibernate.test.annotations.access; +import javax.persistence.Access; +import javax.persistence.AccessType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Transient; -import org.hibernate.annotations.AccessType; - /** * @author Emmanuel Bernard */ @Entity -@AccessType("field") +@Access(AccessType.FIELD) public class Furniture extends Woody { @Id @GeneratedValue @@ -36,9 +36,9 @@ public void setId(Integer id) { this.id = id; } - @AccessType("property") public long weight; + @Access(AccessType.PROPERTY) public long getWeight() { return weight + 1; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Gardenshed.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Gardenshed.java index dad5d73aa659..c67ddef71a7e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Gardenshed.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Gardenshed.java @@ -5,7 +5,7 @@ import javax.persistence.Id; import javax.persistence.Transient; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * This is the opposite of the Furniture test, as this tries to override the class AccessType("property") with @@ -15,7 +15,7 @@ * @since 2007-05-31 */ @Entity -@AccessType( "property" ) +@AttributeAccessor( "property" ) public class Gardenshed extends Woody { @@ -43,7 +43,7 @@ public void setId(Integer id) { } // These 2 functions should not return in Hibernate, but the value should come from the field "floors" - @AccessType( "field" ) + @AttributeAccessor( "field" ) public long getFloors() { return this.floors + 2; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Woody.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Woody.java index 2f7f19b79af5..6ced8e68bcaa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Woody.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/Woody.java @@ -1,14 +1,16 @@ //$Id$ package org.hibernate.test.annotations.access; + import javax.persistence.MappedSuperclass; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * @author Emmanuel Bernard */ @MappedSuperclass -@AccessType("property") +//@Access(AccessType.PROPERTY) +@AttributeAccessor("property") public class Woody extends Thingy { private String color; private String name; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java index 1d81847cf205..67c31e4e5033 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java @@ -23,21 +23,24 @@ */ package org.hibernate.test.annotations.access.jpa; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Environment; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.LenientPersistentAttributeMemberResolver; import org.hibernate.property.BasicPropertyAccessor; import org.hibernate.property.DirectPropertyAccessor; import org.hibernate.service.ServiceRegistry; +import org.hibernate.tuple.entity.EntityTuplizer; + import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.TestForIssue; -import org.hibernate.tuple.entity.EntityTuplizer; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -49,7 +52,7 @@ * @author Hardy Ferentschik */ @SuppressWarnings({ "deprecation" }) -public class AccessMappingTest { +public class AccessMappingTest extends BaseUnitTestCase { private ServiceRegistry serviceRegistry; @Before @@ -141,13 +144,14 @@ public void testExplicitPropertyAccessAnnotationsOnField() throws Exception { cfg.addAnnotatedClass( Student.class ); SessionFactory sf= null; try { - sf = cfg.buildSessionFactory( serviceRegistry ); - fail( "@Id and @OneToMany are not placed consistently in test entities. SessionFactory creation should fail." ); + sf = cfg.buildSessionFactory( serviceRegistry ); + fail( "@Id and @OneToMany are not placed consistently in test entities. SessionFactory creation should fail." ); } catch ( MappingException e ) { // success - } finally { - if(sf!=null){ + } + finally { + if ( sf != null ) { sf.close(); } } @@ -155,12 +159,16 @@ public void testExplicitPropertyAccessAnnotationsOnField() throws Exception { @Test public void testExplicitPropertyAccessAnnotationsWithHibernateStyleOverride() throws Exception { - AnnotationConfiguration cfg = new AnnotationConfiguration(); - Class classUnderTest = Course3.class; - cfg.addAnnotatedClass( classUnderTest ); - cfg.addAnnotatedClass( Student.class ); - SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry ); - EntityTuplizer tuplizer = factory.getEntityPersister( classUnderTest.getName() ) + MetadataSources sources = new MetadataSources( serviceRegistry ); + sources.addAnnotatedClass( Course3.class ) + .addAnnotatedClass( Student.class ); + + SessionFactoryImplementor factory = (SessionFactoryImplementor) sources.getMetadataBuilder() + .with( LenientPersistentAttributeMemberResolver.INSTANCE ) + .build() + .buildSessionFactory(); + + EntityTuplizer tuplizer = factory.getEntityPersister( Course3.class.getName() ) .getEntityMetamodel() .getTuplizer(); assertTrue( @@ -240,8 +248,8 @@ public void testDefaultPropertyAccessIsInherited() throws Exception { factory.close(); } - @TestForIssue(jiraKey = "HHH-5004") @Test + @TestForIssue(jiraKey = "HHH-5004") public void testAccessOnClassAndId() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Course8.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Course3.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Course3.java index 6e3a13097114..551e037a1d91 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Course3.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Course3.java @@ -24,6 +24,7 @@ */ package org.hibernate.test.annotations.access.jpa; import java.util.List; + import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.CascadeType; @@ -48,7 +49,7 @@ public class Course3 { @Id @GeneratedValue - @org.hibernate.annotations.AccessType("field") + @Access(AccessType.FIELD) public long getId() { return id; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java index ad456887e042..b117e69261bf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java @@ -43,6 +43,7 @@ public class Gardenshed Woody { private Integer id; private String brand; + @Access(javax.persistence.AccessType.FIELD) public long floors; @Transient @@ -66,7 +67,6 @@ public void setId(Integer id) { // These 2 functions should not return in Hibernate, but the value should come from the field "floors" - @Access(javax.persistence.AccessType.FIELD) public long getFloors() { return this.floors + 2; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/LenientMemberResolutionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/LenientMemberResolutionTest.java new file mode 100644 index 000000000000..ad3986ff9b52 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/LenientMemberResolutionTest.java @@ -0,0 +1,106 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.access.jpa; + +import javax.persistence.Access; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.AnnotationException; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.LenientPersistentAttributeMemberResolver; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static javax.persistence.AccessType.FIELD; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +/** + * Test for {@link org.hibernate.metamodel.spi.LenientPersistentAttributeMemberResolver} + * + * @author Steve Ebersole + */ +public class LenientMemberResolutionTest extends BaseUnitTestCase { + + @Entity(name = "MyEntity") + public static class MyEntity { + private Integer id; + private String name; + + @Id + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Access(FIELD) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Test + public void testResolution() { + MetadataSources sources = new MetadataSources() + .addAnnotatedClass( MyEntity.class ); + + // technically speaking the @Access(FIELD) annotation on a getter violates + // the JPA spec (section 2.3.2). The standard resolution strategy sees that + // and throws an exception. + // + // the lenient strategy allows it + + try { + sources.getMetadataBuilder().build(); + fail( "Was expecting an exception" ); + } + catch (AnnotationException expected) { + // expected + } + + + Metadata metadata = sources + .getMetadataBuilder() + .with( LenientPersistentAttributeMemberResolver.INSTANCE ) + .build(); + + EntityBinding myEntityBinding = metadata.getEntityBinding( MyEntity.class.getName() ); + assertNotNull( myEntityBinding ); + AttributeBinding nameAttrBinding = myEntityBinding.locateAttributeBinding( "name" ); + assertEquals( "field", nameAttrBinding.getPropertyAccessorName() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/Boy.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/Boy.java index 27c237c8c992..1350ec29b13e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/Boy.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/Boy.java @@ -17,11 +17,11 @@ */ package org.hibernate.test.annotations.access.xml; import java.util.Set; + +import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import org.hibernate.annotations.Entity; - /** * @author Hardy Ferentschik */ diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java index cd3c0a021b06..9aa40925527d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java @@ -23,22 +23,22 @@ */ package org.hibernate.test.annotations.access.xml; -import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.persistence.AccessType; -import org.junit.Assert; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.MetadataSources; import org.hibernate.property.BasicPropertyAccessor; import org.hibernate.property.DirectPropertyAccessor; -import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.tuple.entity.EntityTuplizer; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Assert; +import org.junit.Test; + /** * Test verifying that it is possible to configure the access type via xml configuration. @@ -57,6 +57,7 @@ public void testAccessOnBasicXmlElement() throws Exception { // without any xml configuration we have field access assertAccessType( factory, classUnderTest, AccessType.FIELD ); factory.close(); + // now with an additional xml configuration file changing the default access type for Tourist using basic configFiles = new ArrayList(); configFiles.add( "org/hibernate/test/annotations/access/xml/Tourist.xml" ); @@ -66,6 +67,12 @@ public void testAccessOnBasicXmlElement() throws Exception { } @Test + @FailureExpectedWithNewMetamodel( + message = "The problem here is that XML is attempting to apply PU-wide default AccessType, " + + "but mocker only understands (and overrides) attributes that are explicitly listed in the " + + "XML. Likely we need to link the XML defaults with the local-binding-context defaults as we" + + "start to process Jandex" + ) public void testAccessOnPersistenceUnitDefaultsXmlElement() throws Exception { Class classUnderTest = Tourist.class; List> classes = new ArrayList>(); @@ -176,15 +183,15 @@ public void testAccessOnElementCollectionXmlElement() throws Exception { private SessionFactoryImplementor buildSessionFactory(List> classesUnderTest, List configFiles) { assert classesUnderTest != null; assert configFiles != null; - Configuration cfg = new Configuration(); + + MetadataSources metadataSources = new MetadataSources(); for ( Class clazz : classesUnderTest ) { - cfg.addAnnotatedClass( clazz ); + metadataSources.addAnnotatedClass( clazz ); } for ( String configFile : configFiles ) { - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( configFile ); - cfg.addInputStream( is ); + metadataSources.addResource( configFile ); } - return ( SessionFactoryImplementor ) cfg.buildSessionFactory(); + return ( SessionFactoryImplementor ) metadataSources.buildMetadata().buildSessionFactory(); } // uses the first getter of the tupelizer for the assertions diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java index 148e49388efd..ab7812b51cd8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/any/AnyTest.java @@ -28,12 +28,14 @@ import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +@FailureExpectedWithNewMetamodel public class AnyTest extends BaseCoreFunctionalTestCase { @Test public void testDefaultAnyAssociation() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/backquotes/Bug.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/backquotes/Bug.java index 1b5732bf03cd..fbc21ae12619 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/backquotes/Bug.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/backquotes/Bug.java @@ -1,15 +1,17 @@ //$Id$ package org.hibernate.test.annotations.backquotes; import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; - -import org.hibernate.annotations.Index; +import javax.persistence.Table; @Entity +@Table(indexes = @Index(name="`titleindex`", columnList = "`title`")) public class Bug { @Id @@ -17,7 +19,6 @@ public class Bug private int id; @Column(name="`title`") - @Index(name="`titleindex`") private String title; @ManyToMany diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java index 68093b65b976..2aaf27d64e79 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationAutoTest.java @@ -31,7 +31,6 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; - import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java index 110b6b3fd045..86cb5b9cf194 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationDisabledTest.java @@ -26,14 +26,14 @@ import java.math.BigDecimal; import javax.validation.ConstraintViolationException; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -61,9 +61,16 @@ public void testListeners() { @Test public void testDDLDisabled() { - PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); - Column countryColumn = (Column) classMapping.getProperty( "country" ).getColumnIterator().next(); - assertTrue( "DDL constraints are applied", countryColumn.isNullable() ); + final boolean isNullable; + final EntityBinding entityBinding = metadata().getEntityBinding( Address.class.getName() ); + final SingularAttributeBinding attributeBinding = + (SingularAttributeBinding) entityBinding.locateAttributeBinding( "country" ); + + + final org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) attributeBinding.getValues().get( 0 ); + isNullable = column.isNullable(); + assertTrue( "DDL constraints are applied", isNullable ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java index 912b508dc843..f6e9c28d7af0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/BeanValidationProvidedFactoryTest.java @@ -85,8 +85,9 @@ public String interpolate(String s, Context context, Locale locale) { }; final javax.validation.Configuration configuration = Validation.byDefaultProvider().configure(); configuration.messageInterpolator( messageInterpolator ); - ValidatorFactory vf = configuration.buildValidatorFactory(); - cfg.getProperties().put( "javax.persistence.validation.factory", vf ); + ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); + cfg.getProperties().put( "javax.persistence.validation.factory", validatorFactory ); + cfg.setProperty( "javax.persistence.validation.mode", "AUTO" ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java index 4500f434e58d..416ec74c8b60 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java @@ -26,9 +26,9 @@ import org.junit.Test; import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -37,7 +37,7 @@ import static org.junit.Assert.assertTrue; /** - * Test verifying that DDL constraints get applied when Bean Validation / Hibernate Validator are enabled. + * Test verifying that DDL constraints get applied when Bean Validation / Hibernate Validator is enabled. * * @author Emmanuel Bernard * @author Hardy Ferentschik @@ -45,56 +45,64 @@ public class DDLTest extends BaseCoreFunctionalTestCase { @Test public void testBasicDDL() { - PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); - Column stateColumn = (Column) classMapping.getProperty( "state" ).getColumnIterator().next(); - assertEquals( stateColumn.getLength(), 3 ); - Column zipColumn = (Column) classMapping.getProperty( "zip" ).getColumnIterator().next(); - assertEquals( zipColumn.getLength(), 5 ); + Column stateColumn = SchemaUtil.getColumn( + Address.class, + "state", + metadata() + ); + assertEquals( 3, stateColumn.getSize().getLength() ); + Column zipColumn = SchemaUtil.getColumn( + Address.class, + "zip", + metadata() + ); + assertEquals( 5, zipColumn.getSize().getLength() ); assertFalse( zipColumn.isNullable() ); } @Test public void testApplyOnIdColumn() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); - Column serialColumn = (Column) classMapping.getIdentifierProperty().getColumnIterator().next(); - assertEquals( "Validator annotation not applied on ids", 2, serialColumn.getLength() ); + PrimaryKey id = SchemaUtil.getPrimaryKey( Tv.class, metadata() ); + assertEquals( "Validator annotation not applied on ids", 2, id.getColumns().get( 0 ).getSize().getLength() ); } @Test - @TestForIssue( jiraKey = "HHH-5281" ) + @TestForIssue(jiraKey = "HHH-5281") public void testLengthConstraint() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); - Column modelColumn = (Column) classMapping.getProperty( "model" ).getColumnIterator().next(); - assertEquals( modelColumn.getLength(), 5 ); + Column column = SchemaUtil.getColumn( Tv.class, "model", metadata() ); + assertEquals( 5, column.getSize().getLength() ); } @Test public void testApplyOnManyToOne() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( TvOwner.class.getName() ); - Column serialColumn = (Column) classMapping.getProperty( "tv" ).getColumnIterator().next(); - assertEquals( "Validator annotations not applied on associations", false, serialColumn.isNullable() ); + org.hibernate.metamodel.spi.relational.Column column = SchemaUtil.getColumn( + TvOwner.class, + "tv_serial", + metadata() + ); + assertFalse( "@NotNull on @ManyToOne should be applied", column.isNullable() ); } @Test public void testSingleTableAvoidNotNull() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Rock.class.getName() ); - Column serialColumn = (Column) classMapping.getProperty( "bit" ).getColumnIterator().next(); - assertTrue( "Notnull should not be applied on single tables", serialColumn.isNullable() ); + Column column = SchemaUtil.getColumn( Rock.class, "bit", metadata() ); + assertTrue( "Notnull should not be applied on single tables", column.isNullable() ); } @Test public void testNotNullOnlyAppliedIfEmbeddedIsNotNullItself() throws Exception { - PersistentClass classMapping = configuration().getClassMapping( Tv.class.getName() ); - Property property = classMapping.getProperty( "tuner.frequency" ); - Column serialColumn = (Column) property.getColumnIterator().next(); - assertEquals( - "Validator annotations are applied on tuner as it is @NotNull", false, serialColumn.isNullable() + Column column = SchemaUtil.getColumn( + Tv.class, + "frequency", + metadata() + ); + assertFalse( + "Validator annotations are applied on tuner as it is @NotNull", column.isNullable() ); - property = classMapping.getProperty( "recorder.time" ); - serialColumn = (Column) property.getColumnIterator().next(); - assertEquals( - "Validator annotations are applied on tuner as it is @NotNull", true, serialColumn.isNullable() + column = SchemaUtil.getColumn( Tv.class, "`time`", metadata() ); + assertTrue( + "Validator annotations were not applied on recorder", column.isNullable() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java index 252efbb25bae..0a7b49f43321 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLWithoutCallbackTest.java @@ -26,17 +26,19 @@ import java.math.BigDecimal; import javax.validation.ConstraintViolationException; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; @@ -91,9 +93,12 @@ public void testRangeChecksGetApplied() { @Test public void testDDLEnabled() { - PersistentClass classMapping = configuration().getClassMapping( Address.class.getName() ); - Column countryColumn = (Column) classMapping.getProperty( "country" ).getColumnIterator().next(); - assertFalse( "DDL constraints are not applied", countryColumn.isNullable() ); + EntityBinding eb = metadata().getEntityBinding( Address.class.getName() ); + SingularAttributeBinding ab = (SingularAttributeBinding) eb.locateAttributeBinding( "country" ); + assertEquals( 1, ab.getRelationalValueBindings().size() ); + RelationalValueBinding columnBind = ab.getRelationalValueBindings().get( 0 ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) columnBind.getValue(); + assertFalse( "DDL constraints are not applied", column.isNullable() ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java index b131277d9e55..78cd3286dd6a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/HibernateTraversableResolverTest.java @@ -31,7 +31,6 @@ import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Music.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Music.java index 3221d7bd7a6d..70f75da1c2e6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Music.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Music.java @@ -23,13 +23,17 @@ */ package org.hibernate.test.annotations.beanvalidation; + import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; /** * @author Emmanuel Bernard */ @Entity +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) public class Music { @Id public String name; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/CodedPairSetHolder.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/CodedPairSetHolder.java index 610db2e16998..89b9eac2fa17 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/CodedPairSetHolder.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/CodedPairSetHolder.java @@ -27,17 +27,17 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; + +import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.Table; -import org.hibernate.annotations.ForeignKey; - @Entity @Table(name = "CODED_PAIR_SET_HOLDER") class CodedPairSetHolder implements Serializable { @@ -53,8 +53,8 @@ class CodedPairSetHolder implements Serializable { private String code; @ElementCollection - @JoinTable(name = "CODED_PAIR_HOLDER_PAIR_SET", joinColumns = @JoinColumn(name = "CODED_PAIR_HOLDER_ID")) - @ForeignKey(name = "FK_PAIR_SET") + @CollectionTable(name = "CODED_PAIR_HOLDER_PAIR_SET", joinColumns = @JoinColumn(name = "CODED_PAIR_HOLDER_ID"), + foreignKey = @ForeignKey(name = "FK_PAIR_SET")) private final Set pairs = new HashSet(0); CodedPairSetHolder() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/PersonPair.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/PersonPair.java index 42a7cc1e158d..b58a7fdbf366 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/PersonPair.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cascade/PersonPair.java @@ -24,27 +24,27 @@ package org.hibernate.test.annotations.cascade; import java.io.Serializable; + import javax.persistence.CascadeType; import javax.persistence.Embeddable; import javax.persistence.FetchType; +import javax.persistence.ForeignKey; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; -import org.hibernate.annotations.ForeignKey; - @Embeddable class PersonPair implements Serializable { private static final long serialVersionUID = 4543565503074112720L; @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }) - @JoinColumn(name = "LEFT_PERSON_ID", nullable = false, updatable = false) - @ForeignKey(name = "FK_LEFT_PERSON") + @JoinColumn(name = "LEFT_PERSON_ID", nullable = false, updatable = false, + foreignKey = @ForeignKey(name = "FK_LEFT_PERSON")) private Person left; @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }) - @JoinColumn(name = "RIGHT_PERSON_ID", nullable = false, updatable = false) - @ForeignKey(name = "FK_RIGHT_PERSON") + @JoinColumn(name = "RIGHT_PERSON_ID", nullable = false, updatable = false, + foreignKey = @ForeignKey(name = "FK_RIGHT_PERSON")) private Person right; PersonPair() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java index d277ae1e8353..0a083afc0229 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java @@ -27,15 +27,16 @@ import java.util.Date; import java.util.List; -import org.junit.Test; - import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Disjunction; import org.hibernate.criterion.Restrictions; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -45,6 +46,12 @@ * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( + message = "Part of the problem is how some of the composite ids are defined. For example, " + + "quite a few map a logical `@Id @ManyToOne` combo without the @ManyToOne. Fixing those " + + "leads to an not being able to bind the org.hibernate.test.annotations.cid.A entity; it " + + "has composite id made up of 2 @OneToOnes (need to research that, why not @ManyToOne?)." +) public class CompositeIdTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneInCompositePk() throws Exception { @@ -364,9 +371,12 @@ private void createData(Session s){ protected Class[] getAnnotatedClasses() { return new Class[] { Parent.class, + ParentPk.class, Child.class, + ChildPk.class, Channel.class, TvMagazin.class, + TvMagazinPk.class, TvProgramIdClass.class, TvProgram.class, Presenter.class, @@ -376,6 +386,7 @@ protected Class[] getAnnotatedClasses() { OrderLinePk.class, LittleGenius.class, A.class, + AId.class, B.class, C.class, SomeEntity.class diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java index f93d719ee451..21069ac3ca0a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/OrderLine.java @@ -2,6 +2,7 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; +import javax.persistence.ManyToOne; /** * @author Emmanuel Bernard @@ -10,7 +11,9 @@ @IdClass(OrderLinePk.class) public class OrderLine { @Id + @ManyToOne public Order order; @Id + @ManyToOne public Product product; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java index 70d2edd8f950..8c259bf23419 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/ParentPk.java @@ -2,11 +2,12 @@ package org.hibernate.test.annotations.cid; import java.io.Serializable; import javax.persistence.Column; +import javax.persistence.Embeddable; /** * @author Emmanuel Bernard */ - +@Embeddable public class ParentPk implements Serializable { public String getFirstName() { return firstName; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java index 431881d5b10c..1135c9083c2f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/cid/TvProgramIdClass.java @@ -6,6 +6,7 @@ import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.SecondaryTable; import javax.persistence.Temporal; @@ -20,9 +21,11 @@ @IdClass( TvMagazinPk.class ) public class TvProgramIdClass { @Id + @ManyToOne @JoinColumn(nullable=false) public Channel channel; @Id + @ManyToOne @JoinColumn(nullable=false) public Presenter presenter; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java index 196173fb91f4..069a0d8e1b3c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java @@ -23,25 +23,25 @@ */ package org.hibernate.test.annotations.collectionelement; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Locale; -import org.junit.Test; - import org.hibernate.Filter; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.annotations.Country; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Emmanuel Bernard @@ -51,11 +51,9 @@ public class CollectionElementTest extends BaseCoreFunctionalTestCase { @Test public void testSimpleElement() throws Exception { - assertEquals( - "BoyFavoriteNumbers", - configuration().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ) - .getCollectionTable().getName() - ); + assertEquals( "BoyFavoriteNumbers", SchemaUtil.getCollection( Boy.class, "favoriteNumbers", metadata() ) + .getPluralAttributeKeyBinding().getCollectionTable().getLogicalName().toString() ); + Session s = openSession(); s.getTransaction().begin(); Boy boy = new Boy(); @@ -162,10 +160,10 @@ public void testAttributedJoin() throws Exception { @Test public void testLazyCollectionofElements() throws Exception { assertEquals( - "BoyFavoriteNumbers", - configuration().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ) - .getCollectionTable().getName() + "BoyFavoriteNumbers", SchemaUtil.getCollection( Boy.class, "favoriteNumbers", metadata() ) + .getPluralAttributeKeyBinding().getCollectionTable().getLogicalName().toString() ); + Session s = openSession(); s.getTransaction().begin(); Boy boy = new Boy(); @@ -270,23 +268,28 @@ private void isDefaultValueCollectionColumnPresent(String collectionOwner, Strin } private void isCollectionColumnPresent(String collectionOwner, String propertyName, String columnName) { - final Collection collection = configuration().getCollectionMapping( collectionOwner + "." + propertyName ); - final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); - boolean hasDefault = false; - while ( columnIterator.hasNext() ) { - Column column = (Column) columnIterator.next(); - if ( columnName.equals( column.getName() ) ) hasDefault = true; - } - assertTrue( "Could not find " + columnName, hasDefault ); + final EntityBinding entityBinding = metadata().getEntityBinding( collectionOwner ); + final PluralAttributeBinding binding = (PluralAttributeBinding) entityBinding.locateAttributeBinding( propertyName ); + final TableSpecification table = binding.getPluralAttributeKeyBinding().getCollectionTable(); + + boolean hasColumn = table.locateColumn( propertyName ) != null; + assertTrue( "Could not find " + columnName, hasColumn ); } @Override protected Class[] getAnnotatedClasses() { return new Class[] { Boy.class, + Toy.class, + Brand.class, Country.class, + CountryAttitude.class, TestCourse.class, - Matrix.class + Matrix.class, + LocalizedString.class, + Toy.class, + CountryAttitude.class, + Brand.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java index 1c5609cd3c54..4832581e5e59 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/EntityWithAnElementCollection.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.Set; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.Id; @@ -55,7 +56,7 @@ public void setId(Long id) { @ElementCollection // HHH-7732 -- "EntityWithAnElementCollection_someStrings" is too long for Oracle. - @JoinTable( + @CollectionTable( name = "SomeStrings", joinColumns = @JoinColumn( name = "EWAEC_ID") ) public Set getSomeStrings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Matrix.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Matrix.java index 09a482845121..56f3593ac0ac 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Matrix.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Matrix.java @@ -3,6 +3,7 @@ import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; + import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -10,8 +11,7 @@ import javax.persistence.MapKeyColumn; import org.hibernate.annotations.MapKeyType; -import org.hibernate.annotations.Sort; -import org.hibernate.annotations.SortType; +import org.hibernate.annotations.SortNatural; import org.hibernate.annotations.Type; /** @@ -25,7 +25,7 @@ public class Matrix { @MapKeyType( @Type(type="integer") ) @ElementCollection - @Sort(type = SortType.NATURAL) + @SortNatural @Type(type = "float") @MapKeyColumn(nullable = false) private SortedMap mvalues = new TreeMap(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java index 9ae1d29f6c8d..03ce6f6bc935 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java @@ -45,17 +45,14 @@ public void testOrderByName() throws Exception { Widgets widget = new Widgets(); widget.setName("hammer"); set.add(widget); - s.persist(widget); widget = new Widgets(); widget.setName("axel"); set.add(widget); - s.persist(widget); widget = new Widgets(); widget.setName("screwdriver"); set.add(widget); - s.persist(widget); p.setWidgets(set); s.persist(p); @@ -129,8 +126,10 @@ public void testOrderByWithDottedNotation() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { Products.class, - Widgets.class, - BugSystem.class + BugSystem.class, + Bug.class, + Person.class, + Widgets.class }; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java index b888a85bbb33..5c5cc73d975c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/Widgets.java @@ -1,12 +1,9 @@ package org.hibernate.test.annotations.collectionelement; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import javax.persistence.Embeddable; -@Entity +@Embeddable public class Widgets { private String name; - private int id; public Widgets() { @@ -19,15 +16,4 @@ public String getName() { public void setName(String name) { this.name = name; } - - @Id - @GeneratedValue - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/Location.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/Location.java index 7125491a42cf..fe3694a4a262 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/Location.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/Location.java @@ -71,4 +71,25 @@ public String getName() { public void setName(String name) { this.name = name; } + + @Override + public boolean equals(Object obj) { + if (! obj.getClass().equals( Location.class )) { + return false; + } + + Location loc = (Location) obj; + if (name != null ? !name.equals(loc.name) : loc.name != null) return false; + if (type != null ? !type.equals(loc.type) : loc.type != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result; + result = (name != null ? name.hashCode() : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); + return result; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java index 611f53e699b4..a34112cc1abf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java @@ -23,12 +23,14 @@ */ package org.hibernate.test.annotations.collectionelement.embeddables.withcustomenumdef; -import org.junit.Test; +import static junit.framework.Assert.assertEquals; + +import java.util.Iterator; import org.hibernate.Session; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static junit.framework.Assert.assertEquals; +import org.junit.Test; /** * @author Steve Ebersole @@ -36,20 +38,21 @@ public class TestBasicOps extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Query.class }; + return new Class[] { Query.class, Location.class }; } @Test public void testLoadAndStore() { Session s = openSession(); s.beginTransaction(); - s.save( new Query( new Location( "first", Location.Type.COUNTY ) ) ); + Query q = new Query( new Location( "first", Location.Type.COUNTY ) ); + s.save( q ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); - Query q = (Query) s.get( Query.class, 1L ); + q = (Query) s.get( Query.class, q.getId() ); assertEquals( 1, q.getIncludedLocations().size() ); Location l = q.getIncludedLocations().iterator().next(); assertEquals( Location.Type.COUNTY, l.getType() ); @@ -57,4 +60,42 @@ public void testLoadAndStore() { s.getTransaction().commit(); s.close(); } + + @Test + @TestForIssue(jiraKey = "HHH-7072") + public void testEmbeddableWithNullables() { + Session s = openSession(); + s.beginTransaction(); + Query q = new Query( new Location( null, Location.Type.COMMUNE ) ); + s.save( q ); + s.getTransaction().commit(); + s.clear(); + + s.beginTransaction(); + q.getIncludedLocations().add( new Location( null, Location.Type.COUNTY ) ); + s.update( q ); + s.getTransaction().commit(); + s.clear(); + + s.beginTransaction(); + q = (Query) s.get( Query.class, q.getId() ); +// assertEquals( 2, q.getIncludedLocations().size() ); + s.getTransaction().commit(); + s.clear(); + + s.beginTransaction(); + Iterator itr = q.getIncludedLocations().iterator(); + itr.next(); + itr.remove(); + s.update( q ); + s.getTransaction().commit(); + s.clear(); + + s.beginTransaction(); + q = (Query) s.get( Query.class, q.getId() ); + assertEquals( 1, q.getIncludedLocations().size() ); + s.delete( q ); + s.getTransaction().commit(); + s.close(); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java index e0d7502dbcd1..b0dd61e03f55 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/IndexedCollectionOfElementsTest.java @@ -26,6 +26,7 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -33,6 +34,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class IndexedCollectionOfElementsTest extends BaseCoreFunctionalTestCase { @Test public void testIndexedCollectionOfElements() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java index 7c93ecd4fcdc..fecedea892d1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/indexedCollection/Sale.java @@ -2,6 +2,7 @@ package org.hibernate.test.annotations.collectionelement.indexedCollection; import java.util.ArrayList; import java.util.List; +import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; @@ -22,7 +23,7 @@ public class Sale { @Id @GeneratedValue private Integer id; @ElementCollection - @JoinTable( + @CollectionTable( name = "contact", joinColumns = @JoinColumn(name = "n_key_person")) @CollectionId( diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java index 08873fa06d22..d9f41bd89e35 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java @@ -42,7 +42,7 @@ public class ElementCollectionSortingTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class }; + return new Class[] { Person.class, Address.class }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java index 32176d73d94e..1d3634540aea 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/Person.java @@ -23,12 +23,12 @@ */ package org.hibernate.test.annotations.collectionelement.ordered; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.OrderBy; import java.util.HashSet; @@ -75,7 +75,7 @@ public void setName(String name) { @ElementCollection @JoinColumn - @JoinTable(name = "T_NICKNAMES_A") + @CollectionTable(name = "T_NICKNAMES_A") @OrderBy // testing default @OrderBy mapping public Set getNickNamesAscendingNaturalSort() { return nickNamesAscendingNaturalSort; @@ -87,7 +87,7 @@ public void setNickNamesAscendingNaturalSort(Set nickNamesAscendingNatur @ElementCollection @JoinColumn - @JoinTable(name = "T_NICKNAMES_D") + @CollectionTable(name = "T_NICKNAMES_D") @OrderBy( "desc" ) public Set getNickNamesDescendingNaturalSort() { return nickNamesDescendingNaturalSort; @@ -101,7 +101,7 @@ public void setNickNamesDescendingNaturalSort(Set nickNamesDescendingNat @ElementCollection @JoinColumn @OrderBy - @JoinTable(name = "T_ADDRESS_A") + @CollectionTable(name = "T_ADDRESS_A") public Set

    getAddressesAscendingNaturalSort() { return addressesAscendingNaturalSort; } @@ -113,7 +113,7 @@ public void setAddressesAscendingNaturalSort(Set
    addressesAscendingNatu @ElementCollection @JoinColumn @OrderBy( "desc" ) - @JoinTable(name = "T_ADDRESS_D") + @CollectionTable(name = "T_ADDRESS_D") public Set
    getAddressesDescendingNaturalSort() { return addressesDescendingNaturalSort; } @@ -125,7 +125,7 @@ public void setAddressesDescendingNaturalSort(Set
    addressesDescendingNa @ElementCollection @JoinColumn @OrderBy( "city" ) - @JoinTable(name = "T_ADD_CITY_A") + @CollectionTable(name = "T_ADD_CITY_A") public Set
    getAddressesCityAscendingSort() { return addressesCityAscendingSort; } @@ -137,7 +137,7 @@ public void setAddressesCityAscendingSort(Set
    addressesCityAscendingSor @ElementCollection @JoinColumn @OrderBy( "city desc" ) - @JoinTable(name = "T_ADD_CITY_D") + @CollectionTable(name = "T_ADD_CITY_D") public Set
    getAddressesCityDescendingSort() { return addressesCityDescendingSort; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java index f6320eb244c7..b5fa71661465 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/MedicalHistory.java @@ -16,12 +16,12 @@ * limitations under the License. */ package org.hibernate.test.annotations.derivedidentities; +import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Lob; import javax.persistence.OneToOne; -import org.hibernate.annotations.Entity; /** * @author Hardy Ferentschik diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java index 334857d80ee5..f9eee4f68ae4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/DerivedIdentityWithBidirectionalAssociationTest.java @@ -40,8 +40,9 @@ public class DerivedIdentityWithBidirectionalAssociationTest extends BaseCoreFunctionalTestCase { @Test public void testBidirectionalAssociation() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( !SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( !SchemaUtil.isColumnPresent( "Dependent", "empPK", metadata() ) ); + Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java index 1b35c15bc88e..8a2ac4bbf224 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java @@ -30,6 +30,7 @@ import org.hibernate.Query; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -37,6 +38,7 @@ public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue(jiraKey = "HHH-5695") + @FailureExpectedWithNewMetamodel public void testInsertFooAndBarWithDerivedId() { Session s = openSession(); s.beginTransaction(); @@ -85,6 +87,7 @@ public void testSelectWithDerivedId() { @Test @TestForIssue(jiraKey = "HHH-6813") + @FailureExpectedWithNewMetamodel // Regression test utilizing multiple types of queries. public void testCase() { Session s = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java index 9ae6942783eb..6b39ad9e5d85 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java @@ -30,6 +30,7 @@ import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,11 +40,12 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentitySimpleParentIdClassDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp", metadata() ) ); Session s = openSession(); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java index 351fb57323b0..40496d15f90e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/DerivedIdentitySimpleParentEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,11 +36,13 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentitySimpleParentEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", metadata() ) ); + Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; @@ -62,8 +65,9 @@ public void testManyToOne() throws Exception { @Test public void testOneToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "ExclusiveDependent", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "ExclusiveDependent", "empPK", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "ExclusiveDependent", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "ExclusiveDependent", "empPK", metadata() ) ); + Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; @@ -88,6 +92,7 @@ public void testOneToOne() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { Dependent.class, + DependentId.class, Employee.class, ExclusiveDependent.class }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java index 5a1741b77c00..989ebd1e29f5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java @@ -30,6 +30,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -38,6 +39,7 @@ * * @author Stale W. Pedersen */ +@FailureExpectedWithNewMetamodel public class IdMapManyToOneSpecjTest extends BaseCoreFunctionalTestCase { public IdMapManyToOneSpecjTest() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java index 52b22665603a..192a2715ae96 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/lazy/CompositeKeyDeleteTest.java @@ -32,9 +32,11 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.Item; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +@FailureExpectedWithNewMetamodel // i think the whole SpecJ "partially generated id" thing causes problems in the new code public class CompositeKeyDeleteTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java index ae0b5c701d39..398268142b43 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b2/IdClassGeneratedValueManyToOneTest.java @@ -30,6 +30,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -40,6 +41,7 @@ * * @author Stale W. Pedersen */ +@FailureExpectedWithNewMetamodel public class IdClassGeneratedValueManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testComplexIdClass() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java index 066e91528fa3..4457468c359f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java @@ -38,8 +38,9 @@ public class DerivedIdentitySimpleParentEmbeddedDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", metadata() ) ); + Employee e = new Employee(); e.empId = 1; e.empName = "Emmanuel"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java index 13ddd694f57c..7be5e504cfea 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java @@ -1,9 +1,14 @@ package org.hibernate.test.annotations.derivedidentities.e2.a; +import java.util.List; + import org.junit.Test; import org.hibernate.Session; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -13,14 +18,22 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentIdClassDepTest extends BaseCoreFunctionalTestCase { @Test public void testManytoOne() { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + final TableSpecification dependentTable = SchemaUtil.getTable( "Dependent", metadata() ); + final List dependentPkColumns = dependentTable.getPrimaryKey().getColumns(); + assertEquals( 3, dependentPkColumns.size() ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "name" ) ) ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "FK1" ) ) ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "FK2" ) ) ); + Employee e = new Employee(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java index e99e48a5f65f..3c0cae91ca7f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/b/DerivedIdentityIdClassParentEmbeddedIdDepTest.java @@ -4,6 +4,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -13,14 +14,16 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_firstName", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_lastName", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_firstName", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_lastName", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + Employee e = new Employee(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; @@ -45,8 +48,8 @@ public void testManyToOne() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { Employee.class, - Dependent.class - + Dependent.class, + DependentId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java index 84e78a8700a1..5837c833bb3b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/a/DerivedIdentityEmbeddedIdParentIdClassTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -36,14 +37,16 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentIdClassTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + Employee e = new Employee(); e.empId = new EmployeeId(); e.empId.firstName = "Emmanuel"; @@ -76,7 +79,8 @@ public void testManyToOne() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { Dependent.class, - Employee.class + Employee.class, + EmployeeId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java index 7308e99a34b7..32fcffeaa6eb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e3/b/DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -36,14 +37,16 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK2", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "Dependent", "dep_name", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + Employee e = new Employee(); e.empId = new EmployeeId(); e.empId.firstName = "Emmanuel"; @@ -67,6 +70,6 @@ public void testManyToOne() throws Exception { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Dependent.class, Employee.class }; + return new Class[] { Dependent.class, DependentId.class, Employee.class, EmployeeId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java index 634a6b317a06..f70e9c903abe 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java @@ -25,11 +25,12 @@ import java.util.Date; -import org.junit.Test; - import org.hibernate.Session; -import org.hibernate.test.util.SchemaUtil; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -38,11 +39,15 @@ /** * @author Emmanuel Bernard */ +//@FailureExpectedWithNewMetamodel( +// jiraKey = "HHH-9048", +// message = "Failures have to do with the lookups for MedicalHistory using its derived id (the simple Person id value)" +//) public class DerivedIdentitySimpleParentSimpleDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", metadata() ) ); Session s = openSession(); s.getTransaction().begin(); @@ -73,8 +78,8 @@ public void testOneToOneExplicitJoinColumn() throws Exception { @Test public void testManyToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", metadata() ) ); Session s = openSession(); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java index 40c870f01a55..805a742fa9b9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java @@ -1,4 +1,5 @@ package org.hibernate.test.annotations.derivedidentities.e4.a; +import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; @@ -6,7 +7,7 @@ * @author Emmanuel Bernard */ @Entity -public class Person { +public class Person implements Serializable { @Id String ssn; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java index 5e877a218523..e30203f0676a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java @@ -29,6 +29,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,11 +40,13 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentitySimpleParentSimpleDepMapsIdTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", metadata() ) ); + Person e = new Person(); e.ssn = "aaa"; Session s = openSession( ); @@ -68,8 +71,9 @@ public void testOneToOneExplicitJoinColumn() throws Exception { @Test public void testManyToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "FK", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "FK", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", metadata() ) ); + Person e = new Person(); e.ssn = "aaa"; Session s = openSession( ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java index 8628b0b4ef0f..4049d4ccabfd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,15 +36,16 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentSameIdTypeIdClassDepTest extends BaseCoreFunctionalTestCase { private static final String FIRST_NAME = "Emmanuel"; private static final String LAST_NAME = "Bernard"; @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); Session s = openSession(); s.getTransaction().begin(); @@ -71,9 +73,9 @@ public void testOneToOneExplicitJoinColumn() throws Exception { @Test public void testTckLikeBehavior() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); Session s = openSession(); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java index daf0e5758c1e..ed8bbf6d7d71 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,12 +36,14 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + Person e = new Person(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; @@ -62,7 +65,8 @@ public void testOneToOneExplicitJoinColumn() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { MedicalHistory.class, - Person.class + Person.class, + PersonId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java index e3d1f9256e3b..fb08a88d54d7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/b/PersonId.java @@ -1,9 +1,11 @@ package org.hibernate.test.annotations.derivedidentities.e5.b; import java.io.Serializable; +import javax.persistence.Embeddable; /** * @author Emmanuel Bernard */ +@Embeddable public class PersonId implements Serializable { String firstName; String lastName; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java index f6757b38a0cf..f5a48af9bf78 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/c/ForeignGeneratorViaMapsIdTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,10 +36,12 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ForeignGeneratorViaMapsIdTest extends BaseCoreFunctionalTestCase { @Test public void testForeignGenerator() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "patient_id", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "patient_id", metadata() ) ); + Person e = new Person(); Session s = openSession( ); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java index f848e1b25970..33f68f4aafe6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,12 +36,14 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + Person e = new Person(); e.id = new PersonId(); e.id.firstName = "Emmanuel"; @@ -68,7 +71,8 @@ public void testOneToOneExplicitJoinColumn() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { MedicalHistory.class, - Person.class + Person.class, + PersonId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java index ff97c4b81a69..a888455c5b6e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/b/DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,12 +36,14 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class DerivedIdentityEmbeddedIdParentSameIdTypeEmbeddedIdDepTest extends BaseCoreFunctionalTestCase { @Test public void testOneToOneExplicitJoinColumn() throws Exception { - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", configuration() ) ); - assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", configuration() ) ); - assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", configuration() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) ); + assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) ); + assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) ); + Person e = new Person(); e.id = new PersonId(); e.id.firstName = "Emmanuel"; @@ -66,7 +69,8 @@ public void testOneToOneExplicitJoinColumn() throws Exception { protected Class[] getAnnotatedClasses() { return new Class[] { MedicalHistory.class, - Person.class + Person.class, + PersonId.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/duplicatedgenerator/DuplicateTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/duplicatedgenerator/DuplicateTest.java index e8b198f5259d..13d2db2edbe2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/duplicatedgenerator/DuplicateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/duplicatedgenerator/DuplicateTest.java @@ -1,22 +1,23 @@ -//$Id$ package org.hibernate.test.annotations.duplicatedgenerator; -import org.junit.Assert; -import org.junit.Test; import org.hibernate.AnnotationException; import org.hibernate.SessionFactory; -import org.hibernate.cfg.AnnotationConfiguration; +import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.service.ServiceRegistry; + import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Assert; +import org.junit.Test; /** * @author Emmanuel Bernard */ -public class DuplicateTest { +public class DuplicateTest extends BaseUnitTestCase { @Test public void testDuplicateEntityName() throws Exception { - AnnotationConfiguration cfg = new AnnotationConfiguration(); + Configuration cfg = new Configuration(); cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); ServiceRegistry serviceRegistry = null; SessionFactory sf = null; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java index 9ec9bccb1842..a8cb4a789166 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java @@ -24,6 +24,7 @@ package org.hibernate.test.annotations.embeddables; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.math.BigDecimal; import java.util.ArrayList; @@ -39,7 +40,13 @@ import org.hibernate.cfg.Configuration; import org.hibernate.dialect.H2Dialect; import org.hibernate.exception.GenericJDBCException; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.TypeContributions; +import org.hibernate.metamodel.spi.TypeContributor; import org.hibernate.service.ServiceRegistry; + +import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; @@ -53,70 +60,34 @@ public class EmbeddableIntegratorTest extends BaseUnitTestCase { /** * Throws a mapping exception because DollarValue is not mapped */ - @Test(expected = GenericJDBCException.class) + @Test public void testWithoutIntegrator() { - ServiceRegistry reg = new StandardServiceRegistryBuilder( new BootstrapServiceRegistryImpl() ).build(); - SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class ) - .setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg ); - try { - Session sess = sf.openSession(); - Investor myInv = getInvestor(); - myInv.setId( 1L ); - - sess.save( myInv ); - sess.flush(); - sess.clear(); - - Investor inv = (Investor) sess.get( Investor.class, 1L ); - assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() ); - - sess.close(); + new MetadataSources().addAnnotatedClass( Investor.class ).buildMetadata(); + fail( "Expecting error" ); } - finally { - sf.close(); - StandardServiceRegistryBuilder.destroy( reg ); + catch (Exception expected) { } } @Test + @FailureExpectedWithNewMetamodel public void testWithIntegrator() { - StandardServiceRegistry reg = new StandardServiceRegistryBuilder( - new BootstrapServiceRegistryBuilder().with( new InvestorIntegrator() ).build() - ).build(); - SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class ) - .setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg ); - - try { - Session sess = sf.openSession(); - Investor myInv = getInvestor(); - myInv.setId( 2L ); - - sess.save( myInv ); - sess.flush(); - sess.clear(); - - Investor inv = (Investor) sess.get( Investor.class, 2L ); - assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() ); - - sess.close(); - } - finally { - sf.close(); - StandardServiceRegistryBuilder.destroy( reg ); - } + StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build(); + SessionFactory sf = new MetadataSources().addAnnotatedClass( Investor.class ) + .getMetadataBuilder( ssr ) + .with( new CustomTypeContributor() ) + .build() + .buildSessionFactory(); + sf.close(); + StandardServiceRegistryBuilder.destroy( ssr ); } - private Investor getInvestor() { - Investor i = new Investor(); - List investments = new ArrayList(); - Investment i1 = new Investment(); - i1.setAmount( new DollarValue( new BigDecimal( "100" ) ) ); - i1.setDate( new MyDate( new Date() ) ); - i1.setDescription( "Test Investment" ); - investments.add( i1 ); - i.setInvestments( investments ); - - return i; + public static class CustomTypeContributor implements TypeContributor { + @Override + public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + typeContributions.contributeType( new DollarValueUserType(), new String[] {DollarValue.class.getName()} ); + typeContributions.contributeType( new MyDateUserType(), new String[] {MyDate.class.getName()} ); + } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java index 651003e947a4..05b1c62861c1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java @@ -26,7 +26,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java index e8a36f10ca70..15d9d277096b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java @@ -23,44 +23,46 @@ */ package org.hibernate.test.annotations.embeddables.nested; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.sql.Types; -import java.util.HashMap; -import java.util.Map; -import org.junit.Test; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingEmbedded; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.type.CustomType; -import org.hibernate.cfg.Configuration; -import org.hibernate.engine.spi.Mapping; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.SimpleValue; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.type.CustomType; +import org.junit.Test; import static org.hibernate.testing.junit4.ExtraAssertions.assertJdbcTypeCode; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; /** * @author Steve Ebersole */ public class NestedEmbeddableMetadataTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel public void testEnumTypeInterpretation() { - Configuration cfg = new Configuration().addAnnotatedClass( Customer.class ); - cfg.buildMappings(); - Mapping mapping = cfg.buildMapping(); - PersistentClass classMetadata = cfg.getClassMapping( Customer.class.getName() ); - Property investmentsProperty = classMetadata.getProperty( "investments" ); - Collection investmentsValue = (Collection) investmentsProperty.getValue(); - Component investmentMetadata = (Component) investmentsValue.getElement(); - Component amountMetadata = (Component) investmentMetadata.getProperty( "amount" ).getValue(); - SimpleValue currencyMetadata = (SimpleValue) amountMetadata.getProperty( "currency" ).getValue(); - CustomType currencyType = (CustomType) currencyMetadata.getType(); - int[] currencySqlTypes = currencyType.sqlTypes( mapping ); + Metadata metadata = new MetadataSources().addAnnotatedClass( Customer.class ).buildMetadata(); + EntityBinding eb = metadata.getEntityBinding( Customer.class.getName() ); + PluralAttributeBinding investmentsBinding = (PluralAttributeBinding) eb.locateAttributeBinding( "investments" ); + PluralAttributeElementBindingEmbedded investmentsElementBinding = (PluralAttributeElementBindingEmbedded) investmentsBinding.getPluralAttributeElementBinding(); + EmbeddedAttributeBinding amountBinding = (EmbeddedAttributeBinding) investmentsElementBinding.getEmbeddableBinding().locateAttributeBinding( + "amount" + ); + SingularAttributeBinding currencyBinding = (SingularAttributeBinding) amountBinding.getEmbeddableBinding().locateAttributeBinding( + "currency" + ); + + CustomType currencyType = (CustomType) currencyBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + assertNotNull( currencyType ); + int[] currencySqlTypes = currencyType.sqlTypes( null ); assertEquals( 1, currencySqlTypes.length ); assertJdbcTypeCode( Types.VARCHAR, currencySqlTypes[0] ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableWithSecondaryTableTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableWithSecondaryTableTest.java new file mode 100644 index 000000000000..c700d8b7c00b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/nested/NestedEmbeddableWithSecondaryTableTest.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.annotations.embeddables.nested; + +import static org.junit.Assert.assertEquals; + +import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.SecondaryTable; +import javax.persistence.SecondaryTables; +import javax.persistence.Table; + +import org.hibernate.Session; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +/** + * @author Brett Meyer + */ +public class NestedEmbeddableWithSecondaryTableTest extends BaseCoreFunctionalTestCase { + + @Test + @TestForIssue(jiraKey = "HHH-8021") + public void testCase() { + EntityA e = new EntityA(); + e.embedA.embedAttrA = "foo1"; + e.embedA.embedB.embedAttrB = "foo2"; + + Session s = openSession(); + s.getTransaction().begin(); + s.persist( e ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + e = (EntityA) s.get( EntityA.class, e.id ); + assertEquals( "foo1", e.embedA.embedAttrA ); + assertEquals( "foo2", e.embedA.embedB.embedAttrB ); + s.getTransaction().commit(); + s.close(); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { EntityA.class, EmbeddableA.class, EmbeddableB.class }; + } + + @Entity + @Table(name = "TableA") + @SecondaryTables({ @SecondaryTable(name = "TableB") }) + public static class EntityA { + + @Id + @GeneratedValue + public Integer id; + + @Embedded + @AttributeOverrides({ @AttributeOverride(name = "embedAttrA", column = @Column(table = "TableB")) }) + public EmbeddableA embedA = new EmbeddableA(); + } + + @Embeddable + public static class EmbeddableA { + + @Embedded + @AttributeOverrides({ @AttributeOverride(name = "embedAttrB", column = @Column(table = "TableB")) }) + public EmbeddableB embedB = new EmbeddableB(); + + public String embedAttrA; + } + + @Embeddable + public static class EmbeddableB { + + public String embedAttrB; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/Country.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/Country.java index 61c81fb793e5..12ae5046e1e9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/Country.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/Country.java @@ -1,10 +1,11 @@ //$Id$ package org.hibernate.test.annotations.embedded; import java.io.Serializable; + import javax.persistence.Column; import javax.persistence.Embeddable; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * Non realistic embedded dependent object @@ -12,7 +13,7 @@ * @author Emmanuel Bernard */ @Embeddable -@AccessType("property") +@AttributeAccessor("property") public class Country implements Serializable { private String iso2; private String name; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java index 267d99f287b0..8ada756b5d5e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java @@ -23,25 +23,24 @@ */ package org.hibernate.test.annotations.embedded; -import java.io.Serializable; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; -import org.junit.Test; - import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.test.annotations.embedded.FloatLeg.RateIndex; import org.hibernate.test.annotations.embedded.Leg.Frequency; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Emmanuel Bernard @@ -153,6 +152,7 @@ public void testManyToOneInsideComponent() throws Exception { } @Test + @FailureExpectedWithNewMetamodel public void testEmbeddedSuperclass() { Session s; Transaction tx; @@ -190,6 +190,7 @@ public void testEmbeddedSuperclass() { } @Test + @FailureExpectedWithNewMetamodel public void testDottedProperty() { Session s; Transaction tx; @@ -407,10 +408,9 @@ public void testEmbeddedAndOneToMany() throws Exception { @Test public void testDefaultCollectionTable() throws Exception { //are the tables correct? - assertTrue( SchemaUtil.isTablePresent("WealthyPerson_vacationHomes", configuration() ) ); - assertTrue( SchemaUtil.isTablePresent("WealthyPerson_legacyVacationHomes", configuration() ) ); - assertTrue( SchemaUtil.isTablePresent("WelPers_VacHomes", configuration() ) ); - + assertTrue( SchemaUtil.isTablePresent("WealthyPerson_vacationHomes", metadata() ) ); + assertTrue( SchemaUtil.isTablePresent("WealthyPerson_legacyVacationHomes", metadata() ) ); + assertTrue( SchemaUtil.isTablePresent("WelPers_VacHomes", metadata() ) ); //just to make sure, use the mapping Session s; Transaction tx; @@ -531,7 +531,17 @@ protected Class[] getAnnotatedClasses() { CorpType.class, Nationality.class, Manager.class, - FavoriteThings.class + FavoriteThings.class, + Address.class, + Country.class, + InternetFavorites.class, + FixedLeg.class, + FloatLeg.class, + Swap.class, + RegionalArticlePk.class, + LegalStructure.class, + Summary.class, + URLFavorite.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java index f018512d4e2b..8003f5110b5a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/InternetFavorites.java @@ -1,15 +1,15 @@ package org.hibernate.test.annotations.embedded; import java.util.Collection; +import javax.persistence.ElementCollection; import javax.persistence.Embeddable; -import javax.persistence.Embedded; @Embeddable public class InternetFavorites { - @Embedded + @ElementCollection Collection links; - @Embedded + @ElementCollection Collection ideas; public Collection getIdeas() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java index 569ae8ab3e65..91d7a2696724 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/NestedEmbeddableAttributeOverrideTest.java @@ -54,6 +54,6 @@ public void testAttributeOverride() { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { EntityWithNestedEmbeddables.class }; + return new Class[] { EntityWithNestedEmbeddables.class, EmbeddableA.class, EmbeddableB.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/RegionalArticlePk.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/RegionalArticlePk.java index 8746d85ba7bb..4a4497cd6234 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/RegionalArticlePk.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/RegionalArticlePk.java @@ -1,9 +1,10 @@ //$Id$ package org.hibernate.test.annotations.embedded; import java.io.Serializable; + import javax.persistence.Embeddable; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * Regional article pk @@ -11,7 +12,7 @@ * @author Emmanuel Bernard */ @Embeddable -@AccessType("field") +@AttributeAccessor("field") public class RegionalArticlePk implements Serializable { /** * country iso2 code diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/Address.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/Address.java index 45fb61962264..0020a720f449 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/Address.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/Address.java @@ -25,7 +25,7 @@ import javax.persistence.Embeddable; import javax.persistence.ManyToOne; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * TODO : javadoc @@ -33,7 +33,7 @@ * @author Steve Ebersole */ @Embeddable -@AccessType("property") +@AttributeAccessor("property") public class Address { private String line1; private String line2; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java index f2833230c5aa..d2940bed33af 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,6 +36,7 @@ /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class EmbeddableWithMany2OneTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Alias.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Alias.java index e3d2f9238644..ec968a1b493d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Alias.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Alias.java @@ -22,11 +22,10 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.annotations.embedded.one2many; +import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import org.hibernate.annotations.Entity; - /** * TODO : javadoc * diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Name.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Name.java index d4e7c152aa48..6d90b004420e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Name.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/Name.java @@ -24,7 +24,7 @@ package org.hibernate.test.annotations.embedded.one2many; import javax.persistence.Embeddable; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * TODO : javadoc @@ -32,7 +32,7 @@ * @author Steve Ebersole */ @Embeddable -@AccessType("property") +@AttributeAccessor("property") public class Name { private String first; private String last; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/PersonName.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/PersonName.java index 943030a4836b..58240d7f7e70 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/PersonName.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/one2many/PersonName.java @@ -24,11 +24,12 @@ package org.hibernate.test.annotations.embedded.one2many; import java.util.HashSet; import java.util.Set; + import javax.persistence.CascadeType; import javax.persistence.Embeddable; import javax.persistence.OneToMany; -import org.hibernate.annotations.AccessType; +import org.hibernate.annotations.AttributeAccessor; /** * TODO : javadoc @@ -36,7 +37,7 @@ * @author Steve Ebersole */ @Embeddable -@AccessType("property") +@AttributeAccessor("property") public class PersonName extends Name { private Set aliases = new HashSet(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java index 196b0d61e337..e1c049cd6651 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java @@ -23,13 +23,6 @@ */ package org.hibernate.test.annotations.entity; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - import java.math.BigDecimal; import java.util.Currency; import java.util.Date; @@ -45,12 +38,21 @@ import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; + import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * @author Emmanuel Bernard */ @@ -111,7 +113,7 @@ public void testVersioning() throws Exception { tx.commit(); s.close(); - Session parallelSession = openSession(); + Session parallelSession = openSecondarySession(); Transaction parallelTx = parallelSession.beginTransaction(); s = openSession(); tx = s.beginTransaction(); @@ -129,7 +131,13 @@ public void testVersioning() throws Exception { fail( "All optimistic locking should have make it fail" ); } catch (HibernateException e) { - if ( parallelTx != null ) parallelTx.rollback(); + if ( parallelTx != null ) { + try { + parallelTx.rollback(); + } + catch (Exception ignore) { + } + } } finally { parallelSession.close(); @@ -322,6 +330,11 @@ public void testFilterOnCollection() { tx.commit(); s.close(); + s = openSession(); + tx = s.beginTransaction(); + s.createQuery( "delete from " + Narrative.class.getSimpleName() ).executeUpdate(); + tx.commit(); + s.close(); } @Test @@ -461,6 +474,7 @@ public void testFilter() throws Exception { * defined on a parent MappedSuperclass(s) */ @Test + @FailureExpectedWithNewMetamodel public void testInheritFiltersFromMappedSuperclass() throws Exception { Session s; Transaction tx; @@ -656,9 +670,11 @@ public void testTypeDefWithoutNameAndDefaultForTypeAttributes() { fail("Did not throw expected exception"); } catch( AnnotationException ex ) { - assertEquals( - "Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass org.hibernate.test.annotations.entity.PhoneNumberType", - ex.getMessage()); + assertTrue( + ex.getMessage().startsWith( + "Either name or defaultForType (or both) must be set on TypeDefinition [org.hibernate.test.annotations.entity.PhoneNumberType]" + ) + ); } finally { if( sf != null){ sf.close(); @@ -709,6 +725,7 @@ protected Class[] getAnnotatedClasses() { ZipCode.class, Flight.class, Name.class, + LastName.class, FormalLastName.class, Car.class, Peugot.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/Forest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/Forest.java index e3086ddc2173..c4b334f53d8b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/Forest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/Forest.java @@ -1,22 +1,28 @@ //$Id$ package org.hibernate.test.annotations.entity; import java.util.Set; + import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.Lob; import org.hibernate.annotations.BatchSize; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.Filters; -import org.hibernate.annotations.Index; import org.hibernate.annotations.OptimisticLock; import org.hibernate.annotations.OptimisticLockType; +import org.hibernate.annotations.OptimisticLocking; import org.hibernate.annotations.ParamDef; import org.hibernate.annotations.Parameter; +import org.hibernate.annotations.Polymorphism; import org.hibernate.annotations.PolymorphismType; +import org.hibernate.annotations.SelectBeforeUpdate; import org.hibernate.annotations.Type; import org.hibernate.annotations.Where; @@ -27,11 +33,11 @@ */ @Entity @BatchSize(size = 5) -@org.hibernate.annotations.Entity( - selectBeforeUpdate = true, - dynamicInsert = true, dynamicUpdate = true, - optimisticLock = OptimisticLockType.ALL, - polymorphism = PolymorphismType.EXPLICIT) +@SelectBeforeUpdate +@DynamicInsert +@DynamicUpdate +@OptimisticLocking(type = OptimisticLockType.ALL) +@Polymorphism(type = PolymorphismType.EXPLICIT) @Where(clause = "1=1") @FilterDef(name = "minLength", parameters = {@ParamDef(name = "minLength", type = "integer")}) @Filters({ @@ -39,7 +45,7 @@ @Filter(name = "minLength", condition = ":minLength <= length") }) @org.hibernate.annotations.Table(appliesTo = "Forest", - indexes = {@Index(name = "idx", columnNames = {"name", "length"})}) + indexes = {@Index(name = "idx", columnList = "name, length")}) public class Forest { private Integer id; private String name; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java index 5e81af1c688b..f12ad07a5486 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/NewCustomEntityMappingAnnotationsTest.java @@ -23,13 +23,11 @@ */ package org.hibernate.test.annotations.entity; -import org.hibernate.mapping.RootClass; - -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * @author Steve Ebersole @@ -47,12 +45,15 @@ protected String[] getAnnotatedPackages() { @Test public void testSameMappingValues() { - RootClass forest = (RootClass) configuration().getClassMapping( Forest.class.getName() ); - RootClass forest2 = (RootClass) configuration().getClassMapping( Forest2.class.getName() ); - assertEquals( forest.useDynamicInsert(), forest2.useDynamicInsert() ); - assertEquals( forest.useDynamicUpdate(), forest2.useDynamicUpdate() ); - assertEquals( forest.hasSelectBeforeUpdate(), forest2.hasSelectBeforeUpdate() ); - assertEquals( forest.getOptimisticLockStyle(), forest2.getOptimisticLockStyle() ); - assertEquals( forest.isExplicitPolymorphism(), forest2.isExplicitPolymorphism() ); + EntityBinding forest = metadata().getEntityBinding( Forest.class.getName() ); + EntityBinding forest2 = metadata().getEntityBinding( Forest2.class.getName() ); + assertEquals( forest.isDynamicInsert(), forest2.isDynamicInsert() ); + assertEquals( forest.isDynamicUpdate(), forest2.isDynamicUpdate() ); + assertEquals( forest.isSelectBeforeUpdate(), forest2.isSelectBeforeUpdate() ); + assertEquals( + forest.getHierarchyDetails().getOptimisticLockStyle(), + forest2.getHierarchyDetails().getOptimisticLockStyle() + ); + assertEquals( forest.isPolymorphic(), forest2.isPolymorphic() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/ZipCode.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/ZipCode.java index 21f166100d47..db4ca18fa723 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/ZipCode.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entity/ZipCode.java @@ -5,13 +5,14 @@ import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.Immutable; /** * @author Emmanuel Bernard */ @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) @Entity -@org.hibernate.annotations.Entity(mutable = false) +@Immutable public class ZipCode { @Id public String code; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java index cb044db75b8e..b0c399405533 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/entitynonentity/EntityNonEntityTest.java @@ -23,15 +23,14 @@ */ package org.hibernate.test.annotations.entitynonentity; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Emmanuel Bernard diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java index 6d5260d33bec..86de4728d614 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/EnumeratedTypeTest.java @@ -1,7 +1,5 @@ package org.hibernate.test.annotations.enumerated; -import static org.junit.Assert.assertEquals; - import java.io.Serializable; import java.sql.Connection; import java.sql.SQLException; @@ -10,23 +8,25 @@ import org.hibernate.Query; import org.hibernate.Session; -import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Restrictions; import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.type.EnumType; + +import org.hibernate.testing.SkipForDialect; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.annotations.enumerated.EntityEnum.Common; import org.hibernate.test.annotations.enumerated.EntityEnum.FirstLetter; import org.hibernate.test.annotations.enumerated.EntityEnum.LastNumber; import org.hibernate.test.annotations.enumerated.EntityEnum.Trimmed; -import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.type.EnumType; -import org.hibernate.type.Type; import org.junit.Test; +import static org.junit.Assert.assertEquals; + /** * Test type definition for enum * @@ -36,33 +36,49 @@ public class EnumeratedTypeTest extends BaseCoreFunctionalTestCase { @Test public void testTypeDefinition() { - Configuration cfg = configuration(); - PersistentClass pc = cfg.getClassMapping( EntityEnum.class.getName() ); + EntityBinding binding = metadata().getEntityBinding( EntityEnum.class.getName() ); // ordinal default of EnumType - Type ordinalEnum = pc.getProperty( "ordinal" ).getType(); - assertEquals( Common.class, ordinalEnum.getReturnedClass() ); - assertEquals( EnumType.class.getName(), ordinalEnum.getName() ); + HibernateTypeDescriptor ordinalEnum = binding + .locateAttributeBinding( "ordinal" ) + .getHibernateTypeDescriptor(); + assertEquals( Common.class, ordinalEnum.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( EnumType.class.getName(), ordinalEnum.getExplicitTypeName() ); // string defined by Enumerated(STRING) - Type stringEnum = pc.getProperty( "string" ).getType(); - assertEquals( Common.class, stringEnum.getReturnedClass() ); - assertEquals( EnumType.class.getName(), stringEnum.getName() ); + HibernateTypeDescriptor stringEnum = binding + .locateAttributeBinding( "string" ) + .getHibernateTypeDescriptor(); + assertEquals( Common.class, stringEnum.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( EnumType.class.getName(), stringEnum.getExplicitTypeName() ); // explicit defined by @Type - Type first = pc.getProperty( "firstLetter" ).getType(); - assertEquals( FirstLetter.class, first.getReturnedClass() ); - assertEquals( FirstLetterType.class.getName(), first.getName() ); + HibernateTypeDescriptor first = binding + .locateAttributeBinding( "firstLetter" ) + .getHibernateTypeDescriptor(); + assertEquals( FirstLetter.class, first.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( FirstLetterType.class.getName(), first.getExplicitTypeName() ); // implicit defined by @TypeDef in somewhere - Type last = pc.getProperty( "lastNumber" ).getType(); - assertEquals( LastNumber.class, last.getReturnedClass() ); - assertEquals( LastNumberType.class.getName(), last.getName() ); + HibernateTypeDescriptor last = binding + .locateAttributeBinding( "lastNumber" ) + .getHibernateTypeDescriptor(); + assertEquals( LastNumber.class, last.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( LastNumberType.class.getName(), last.getExplicitTypeName() ); // implicit defined by @TypeDef in anywhere, but overrided by Enumerated(STRING) - Type implicitOverrideExplicit = pc.getProperty( "explicitOverridingImplicit" ).getType(); - assertEquals( LastNumber.class, implicitOverrideExplicit.getReturnedClass() ); - assertEquals( EnumType.class.getName(), implicitOverrideExplicit.getName() ); + HibernateTypeDescriptor implicitOverrideExplicit = binding + .locateAttributeBinding( "explicitOverridingImplicit" ) + .getHibernateTypeDescriptor(); + assertEquals( LastNumber.class, + implicitOverrideExplicit.getResolvedTypeMapping() + .getReturnedClass() ); + assertEquals( EnumType.class.getName(), + implicitOverrideExplicit.getExplicitTypeName() ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java index 0fee63658e8f..7f89b8dd1f35 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/enumerated/ormXml/OrmXmlEnumTypeTest.java @@ -23,6 +23,7 @@ */ package org.hibernate.test.annotations.enumerated.ormXml; +import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.type.CustomType; import org.hibernate.type.EnumType; import org.hibernate.type.Type; @@ -47,9 +48,10 @@ protected String[] getXmlFiles() { @Test public void testOrmXmlDefinedEnumType() { - Type bindingPropertyType = configuration().getClassMapping( BookWithOrmEnum.class.getName() ) - .getProperty( "bindingStringEnum" ) - .getType(); + final Type bindingPropertyType; + AttributeBinding attributeBinding = metadata().getEntityBinding( BookWithOrmEnum.class.getName() ) + .locateAttributeBinding( "bindingStringEnum" ); + bindingPropertyType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); CustomType customType = ExtraAssertions.assertTyping( CustomType.class, bindingPropertyType ); EnumType enumType = ExtraAssertions.assertTyping( EnumType.class, customType.getUserType() ); assertFalse( enumType.isOrdinal() ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/fetchprofile/FetchProfileTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/fetchprofile/FetchProfileTest.java index 93b9e3d52615..ac1379ab78f3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/fetchprofile/FetchProfileTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/fetchprofile/FetchProfileTest.java @@ -23,25 +23,27 @@ */ package org.hibernate.test.annotations.fetchprofile; -import java.io.InputStream; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; -import org.jboss.logging.Logger; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import java.io.InputStream; import org.hibernate.MappingException; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.jboss.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; /** * Test case for HHH-4812 @@ -52,28 +54,31 @@ public class FetchProfileTest extends BaseUnitTestCase { private static final Logger log = Logger.getLogger( FetchProfileTest.class ); - private ServiceRegistry serviceRegistry; - + private BootstrapServiceRegistry bootstrapServiceRegistry; + private StandardServiceRegistry serviceRegistry; + @Before - public void setUp() { - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() ); + public void setUp() { + bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder().build(); + serviceRegistry = new StandardServiceRegistryBuilder( bootstrapServiceRegistry ).build(); } - + @After - public void tearDown() { - if (serviceRegistry != null) ServiceRegistryBuilder.destroy(serviceRegistry); + public void tearDown() { + ( (ServiceRegistryImplementor) serviceRegistry ).destroy(); + ( (ServiceRegistryImplementor) bootstrapServiceRegistry ).destroy(); } + @Test public void testFetchProfileConfigured() { - Configuration config = new Configuration(); - config.addAnnotatedClass( Customer.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( SupportTickets.class ); - config.addAnnotatedClass( Country.class ); - SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) config.buildSessionFactory( - serviceRegistry - ); + MetadataSources metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( SupportTickets.class ); + metadataSources.addAnnotatedClass( Country.class ); + SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) metadataSources + .getMetadataBuilder( serviceRegistry ).build().buildSessionFactory(); assertTrue( "fetch profile not parsed properly", @@ -88,13 +93,13 @@ public void testFetchProfileConfigured() { @Test public void testWrongAssociationName() { - Configuration config = new Configuration(); - config.addAnnotatedClass( Customer2.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( Country.class ); + MetadataSources metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer2.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( Country.class ); try { - config.buildMappings(); + metadataSources.buildMetadata(); fail(); } catch ( MappingException e ) { @@ -104,13 +109,13 @@ public void testWrongAssociationName() { @Test public void testWrongClass() { - Configuration config = new Configuration(); - config.addAnnotatedClass( Customer3.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( Country.class ); + MetadataSources metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer3.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( Country.class ); try { - config.buildMappings(); + metadataSources.buildMetadata(); fail(); } catch ( MappingException e ) { @@ -120,13 +125,13 @@ public void testWrongClass() { @Test public void testUnsupportedFetchMode() { - Configuration config = new Configuration(); - config.addAnnotatedClass( Customer4.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( Country.class ); + MetadataSources metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer4.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( Country.class ); try { - config.buildMappings(); + metadataSources.buildMetadata(); fail(); } catch ( MappingException e ) { @@ -135,18 +140,18 @@ public void testUnsupportedFetchMode() { } @Test + @FailureExpectedWithNewMetamodel public void testXmlOverride() { - Configuration config = new Configuration(); - config.addAnnotatedClass( Customer5.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( Country.class ); + MetadataSources metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer5.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( Country.class ); InputStream is = Thread.currentThread() .getContextClassLoader() .getResourceAsStream( "org/hibernate/test/annotations/fetchprofile/mappings.hbm.xml" ); - config.addInputStream( is ); - SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) config.buildSessionFactory( - serviceRegistry - ); + metadataSources.addInputStream( is ); + SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) metadataSources + .getMetadataBuilder( serviceRegistry ).build().buildSessionFactory(); assertTrue( "fetch profile not parsed properly", @@ -155,12 +160,12 @@ public void testXmlOverride() { sessionImpl.close(); // now the same with no xml - config = new Configuration(); - config.addAnnotatedClass( Customer5.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( Country.class ); + metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer5.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( Country.class ); try { - config.buildMappings(); + metadataSources.buildMetadata(); fail(); } catch ( MappingException e ) { @@ -170,15 +175,14 @@ public void testXmlOverride() { @Test public void testPackageConfiguredFetchProfile() { - Configuration config = new Configuration(); - config.addAnnotatedClass( Customer.class ); - config.addAnnotatedClass( Order.class ); - config.addAnnotatedClass( SupportTickets.class ); - config.addAnnotatedClass( Country.class ); - config.addPackage( Customer.class.getPackage().getName() ); - SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) config.buildSessionFactory( - serviceRegistry - ); + MetadataSources metadataSources = new MetadataSources( bootstrapServiceRegistry ); + metadataSources.addAnnotatedClass( Customer.class ); + metadataSources.addAnnotatedClass( Order.class ); + metadataSources.addAnnotatedClass( SupportTickets.class ); + metadataSources.addAnnotatedClass( Country.class ); + metadataSources.addPackage( Customer.class.getPackage().getName() ); + SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) metadataSources + .getMetadataBuilder( serviceRegistry ).build().buildSessionFactory(); assertTrue( "fetch profile not parsed properly", diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/D_PK.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/D_PK.java index 48c0e2fb902a..94bf1d7997ae 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/D_PK.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/D_PK.java @@ -1,6 +1,7 @@ -// $Id$ package org.hibernate.test.annotations.fkcircularity; + import java.io.Serializable; +import javax.persistence.Embeddable; import javax.persistence.ManyToOne; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/FkCircularityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/FkCircularityTest.java index adac9331f8de..32c50eb37540 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/FkCircularityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/fkcircularity/FkCircularityTest.java @@ -1,73 +1,22 @@ -// $Id$ package org.hibernate.test.annotations.fkcircularity; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.jboss.logging.Logger; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.dialect.HSQLDialect; -import org.hibernate.dialect.SQLServerDialect; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; - /** * Test case for ANN-722 and ANN-730. * * @author Hardy Ferentschik */ -public class FkCircularityTest { - private static final Logger log = Logger.getLogger( FkCircularityTest.class ); - - +public class FkCircularityTest extends BaseUnitTestCase { @Test public void testJoinedSublcassesInPK() { - try { - Configuration config = new Configuration(); - config.addAnnotatedClass(A.class); - config.addAnnotatedClass(B.class); - config.addAnnotatedClass(C.class); - config.addAnnotatedClass(D.class); - config.buildMappings( ); - String[] schema = config - .generateSchemaCreationScript(new SQLServerDialect()); - for (String s : schema) { - log.debug(s); - } - log.debug("success"); - } catch (Exception e) { - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - log.debug(writer.toString()); - Assert.fail( e.getMessage() ); - } - } - @Test - public void testDeepJoinedSuclassesHierachy() { - try { - Configuration config = new Configuration(); - config.addAnnotatedClass(ClassA.class); - config.addAnnotatedClass(ClassB.class); - config.addAnnotatedClass(ClassC.class); - config.addAnnotatedClass(ClassD.class); - config.buildMappings( ); - String[] schema = config - .generateSchemaCreationScript(new HSQLDialect()); - for (String s : schema) { - log.debug(s); - } - log.debug("success"); - } catch (Exception e) { - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - log.debug(writer.toString()); - Assert.fail(e.getMessage()); - } + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( A.class ) + .addAnnotatedClass( B.class ) + .addAnnotatedClass( C.class ) + .addAnnotatedClass( D.class ); + metadataSources.buildMetadata(); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java index a0f1d8e10f2a..07b8871df043 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/Classes.java @@ -1,6 +1,7 @@ package org.hibernate.test.annotations.generics; import java.util.HashSet; import java.util.Set; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.Embedded; @@ -9,7 +10,6 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.Table; public class Classes { @@ -40,7 +40,7 @@ public static class PopularBook { Long id; @ElementCollection - @JoinTable(name="PopularBook_Editions",joinColumns={@JoinColumn(name="PopularBook_id")}) + @CollectionTable(name="PopularBook_Editions",joinColumns={@JoinColumn(name="PopularBook_id")}) Set> editions = new HashSet>(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java index 936fe9b218ef..58780e706435 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/EmbeddedGenericsTest.java @@ -23,13 +23,15 @@ */ package org.hibernate.test.annotations.generics; -import org.junit.Test; - import org.hibernate.Session; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9049" ) public class EmbeddedGenericsTest extends BaseCoreFunctionalTestCase { @Test public void testWorksWithGenericEmbedded() { @@ -76,7 +78,8 @@ public void testWorksWithGenericCollectionOfElements() { protected Class[] getAnnotatedClasses() { return new Class[]{ Classes.Book.class, - Classes.PopularBook.class + Classes.PopularBook.class, + Classes.Edition.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java index 1cb09fe6f981..981f54958645 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/generics/GenericsTest.java @@ -23,19 +23,21 @@ */ package org.hibernate.test.annotations.generics; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.dialect.AbstractHANADialect; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9049" ) public class GenericsTest extends BaseCoreFunctionalTestCase { @SkipForDialect(value = AbstractHANADialect.class, comment = "known bug in HANA: rs.next() returns false for org.hibernate.id.enhanced.SequenceStructure$1.getNextValue() for this test") @@ -81,6 +83,9 @@ protected void configure(Configuration cfg) { protected Class[] getAnnotatedClasses() { return new Class[]{ Paper.class, + Stuff.class, + PricedStuff.class, + Item.class, PaperType.class, SomeGuy.class, Price.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java index 0ab19750705c..c4b38df46bb0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/genericsinheritance/GenericsInheritanceTest.java @@ -26,11 +26,13 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class GenericsInheritanceTest extends BaseCoreFunctionalTestCase { @Test public void testMapping() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java index 34f2181615ee..7eb59a7eb0c4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/IdTest.java @@ -23,12 +23,10 @@ */ package org.hibernate.test.annotations.id; -import org.hibernate.test.annotations.id.entities.Hotel; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.mapping.Column; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.annotations.id.entities.Ball; import org.hibernate.test.annotations.id.entities.BreakDance; import org.hibernate.test.annotations.id.entities.Computer; @@ -40,13 +38,15 @@ import org.hibernate.test.annotations.id.entities.Furniture; import org.hibernate.test.annotations.id.entities.GoalKeeper; import org.hibernate.test.annotations.id.entities.Home; +import org.hibernate.test.annotations.id.entities.Hotel; import org.hibernate.test.annotations.id.entities.Monkey; import org.hibernate.test.annotations.id.entities.Phone; import org.hibernate.test.annotations.id.entities.Shoe; import org.hibernate.test.annotations.id.entities.SoundSystem; import org.hibernate.test.annotations.id.entities.Store; import org.hibernate.test.annotations.id.entities.Tree; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -327,9 +327,9 @@ public void testIdClass() throws Exception { @Test public void testColumnDefinition() { - Column idCol = (Column) configuration().getClassMapping(Ball.class.getName()) - .getIdentifierProperty().getValue().getColumnIterator().next(); - assertEquals( "ball_id", idCol.getName() ); + org.hibernate.metamodel.spi.relational.Column idCol = SchemaUtil.getPrimaryKey( Ball.class, metadata() ) + .getColumns().get( 0 ); + assertEquals( "ball_id", idCol.getColumnName().getText() ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java index af9bee9c05f7..add1e310bfb1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/JoinColumnOverrideTest.java @@ -23,23 +23,21 @@ */ package org.hibernate.test.annotations.id; -import java.io.PrintWriter; -import java.io.StringWriter; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Table; -import org.jboss.logging.Logger; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; -import org.hibernate.dialect.SQLServerDialect; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.test.annotations.id.entities.Bunny; import org.hibernate.test.annotations.id.entities.PointyTooth; import org.hibernate.test.annotations.id.entities.TwinkleToes; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import org.jboss.logging.Logger; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; /** * Tests for JIRA issue ANN-748. @@ -53,30 +51,17 @@ public class JoinColumnOverrideTest extends BaseUnitTestCase { @Test @TestForIssue( jiraKey = "ANN-748" ) public void testBlownPrecision() throws Exception { - try { - Configuration config = new Configuration(); - config.addAnnotatedClass(Bunny.class); - config.addAnnotatedClass(PointyTooth.class); - config.addAnnotatedClass(TwinkleToes.class); - config.buildMappings( ); - String[] schema = config - .generateSchemaCreationScript(new SQLServerDialect()); - for (String s : schema) { - log.debug(s); - } - String expectedSqlPointyTooth = "create table PointyTooth (id numeric(128,0) not null, " + - "bunny_id numeric(128,0), primary key (id))"; - assertEquals("Wrong SQL", expectedSqlPointyTooth, schema[1]); + MetadataSources sources = new MetadataSources() + .addAnnotatedClass( Bunny.class ) + .addAnnotatedClass( PointyTooth.class ) + .addAnnotatedClass( TwinkleToes.class ); + Metadata metadata = sources.buildMetadata(); + + EntityBinding eb = metadata.getEntityBinding( PointyTooth.class.getName() ); + Table table = (Table) eb.getPrimaryTable(); + + final org.hibernate.metamodel.spi.relational.Column idColumn = table.locateColumn( "id" ); + assertEquals( 128, idColumn.getSize().getPrecision() ); - String expectedSqlTwinkleToes = "create table TwinkleToes (id numeric(128,0) not null, " + - "bunny_id numeric(128,0), primary key (id))"; - assertEquals("Wrong SQL", expectedSqlTwinkleToes, schema[2]); - } - catch (Exception e) { - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - log.debug(writer.toString()); - fail(e.getMessage()); - } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/HibernateSequenceTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/HibernateSequenceTest.java index 624ee0f201f9..7649cfbc1a24 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/HibernateSequenceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/HibernateSequenceTest.java @@ -13,6 +13,7 @@ import org.hibernate.mapping.Table; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.test.annotations.id.sequences.entities.HibernateSequenceEntity; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -44,6 +45,7 @@ protected String createSecondSchema() { } @Test + @FailureExpectedWithNewMetamodel public void testHibernateSequenceSchema() { EntityPersister persister = sessionFactory().getEntityPersister( HibernateSequenceEntity.class.getName() ); IdentifierGenerator generator = persister.getIdentifierGenerator(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java index 6c856ecd5e65..1e7f0153ee10 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/IdTest.java @@ -23,11 +23,13 @@ */ package org.hibernate.test.annotations.id.sequences; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.mapping.Column; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.annotations.id.generationmappings.DedicatedSequenceEntity1; import org.hibernate.test.annotations.id.generationmappings.DedicatedSequenceEntity2; import org.hibernate.test.annotations.id.sequences.entities.Ball; @@ -47,10 +49,9 @@ import org.hibernate.test.annotations.id.sequences.entities.SoundSystem; import org.hibernate.test.annotations.id.sequences.entities.Store; import org.hibernate.test.annotations.id.sequences.entities.Tree; -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Assert; +import org.junit.Test; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -314,9 +315,12 @@ public void testSequencePerEntity() { @Test public void testColumnDefinition() { - Column idCol = ( Column ) configuration().getClassMapping( Ball.class.getName() ) - .getIdentifierProperty().getValue().getColumnIterator().next(); - assertEquals( "ball_id", idCol.getName() ); + org.hibernate.metamodel.spi.relational.Column idCol = SchemaUtil.getPrimaryKey( + Ball.class, + metadata() + ) + .getColumns().get( 0 ); + Assert.assertEquals( "ball_id", idCol.getColumnName().getText() ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java index 8629c9608257..d137624af7b1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/id/sequences/JoinColumnOverrideTest.java @@ -1,23 +1,22 @@ //$Id$ package org.hibernate.test.annotations.id.sequences; -import java.io.PrintWriter; -import java.io.StringWriter; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Table; -import org.jboss.logging.Logger; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; -import org.hibernate.dialect.SQLServerDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.test.annotations.id.sequences.entities.Bunny; import org.hibernate.test.annotations.id.sequences.entities.PointyTooth; import org.hibernate.test.annotations.id.sequences.entities.TwinkleToes; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import org.jboss.logging.Logger; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; /** * Tests for JIRA issue ANN-748. @@ -31,29 +30,16 @@ public class JoinColumnOverrideTest extends BaseUnitTestCase { @Test @TestForIssue( jiraKey = "ANN-748" ) public void testBlownPrecision() throws Exception { - try { - Configuration config = new Configuration(); - config.addAnnotatedClass(Bunny.class); - config.addAnnotatedClass(PointyTooth.class); - config.addAnnotatedClass(TwinkleToes.class); - config.buildMappings( ); - String[] schema = config.generateSchemaCreationScript( new SQLServerDialect() ); - for (String s : schema) { - log.debug(s); - } - String expectedSqlPointyTooth = "create table PointyTooth (id numeric(128,0) not null, " + - "bunny_id numeric(128,0), primary key (id))"; - assertEquals("Wrong SQL", expectedSqlPointyTooth, schema[1]); - - String expectedSqlTwinkleToes = "create table TwinkleToes (id numeric(128,0) not null, " + - "bunny_id numeric(128,0), primary key (id))"; - assertEquals("Wrong SQL", expectedSqlTwinkleToes, schema[2]); - } - catch (Exception e) { - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - log.debug(writer.toString()); - fail(e.getMessage()); - } + MetadataSources sources = new MetadataSources() + .addAnnotatedClass( Bunny.class ) + .addAnnotatedClass( PointyTooth.class ) + .addAnnotatedClass( TwinkleToes.class ); + Metadata metadata = sources.buildMetadata(); + + EntityBinding eb = metadata.getEntityBinding( PointyTooth.class.getName() ); + Table table = (Table) eb.getPrimaryTable(); + + final org.hibernate.metamodel.spi.relational.Column idColumn = table.locateColumn( "id" ); + assertEquals( 128, idColumn.getSize().getPrecision() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java index 77c247d0e265..fabf12579168 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -65,6 +66,7 @@ public void testBaseLine() { @Test @SuppressWarnings({ "unchecked" }) + @FailureExpectedWithNewMetamodel public void testSingleGeneratedValue() { Session s = openSession(); s.beginTransaction(); @@ -90,6 +92,7 @@ public void testSingleGeneratedValue() { @Test @SuppressWarnings({ "unchecked" }) + @FailureExpectedWithNewMetamodel public void testMultipleGeneratedValue() { Session s = openSession(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java index 452e008ba9ff..ee971250ea52 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/identifiercollection/IdentifierCollectionTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -34,6 +35,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class IdentifierCollectionTest extends BaseCoreFunctionalTestCase { @Test public void testIdBag() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/IdManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/IdManyToOneTest.java index 49654a96cb99..94725cdc7664 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/IdManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/IdManyToOneTest.java @@ -24,20 +24,23 @@ package org.hibernate.test.annotations.idmanytoone; import org.hibernate.Criteria; -import org.hibernate.criterion.Restrictions; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( + message = "The problem here is actually the combination of @ManyToOne and @Basic on attributes; need to determine if that's really valid" +) public class IdManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testFkCreationOrdering() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java index d259fe2cf1ef..b33f3aedab85 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/idmanytoone/alphabetical/AlphabeticalIdManyToOneTest.java @@ -25,11 +25,13 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class AlphabeticalIdManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testAlphabeticalTest() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/immutable/ImmutableTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/immutable/ImmutableTest.java index d88158df6374..1ddf2f6b4876 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/immutable/ImmutableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/immutable/ImmutableTest.java @@ -23,24 +23,22 @@ */ package org.hibernate.test.annotations.immutable; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.ArrayList; import java.util.List; -import org.jboss.logging.Logger; -import org.junit.Test; - import org.hibernate.AnnotationException; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.metamodel.MetadataSources; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.jboss.logging.Logger; +import org.junit.Test; /** * Tests for Immutable annotation. @@ -152,20 +150,20 @@ public void testImmutableCollection() { } @Test - public void testMiscplacedImmutableAnnotation() { + public void testMisplacedImmutableAnnotation() { try { - Configuration config = new Configuration(); - config.addAnnotatedClass(Foobar.class); - config.buildMappings( ); + MetadataSources sources = new MetadataSources( serviceRegistry().getParentServiceRegistry() ); + sources.addAnnotatedClass(Foobar.class); + sources.buildMetadata(); fail(); } catch (AnnotationException ae) { - log.debug("succes"); + log.debug("success"); } } @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Country.class, State.class}; + return new Class[] { Country.class, State.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java index 3c774427af27..5a33a8d13d83 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/AbstractJPAIndexTest.java @@ -23,119 +23,99 @@ */ package org.hibernate.test.annotations.index.jpa; -import java.util.Iterator; - -import org.junit.Test; - -import org.hibernate.internal.util.StringHelper; -import org.hibernate.mapping.Bag; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Index; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Set; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.UniqueKey; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.util.Iterator; + +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + /** * @author Strong Liu */ public abstract class AbstractJPAIndexTest extends BaseCoreFunctionalTestCase { @Test public void testTableIndex() { - PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); - Iterator itr = entity.getTable().getUniqueKeyIterator(); - assertTrue( itr.hasNext() ); - UniqueKey uk = (UniqueKey) itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( StringHelper.isNotEmpty( uk.getName() ) ); - assertEquals( 2, uk.getColumnSpan() ); - Column column = (Column) uk.getColumns().get( 0 ); - assertEquals( "brand", column.getName() ); - column = (Column) uk.getColumns().get( 1 ); - assertEquals( "producer", column.getName() ); - assertSame( entity.getTable(), uk.getTable() ); - - - itr = entity.getTable().getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = (Index)itr.next(); - assertFalse( itr.hasNext() ); - assertEquals( "Car_idx", index.getName() ); - assertEquals( 1, index.getColumnSpan() ); - column = index.getColumnIterator().next(); - assertEquals( "since", column.getName() ); - assertSame( entity.getTable(), index.getTable() ); + TableSpecification table = SchemaUtil.getTable( Car.class, metadata() ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + int found = 0; + while (indexes.hasNext()) { + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + if (index.isUnique()) { + found++; + assertTrue( StringHelper.isNotEmpty( index.getName().toString() ) ); + assertEquals( 2, index.getColumnSpan() ); + Column column = index.getColumns().get( 0 ); + assertEquals( "brand", column.getColumnName().getText() ); + column = index.getColumns().get( 1 ); + assertEquals( "producer", column.getColumnName().getText() ); + } + else { + found++; + assertEquals( "Car_idx", index.getName().toString() ); + assertEquals( 1, index.getColumnSpan() ); + Column column = index.getColumns().get( 0 ); + assertEquals( "since", column.getColumnName().getText() ); + } + assertSame( table, index.getTable() ); + } + assertEquals( 2, found ); } @Test public void testSecondaryTableIndex(){ - PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); - - Join join = (Join)entity.getJoinIterator().next(); - Iterator itr = join.getTable().getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + EntityBinding entity = metadata().getEntityBinding( Car.class.getName() ); + + TableSpecification table = entity.locateTable( "T_DEALER" ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName().toString() ) ); assertEquals( 2, index.getColumnSpan() ); - Iterator columnIterator = index.getColumnIterator(); - Column column = columnIterator.next(); - assertEquals( "dealer_name", column.getName() ); - column = columnIterator.next(); - assertEquals( "rate", column.getName() ); - assertSame( join.getTable(), index.getTable() ); - + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "dealer_name", column.getColumnName().getText() ); + column = index.getColumns().get( 1 ); + assertEquals( "rate", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); } @Test public void testCollectionTableIndex(){ - PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); - Property property = entity.getProperty( "otherDealers" ); - Set set = (Set)property.getValue(); - Table collectionTable = set.getCollectionTable(); + TableSpecification table = SchemaUtil.getCollectionTable( Car.class, "otherDealers", metadata() ); - Iterator itr = collectionTable.getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName().toString() ) ); assertEquals( 1, index.getColumnSpan() ); - Iterator columnIterator = index.getColumnIterator(); - Column column = columnIterator.next(); - assertEquals( "name", column.getName() ); - assertSame( collectionTable, index.getTable() ); - + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "name", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); } @Test public void testJoinTableIndex(){ - PersistentClass entity = configuration().getClassMapping( Importer.class.getName() ); - Property property = entity.getProperty( "cars" ); - Bag set = (Bag)property.getValue(); - Table collectionTable = set.getCollectionTable(); + TableSpecification table = SchemaUtil.getCollectionTable( Importer.class, "cars", metadata() ); - Iterator itr = collectionTable.getIndexIterator(); - assertTrue( itr.hasNext() ); - Index index = itr.next(); - assertFalse( itr.hasNext() ); - assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName().toString() ) ); assertEquals( 1, index.getColumnSpan() ); - Iterator columnIterator = index.getColumnIterator(); - Column column = columnIterator.next(); - assertEquals( "importers_id", column.getName() ); - assertSame( collectionTable, index.getTable() ); - } - - @Test - public void testTableGeneratorIndex(){ - //todo + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "importers_id", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/Car.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/Car.java index d67522af786f..6a18929f6246 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/Car.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/Car.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Set; + import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.CascadeType; @@ -33,28 +34,37 @@ import javax.persistence.ElementCollection; import javax.persistence.Embedded; import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Index; import javax.persistence.ManyToMany; import javax.persistence.SecondaryTable; import javax.persistence.Table; +import javax.persistence.TableGenerator; /** * @author Strong Liu */ @Entity -@Table(indexes = { - @Index(unique = true, columnList = "brand, producer") - , @Index(name = "Car_idx", columnList = "since DESC") +@Table(indexes = { @Index(unique = true, columnList = "brand, producer"), + @Index(name = "Car_idx", columnList = "since DESC") }) +@TableGenerator(name = "idGen", table = "ID_GEN", valueColumnName="GEN_VALUE", + indexes = @Index(columnList = "GEN_VALUE")) @SecondaryTable(name = "T_DEALER", indexes = @Index(columnList = "dealer_name ASC, rate DESC")) public class Car { @Id + @GeneratedValue(strategy = GenerationType.TABLE, generator = "idGen") private long id; + private String brand; + private String producer; + private long since; + @AttributeOverrides({ @AttributeOverride(name = "name", column = @Column(name = "dealer_name", table = "T_DEALER")), @AttributeOverride(name = "rate", column = @Column(table = "T_DEALER")) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java index 28da6edd8627..045e0255078c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java @@ -23,32 +23,18 @@ */ package org.hibernate.test.annotations.index.jpa; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import java.util.Iterator; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; import org.junit.Test; -import static org.junit.Assert.*; - -import org.hibernate.internal.util.StringHelper; -import org.hibernate.mapping.Bag; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Index; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.List; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Set; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.UniqueKey; -import org.hibernate.mapping.Value; -import org.hibernate.test.annotations.embedded.Address; -import org.hibernate.test.annotations.embedded.AddressType; -import org.hibernate.test.annotations.embedded.Book; -import org.hibernate.test.annotations.embedded.Person; -import org.hibernate.test.annotations.embedded.Summary; -import org.hibernate.test.annotations.embedded.WealthyPerson; -import org.hibernate.test.event.collection.detached.*; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Strong Liu @@ -63,5 +49,18 @@ protected Class[] getAnnotatedClasses() { }; } + @Test + public void testTableGeneratorIndex(){ + TableSpecification table = SchemaUtil.getTable( "ID_GEN", metadata() ); + Iterator indexes = table.getIndexes().iterator(); + assertTrue( indexes.hasNext() ); + org.hibernate.metamodel.spi.relational.Index index = indexes.next(); + assertFalse( indexes.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName().toString() ) ); + assertEquals( 1, index.getColumnSpan() ); + org.hibernate.metamodel.spi.relational.Column column = index.getColumns().get( 0 ); + assertEquals( "GEN_VALUE", column.getColumnName().getText() ); + assertSame( table, index.getTable() ); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java index 156c4ec4fc4e..2ca50ef4bc0d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/IndexedCollectionTest.java @@ -26,21 +26,21 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; -import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HSQLDialect; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.relational.Value; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -53,36 +53,36 @@ * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( message = "@MapKeyJoinColumns not supported yet." ) public class IndexedCollectionTest extends BaseCoreFunctionalTestCase { @Test public void testJPA2DefaultMapColumns() throws Exception { - isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesDef", "_KEY" ); - isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesPerKeyDef", "_KEY" ); - isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesDefLeg", "_KEY" ); + isDefaultKeyColumnPresent( Atmosphere.class, "gasesDef", "_KEY" ); + isDefaultKeyColumnPresent( Atmosphere.class, "gasesPerKeyDef", "_KEY" ); + isDefaultKeyColumnPresent( Atmosphere.class, "gasesDefLeg", "_KEY" ); } @Test public void testJPA2DefaultIndexColumns() throws Exception { - isDefaultKeyColumnPresent( Drawer.class.getName(), "dresses", "_ORDER" ); + isDefaultKeyColumnPresent( Drawer.class, "dresses", "_ORDER" ); } - private void isDefaultKeyColumnPresent(String collectionOwner, String propertyName, String suffix) { + private void isDefaultKeyColumnPresent(Class collectionOwner, String propertyName, String suffix) { assertTrue( "Could not find " + propertyName + suffix, isDefaultColumnPresent(collectionOwner, propertyName, suffix) ); } - private boolean isDefaultColumnPresent(String collectionOwner, String propertyName, String suffix) { - final Collection collection = configuration().getCollectionMapping( collectionOwner + "." + propertyName ); - final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); + private boolean isDefaultColumnPresent(Class collectionOwner, String propertyName, String suffix) { boolean hasDefault = false; - while ( columnIterator.hasNext() ) { - Column column = (Column) columnIterator.next(); - if ( (propertyName + suffix).equals( column.getName() ) ) hasDefault = true; + List values = SchemaUtil.getCollectionTable( collectionOwner, propertyName, metadata() ).values(); + for ( Value value : values ) { + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) value; + if ( (propertyName + suffix).equals( column.getColumnName().getText() ) ) hasDefault = true; } return hasDefault; } - private void isNotDefaultKeyColumnPresent(String collectionOwner, String propertyName, String suffix) { + private void isNotDefaultKeyColumnPresent(Class collectionOwner, String propertyName, String suffix) { assertFalse( "Could not find " + propertyName + suffix, isDefaultColumnPresent(collectionOwner, propertyName, suffix) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java index cd743239033f..7f82c59af8c2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/MapKeyTest.java @@ -27,6 +27,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -34,6 +35,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class MapKeyTest extends BaseCoreFunctionalTestCase { @Test public void testMapKeyOnEmbeddedId() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/Training.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/Training.java index b3932e97980b..43842ef4cc7c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/Training.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/indexcoll/Training.java @@ -2,14 +2,14 @@ package org.hibernate.test.annotations.indexcoll; import java.util.SortedMap; import java.util.TreeMap; + import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.MapKey; -import org.hibernate.annotations.Sort; -import org.hibernate.annotations.SortType; +import org.hibernate.annotations.SortNatural; /** * @author Emmanuel Bernard @@ -17,7 +17,7 @@ @Entity public class Training { @Id @GeneratedValue private Long id; - @Sort(type= SortType.NATURAL) + @SortNatural @MapKey(name="name") @ManyToMany SortedMap trainees = new TreeMap(); public Long getId() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/SubclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/SubclassTest.java index feeeb405fd26..ed8289f1882a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/SubclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/SubclassTest.java @@ -25,11 +25,12 @@ import java.util.List; -import org.junit.Test; - import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.annotations.A320; import org.hibernate.test.annotations.A320b; import org.hibernate.test.annotations.Plane; @@ -37,7 +38,7 @@ import org.hibernate.test.annotations.inheritance.singletable.Music; import org.hibernate.test.annotations.inheritance.singletable.Noise; import org.hibernate.test.annotations.inheritance.singletable.Rock; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -48,6 +49,10 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( + message = "The issue here is that 2 subclasses use the same discriminator value leading to an exception; " + + "that exception seems valid to me" +) public class SubclassTest extends BaseCoreFunctionalTestCase { @Override protected boolean isCleanupTestDataRequired() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/Vegetable.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/Vegetable.java index e64a1559f580..59ceaa6f0e76 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/Vegetable.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/Vegetable.java @@ -1,5 +1,5 @@ -//$Id$ package org.hibernate.test.annotations.inheritance; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Inheritance; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/VegetablePk.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/VegetablePk.java index de7bd8d687ff..84abb65d1568 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/VegetablePk.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/VegetablePk.java @@ -1,5 +1,5 @@ -//$Id$ package org.hibernate.test.annotations.inheritance; + import java.io.Serializable; import javax.persistence.Embeddable; @@ -9,6 +9,23 @@ @Embeddable public class VegetablePk implements Serializable { private String farmer; + private String harvestDate; + + public String getFarmer() { + return farmer; + } + + public void setFarmer(String farmer) { + this.farmer = farmer; + } + + public String getHarvestDate() { + return harvestDate; + } + + public void setHarvestDate(String harvestDate) { + this.harvestDate = harvestDate; + } public boolean equals(Object o) { if ( this == o ) return true; @@ -29,21 +46,4 @@ public int hashCode() { return result; } - public String getFarmer() { - return farmer; - } - - public void setFarmer(String farmer) { - this.farmer = farmer; - } - - public String getHarvestDate() { - return harvestDate; - } - - public void setHarvestDate(String harvestDate) { - this.harvestDate = harvestDate; - } - - private String harvestDate; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java index c160c390b9fd..916d319f70ed 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java @@ -23,13 +23,12 @@ */ package org.hibernate.test.annotations.inheritance.discriminatoroptions; -import org.junit.Test; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.RootClass; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -43,45 +42,45 @@ public class DiscriminatorOptionsTest extends BaseUnitTestCase { @Test public void testNonDefaultOptions() throws Exception { - Configuration configuration = new Configuration(); - configuration.addAnnotatedClass( BaseClass.class ); - configuration.addAnnotatedClass( SubClass.class ); - configuration.buildMappings(); - PersistentClass persistentClass = configuration.getClassMapping( BaseClass.class.getName() ); - assertNotNull( persistentClass ); - assertTrue( persistentClass instanceof RootClass ); + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( BaseClass.class ) + .addAnnotatedClass( SubClass.class ); + MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); - RootClass root = ( RootClass ) persistentClass; - assertTrue( "Discriminator should be forced", root.isForceDiscriminator() ); - assertFalse( "Discriminator should not be insertable", root.isDiscriminatorInsertable() ); + EntityBinding entityBinding = metadata.getEntityBinding( BaseClass.class.getName() ); + assertNotNull( entityBinding ); + assertTrue( entityBinding.isRoot() ); + + assertTrue( entityBinding.getHierarchyDetails().getEntityDiscriminator().isForced() ); + assertFalse( entityBinding.getHierarchyDetails().getEntityDiscriminator().isInserted() ); } @Test public void testBaseline() throws Exception { - Configuration configuration = new Configuration() + MetadataSources metadataSources = new MetadataSources() .addAnnotatedClass( BaseClass2.class ) .addAnnotatedClass( SubClass2.class ); - configuration.buildMappings(); - PersistentClass persistentClass = configuration.getClassMapping( BaseClass2.class.getName() ); - assertNotNull( persistentClass ); - assertTrue( persistentClass instanceof RootClass ); + MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); + + EntityBinding entityBinding = metadata.getEntityBinding( BaseClass2.class.getName() ); + assertNotNull( entityBinding ); + assertTrue( entityBinding.isRoot() ); - RootClass root = ( RootClass ) persistentClass; - assertFalse( "Discriminator should not be forced by default", root.isForceDiscriminator() ); + assertFalse( entityBinding.getHierarchyDetails().getEntityDiscriminator().isForced() ); } @Test public void testPropertyBasedDiscriminatorForcing() throws Exception { - Configuration configuration = new Configuration() - .setProperty( AvailableSettings.FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT, "true" ) - .addAnnotatedClass( BaseClass2.class ) - .addAnnotatedClass( SubClass2.class ); - configuration.buildMappings(); - PersistentClass persistentClass = configuration.getClassMapping( BaseClass2.class.getName() ); - assertNotNull( persistentClass ); - assertTrue( persistentClass instanceof RootClass ); - - RootClass root = ( RootClass ) persistentClass; - assertTrue( "Discriminator should be forced by property", root.isForceDiscriminator() ); +// Configuration configuration = new Configuration() +// .setProperty( AvailableSettings.FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT, "true" ) +// .addAnnotatedClass( BaseClass2.class ) +// .addAnnotatedClass( SubClass2.class ); +// configuration.buildMappings(); +// PersistentClass persistentClass = configuration.getClassMapping( BaseClass2.class.getName() ); +// assertNotNull( persistentClass ); +// assertTrue( persistentClass instanceof RootClass ); +// +// RootClass root = ( RootClass ) persistentClass; +// assertTrue( "Discriminator should be forced by property", root.isForceDiscriminator() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/Document.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/Document.java index 8eab06736cc2..cdb3eba3b1e9 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/Document.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/Document.java @@ -3,13 +3,10 @@ import javax.persistence.Column; import javax.persistence.Entity; -import org.hibernate.annotations.ForeignKey; - /** * @author Emmanuel Bernard */ @Entity -@ForeignKey(name = "FK_DOCU_FILE") public class Document extends File { @Column(nullable = false, name="xsize") private int size; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java index 2ab15d09f4df..53661ae07319 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/inheritance/joined/JoinedSubclassAndSecondaryTable.java @@ -88,6 +88,6 @@ private long getTableRowCount(Session s) { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Pool.class, SwimmingPool.class }; + return new Class[] { Pool.class, PoolAddress.class, SwimmingPool.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/ApplicationServer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/ApplicationServer.java new file mode 100644 index 000000000000..c780666af8d7 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/ApplicationServer.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.jandex; + +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author Steve Ebersole + */ +@Entity +public class ApplicationServer { + private Integer id; + private String name; + private Version version; + + @Id + @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Embedded + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/BasicJandexExpectationsTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/BasicJandexExpectationsTest.java new file mode 100644 index 000000000000..f5700c4f4a51 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/BasicJandexExpectationsTest.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.jandex; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.hibernate.HibernateException; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; + +import static org.junit.Assert.assertNotNull; + +/** + * @author Steve Ebersole + */ +public class BasicJandexExpectationsTest extends BaseUnitTestCase { + @Test + public void test1() { + Indexer indexer = new Indexer(); + add( Version.class, indexer ); + add( ApplicationServer.class, indexer ); + + Index index = indexer.complete(); + + index.printSubclasses(); + index.printAnnotations(); + + ClassInfo ci = index.getClassByName( DotName.createSimple( ApplicationServer.class.getName() ) ); + List annotations = ci.annotations().get( DotName.createSimple( javax.persistence.Id.class.getName() ) ); + assertNotNull( annotations ); + } + + @Test + public void testIndexingSameClassMultipleTimes() { + Indexer indexer = new Indexer(); + add( Version.class, indexer ); + add( Version.class, indexer ); + add( Version.class, indexer ); + add( ApplicationServer.class, indexer ); + + Index index = indexer.complete(); + + index.printSubclasses(); + index.printAnnotations(); + } + + private ClassInfo add(Class theClass, Indexer indexer) { + final String theClassResourceName = '/' + theClass.getName().replace( '.', '/' ) + ".class"; + + InputStream stream = getClass().getResourceAsStream( theClassResourceName ); + + try { + return indexer.index( stream ); + } + catch ( IOException e ) { + throw new HibernateException( "Unable to open input stream for resource " + theClassResourceName, e ); + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/Version.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/Version.java new file mode 100644 index 000000000000..498c37dc285c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/jandex/Version.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.jandex; + +import javax.persistence.Embeddable; + +/** + * @author Steve Ebersole + */ +@Embeddable +public class Version { + private static final String DOT = "."; + private int major; + private int minor; + private int micro; + + public int getMajor() { + return major; + } + + public void setMajor(int major) { + this.major = major; + } + + public int getMinor() { + return minor; + } + + public void setMinor(int minor) { + this.minor = minor; + } + + public int getMicro() { + return micro; + } + + public void setMicro(int micro) { + this.micro = micro; + } + + public String toString() { + return new StringBuffer( major ).append( DOT ).append( minor ).append( DOT ).append( micro ).toString(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/Cat.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/Cat.java index d187e5ab4ae3..bddc4aa05460 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/Cat.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/Cat.java @@ -1,17 +1,18 @@ //$Id$ package org.hibernate.test.annotations.join; import java.io.Serializable; + import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.SecondaryTable; import javax.persistence.SecondaryTables; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.FetchMode; -import org.hibernate.annotations.ForeignKey; -import org.hibernate.annotations.Index; import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.Table; import org.hibernate.annotations.Tables; @@ -25,11 +26,12 @@ @SecondaryTable(name = "Cat2", uniqueConstraints = {@UniqueConstraint(columnNames = {"storyPart2"})}) }) @Tables( { - @Table(appliesTo = "Cat", indexes = @Index(name = "secondname", - columnNames = "secondName"), comment = "My cat table" ), + @Table(comment = "My cat table", appliesTo = "Cat", indexes = { + @Index(name = "secondname", columnList = "secondName"), + @Index(name = "nameindex", columnList = "name"), + @Index(name = "story1index", columnList = "`Cat nbr1`")}), @Table(appliesTo = "Cat2", foreignKey = @ForeignKey(name="FK_CAT2_CAT"), fetch = FetchMode.SELECT, - sqlInsert=@SQLInsert(sql="insert into Cat2(storyPart2, id) values(upper(?), ?)") ) - } ) + sqlInsert=@SQLInsert(sql="insert into Cat2(storyPart2, id) values(upper(?), ?)"))}) public class Cat implements Serializable { private Integer id; @@ -44,7 +46,6 @@ public Integer getId() { return id; } - @Index(name = "nameindex") public String getName() { return name; } @@ -77,7 +78,6 @@ public void setSecondName(String secondName) { // } @Column(table = "`Cat nbr1`") - @Index(name = "story1index") public String getStoryPart1() { return storyPart1; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java index 187c6717c3b4..1b2f1285f33f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java @@ -26,16 +26,21 @@ import java.util.ArrayList; import java.util.Date; -import org.junit.Test; - import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; -import org.hibernate.mapping.Join; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -45,14 +50,14 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class JoinTest extends BaseCoreFunctionalTestCase { @Test public void testDefaultValue() throws Exception { - Join join = (Join) configuration().getClassMapping( Life.class.getName() ).getJoinClosureIterator().next(); - assertEquals( "ExtendedLife", join.getTable().getName() ); - org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); - owner.setName( "LIFE_ID" ); - assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); + TableSpecification joinTable = metadata().getEntityBinding( Life.class.getName() ).locateTable( "ExtendedLife" ); + assertNotNull( joinTable ); + assertTrue( joinTable.getPrimaryKey().hasColumn( "LIFE_ID" ) ); + Session s = openSession(); Transaction tx = s.beginTransaction(); Life life = new Life(); @@ -73,11 +78,19 @@ public void testDefaultValue() throws Exception { @Test public void testCompositePK() throws Exception { - Join join = (Join) configuration().getClassMapping( Dog.class.getName() ).getJoinClosureIterator().next(); - assertEquals( "DogThoroughbred", join.getTable().getName() ); - org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); - owner.setName( "OWNER_NAME" ); - assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); + SecondaryTable secondaryTable = + metadata().getEntityBinding( Dog.class.getName() ).getSecondaryTables().values().iterator().next(); + Table table = (Table) secondaryTable.getSecondaryTableReference(); + assertEquals( "DogThoroughbred", table.getPhysicalName().getText() ); + PrimaryKey pk = table.getPrimaryKey(); + assertEquals( 2, pk.getColumnSpan() ); + Column c0 = pk.getColumns().get( 0 ); + Column c1 = pk.getColumns().get( 1 ); + assertTrue( + "OWNER_NAME".equals( c0.getColumnName().getText() ) || + "OWNER_NAME".equals( c1.getColumnName().getText() ) + ); + Session s = openSession(); Transaction tx = s.beginTransaction(); Dog dog = new Dog(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/LoaderTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/LoaderTest.java index 54fc6c2b4f20..3f5cd75e6c3f 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/LoaderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/LoaderTest.java @@ -23,16 +23,17 @@ */ package org.hibernate.test.annotations.loader; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + import java.util.Iterator; import java.util.Set; -import org.junit.Test; - +import org.hibernate.ObjectNotFoundException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * @author Emmanuel Bernard @@ -87,5 +88,22 @@ public void testBasic() throws Exception { s.close(); } } + + @Test + public void testGetNotExisting() { + Session s = openSession(); + + try { + long notExistingId = 1l; + s.load( Team.class, notExistingId ); + s.get( Team.class, notExistingId ); + } + catch (ObjectNotFoundException e) { + fail("#get threw an ObjectNotFoundExcepton"); + } + finally { + s.close(); + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java index f3ca7b6669d9..7e60dcf0eb37 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/lob/SerializableToBlobTypeTest.java @@ -1,17 +1,18 @@ package org.hibernate.test.annotations.lob; -import static org.junit.Assert.assertEquals; - import org.hibernate.Session; -import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.type.SerializableToBlobType; +import org.hibernate.type.Type; + import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.type.SerializableToBlobType; -import org.hibernate.type.Type; import org.junit.Test; +import static org.junit.Assert.assertEquals; + /** * Test type definition for SerializableToBlobType * @@ -20,27 +21,31 @@ @RequiresDialectFeature( DialectChecks.SupportsExpectedLobUsagePattern.class ) public class SerializableToBlobTypeTest extends BaseCoreFunctionalTestCase { @Test + @FailureExpectedWithNewMetamodel public void testTypeDefinition() { - Configuration cfg = configuration(); - PersistentClass pc = cfg.getClassMapping( EntitySerialize.class.getName() ); + EntityBinding binding = metadata().getEntityBinding( EntitySerialize.class.getName() ); // explicitLob of SerializableToBlobType - Type explicitLobType = pc.getProperty( "explicitLob" ).getType(); + Type explicitLobType = binding.locateAttributeBinding( "explicitLob" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); assertEquals( ExplicitSerializable.class, explicitLobType.getReturnedClass() ); assertEquals( SerializableToBlobType.class.getName(), explicitLobType.getName() ); // explicit of ExplicitSerializableType - Type explicitType = pc.getProperty( "explicit" ).getType(); + Type explicitType = binding.locateAttributeBinding( "explicit" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); assertEquals( ExplicitSerializable.class, explicitType.getReturnedClass() ); assertEquals( ExplicitSerializableType.class.getName(), explicitType.getName() ); // implicit of ImplicitSerializableType - Type implicitType = pc.getProperty( "implicit" ).getType(); + Type implicitType = binding.locateAttributeBinding( "implicit" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); assertEquals( ImplicitSerializable.class, implicitType.getReturnedClass() ); assertEquals( ImplicitSerializableType.class.getName(), implicitType.getName() ); // explicitOverridingImplicit ExplicitSerializableType overrides ImplicitSerializableType - Type overrideType = pc.getProperty( "explicitOverridingImplicit" ).getType(); + Type overrideType = binding.locateAttributeBinding( "explicitOverridingImplicit" ) + .getHibernateTypeDescriptor().getResolvedTypeMapping(); assertEquals( ImplicitSerializable.class, overrideType.getReturnedClass() ); assertEquals( ExplicitSerializableType.class.getName(), overrideType.getName() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java index 72b99f1ff20e..f8078f35d42f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/CatPk.java @@ -2,10 +2,12 @@ package org.hibernate.test.annotations.manytomany; import java.io.Serializable; import javax.persistence.Column; +import javax.persistence.Embeddable; /** * @author Emmanuel Bernard */ +@Embeddable public class CatPk implements Serializable { private String name; private String thoroughbred; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyMaxFetchDepth0Test.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyMaxFetchDepth0Test.java index d36bf821c614..71b7066a3857 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyMaxFetchDepth0Test.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyMaxFetchDepth0Test.java @@ -26,6 +26,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * Many to many tests using max_fetch_depth == 0 @@ -33,6 +34,7 @@ * @author Gail Badner */ @SuppressWarnings("unchecked") +@FailureExpectedWithNewMetamodel public class ManyToManyMaxFetchDepth0Test extends ManyToManyTest { @Override protected void configure(Configuration cfg) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java index f2d27e163370..29f223ecfe95 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java @@ -38,6 +38,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -53,6 +54,7 @@ * @author Emmanuel Bernard */ @SuppressWarnings("unchecked") +@FailureExpectedWithNewMetamodel public class ManyToManyTest extends BaseCoreFunctionalTestCase { @Test public void testDefault() throws Exception { @@ -763,6 +765,8 @@ protected Class[] getAnnotatedClasses() { Friend.class, Employer.class, Employee.class, + ContactInfo.class, + JobInfo.class, Contractor.class, Man.class, Woman.class, @@ -771,6 +775,7 @@ protected Class[] getAnnotatedClasses() { Supplier.class, City.class, Cat.class, + CatPk.class, Group.class, GroupWithSet.class, Permission.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/Woman.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/Woman.java index bfb478ed9bfd..6808dd7bf14c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/Woman.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/Woman.java @@ -2,15 +2,15 @@ package org.hibernate.test.annotations.manytomany; import java.io.Serializable; import java.util.Set; + import javax.persistence.CascadeType; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; -import org.hibernate.annotations.ForeignKey; - /** * Woman knowing several mens * @@ -33,19 +33,16 @@ public void setCats(Set cats) { } @ManyToMany(cascade = {CascadeType.ALL}) - @JoinTable( - name = "Man_Woman", + @JoinTable(name = "Man_Woman", joinColumns = { - @JoinColumn(name = "womanLastName", referencedColumnName = "lastName"), - @JoinColumn(name = "womanFirstName", referencedColumnName = "firstName") - }, + @JoinColumn(name = "womanLastName", referencedColumnName = "lastName"), + @JoinColumn(name = "womanFirstName", referencedColumnName = "firstName") }, inverseJoinColumns = { - @JoinColumn(name = "manIsElder", referencedColumnName = "elder"), - @JoinColumn(name = "manLastName", referencedColumnName = "lastName"), - @JoinColumn(name = "manFirstName", referencedColumnName = "firstName") - } - ) - @ForeignKey(name = "WM_W_FK", inverseName = "WM_M_FK") + @JoinColumn(name = "manIsElder", referencedColumnName = "elder"), + @JoinColumn(name = "manLastName", referencedColumnName = "lastName"), + @JoinColumn(name = "manFirstName", referencedColumnName = "firstName") }, + foreignKey = @ForeignKey(name = "WM_W_FK"), + inverseForeignKey = @ForeignKey(name = "WM_M_FK")) public Set getMens() { return mens; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Car.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Car.java index d4bb2c9ab5a1..005be7049506 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Car.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Car.java @@ -2,12 +2,12 @@ package org.hibernate.test.annotations.manytoone; import javax.persistence.Entity; import javax.persistence.FetchType; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; -import org.hibernate.annotations.ForeignKey; - /** * Many to one sample using default mapping values * @@ -30,7 +30,7 @@ public void setId(Integer id) { } @ManyToOne(fetch = FetchType.EAGER) - @ForeignKey(name="BODY_COLOR_FK") + @JoinColumn(foreignKey = @ForeignKey(name="BODY_COLOR_FK")) public Color getBodyColor() { return bodyColor; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ForestType.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ForestType.java index 3d14010efb4a..04457c426077 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ForestType.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ForestType.java @@ -1,7 +1,9 @@ //$Id$ package org.hibernate.test.annotations.manytoone; import java.util.Set; + import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; @@ -9,8 +11,6 @@ import javax.persistence.OneToMany; import javax.persistence.OneToOne; -import org.hibernate.annotations.ForeignKey; - /** * @author Emmanuel Bernard */ @@ -24,10 +24,9 @@ public class ForestType { @OneToOne @JoinTable(name="BiggestRepPerForestType", joinColumns = @JoinColumn(name="forest_type"), - inverseJoinColumns = @JoinColumn(name="forest") - ) - @ForeignKey(name="A_TYP_FK", - inverseName = "A_FOR_FK" //inverse fail cause it involves a Join + inverseJoinColumns = @JoinColumn(name="forest"), + foreignKey = @ForeignKey(name="A_TYP_FK"), + inverseForeignKey = @ForeignKey(name="A_FOR_FK") //inverse fail cause it involves a Join ) public BiggestForest getBiggestRepresentative() { return biggestRepresentative; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java index ec61f61b2b80..69331a4063d7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/ManyToOneTest.java @@ -39,6 +39,7 @@ import org.hibernate.test.annotations.Flight; import org.hibernate.test.annotations.Passport; import org.hibernate.test.annotations.Ticket; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -49,6 +50,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ManyToOneTest extends BaseCoreFunctionalTestCase { @Test public void testEager() throws Exception { @@ -385,8 +387,10 @@ protected Class[] getAnnotatedClasses() { Ticket.class, Passport.class, Parent.class, + ParentPk.class, Child.class, Node.class, + NodePk.class, User.class, DistrictUser.class, Order.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Node.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Node.java index c4477aaaab8f..4c8dab455be1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Node.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Node.java @@ -2,6 +2,7 @@ package org.hibernate.test.annotations.manytoone; import java.io.Serializable; import javax.persistence.CascadeType; +import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; @@ -34,7 +35,7 @@ public int hashCode() { return id.hashCode(); } - @Id + @EmbeddedId public NodePk getId() { return id; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Parent.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Parent.java index 126b60f8b3c6..77aa93a53939 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Parent.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/Parent.java @@ -1,6 +1,7 @@ //$Id$ package org.hibernate.test.annotations.manytoone; import java.io.Serializable; +import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @@ -11,7 +12,7 @@ @Entity @Table(name = "tbl_parent") public class Parent implements Serializable { - @Id + @EmbeddedId public ParentPk id; public int age; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java index 8f89fad0c809..e340352b4e30 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java @@ -29,12 +29,14 @@ import org.hibernate.Session; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ManyToOneReferencedColumnNameTest extends BaseCoreFunctionalTestCase { @Test @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java index d18378fe55fc..9a9b6d0ccff5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytoonewithformula/ManyToOneWithFormulaTest.java @@ -35,6 +35,7 @@ import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.SQLServer2005Dialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.SkipForDialects; @@ -67,6 +68,7 @@ public void testManyToOneFromNonPk() throws Exception { } @Test + @FailureExpectedWithNewMetamodel public void testManyToOneFromPk() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -91,6 +93,7 @@ public void testManyToOneFromPk() throws Exception { @Test @SkipForDialect(value = { HSQLDialect.class }, comment = "The used join conditions does not work in HSQLDB. See HHH-4497") + @FailureExpectedWithNewMetamodel public void testManyToOneToPkWithOnlyFormula() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -160,6 +163,7 @@ public void testReferencedColumnNameBelongsToEmbeddedIdOfReferencedEntity() thro @SkipForDialect( value = { SQLServer2005Dialect.class } ), @SkipForDialect( value = { Oracle8iDialect.class }, comment = "Oracle/DB2 do not support 'substring' function" ), @SkipForDialect( value = { DB2Dialect.class }, comment = "Oracle/DB2 do not support 'substring' function" ) } ) + @FailureExpectedWithNewMetamodel public void testManyToOneFromNonPkToNonPk() throws Exception { // also tests usage of the stand-alone @JoinFormula annotation (i.e. not wrapped within @JoinColumnsOrFormulas) Session s = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java index 7c175c7401fb..c1404b90e0d3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/mappedsuperclass/intermediate/IntermediateMappedSuperclassTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -35,6 +36,7 @@ /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class IntermediateMappedSuperclassTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java index 3c2c45a2d3a0..66f64cddb492 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/namingstrategy/NamingStrategyTest.java @@ -1,34 +1,31 @@ // $Id$ package org.hibernate.test.annotations.namingstrategy; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + import java.io.PrintWriter; import java.io.StringWriter; -import java.util.Iterator; - -import org.jboss.logging.Logger; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.EJB3NamingStrategy; import org.hibernate.cfg.Environment; -import org.hibernate.cfg.Mappings; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.ServiceRegistry; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.ServiceRegistryBuilder; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.jboss.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; /** * Test harness for ANN-716. * * @author Hardy Ferentschik */ -public class NamingStrategyTest { +public class NamingStrategyTest extends BaseUnitTestCase { private static final Logger log = Logger.getLogger( NamingStrategyTest.class ); private ServiceRegistry serviceRegistry; @@ -42,14 +39,14 @@ public void setUp() { public void tearDown() { if (serviceRegistry != null) ServiceRegistryBuilder.destroy(serviceRegistry); } + @Test public void testWithCustomNamingStrategy() throws Exception { try { - AnnotationConfiguration config = new AnnotationConfiguration(); - config.setNamingStrategy(new DummyNamingStrategy()); - config.addAnnotatedClass(Address.class); - config.addAnnotatedClass(Person.class); - config.buildMappings(); + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( Address.class ) + .addAnnotatedClass( Person.class ); + metadataSources.getMetadataBuilder().with( new DummyNamingStrategy() ).build(); } catch( Exception e ) { StringWriter writer = new StringWriter(); @@ -58,47 +55,25 @@ public void testWithCustomNamingStrategy() throws Exception { fail(e.getMessage()); } } + @Test public void testWithEJB3NamingStrategy() throws Exception { - SessionFactory sf = null; - try { - AnnotationConfiguration config = new AnnotationConfiguration(); - config.setNamingStrategy(EJB3NamingStrategy.INSTANCE); - config.addAnnotatedClass(A.class); - config.addAnnotatedClass(AddressEntry.class); - sf = config.buildSessionFactory( serviceRegistry ); - Mappings mappings = config.createMappings(); - boolean foundIt = false; - - for ( Iterator iter = mappings.iterateTables(); iter.hasNext(); ) { - Table table = (Table) iter.next(); - log.info("testWithEJB3NamingStrategy table = " + table.getName()); - if ( table.getName().equalsIgnoreCase("A_ADDRESS")) { - foundIt = true; - } - // make sure we use A_ADDRESS instead of AEC_address - assertFalse("got table name mapped to: AEC_address (should be A_ADDRESS) which violates JPA-2 spec section 11.1.8 ([OWNING_ENTITY_NAME]_[COLLECTION_ATTRIBUTE_NAME])",table.getName().equalsIgnoreCase("AEC_address")); - } - assertTrue("table not mapped to A_ADDRESS which violates JPA-2 spec section 11.1.8",foundIt); - } - catch( Exception e ) { - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - log.debug(writer.toString()); - fail(e.getMessage()); - } finally { - if( sf != null ){ - sf.close(); - } - } + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( A.class ) + .addAnnotatedClass( AddressEntry.class ); + MetadataImplementor metadata = (MetadataImplementor) metadataSources.getMetadataBuilder() + .with( EJB3NamingStrategy.INSTANCE ) + .build(); + assertNotNull( SchemaUtil.getTable( "A_ADDRESS", metadata ) ); } + @Test public void testWithoutCustomNamingStrategy() throws Exception { try { - AnnotationConfiguration config = new AnnotationConfiguration(); - config.addAnnotatedClass(Address.class); - config.addAnnotatedClass(Person.class); - config.buildMappings(); + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( Address.class ) + .addAnnotatedClass( Person.class ); + metadataSources.buildMetadata(); } catch( Exception e ) { StringWriter writer = new StringWriter(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/Coin.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/Coin.java index cfc6fba0ecdf..952190035c20 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/Coin.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/Coin.java @@ -1,6 +1,8 @@ //$Id$ package org.hibernate.test.annotations.notfound; +import javax.persistence.ConstraintMode; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; @@ -37,7 +39,8 @@ public void setName(String name) { } @ManyToOne - @JoinColumn(name = "currency", referencedColumnName = "name") + @JoinColumn(name = "currency", referencedColumnName = "name", + foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @NotFound(action = NotFoundAction.IGNORE) public Currency getCurrency() { return currency; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java index 06741eea2dbc..0251e312acb4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/notfound/NotFoundTest.java @@ -23,13 +23,12 @@ */ package org.hibernate.test.annotations.notfound; -import org.junit.Test; +import static org.junit.Assert.assertNull; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertNull; +import org.junit.Test; /** * @author Emmanuel Bernard diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/A.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/A.java new file mode 100644 index 000000000000..7b4886baf402 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/A.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.onetomany; + +import java.awt.List; +import java.util.ArrayList; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.Cascade; + +/** + * @author Peter Kotula + */ +@Entity +public class A { + @GeneratedValue(strategy = GenerationType.AUTO) + @Id + Long id; + + + @NotNull + String name; + + @OneToMany( cascade = CascadeType.ALL) + @Cascade(org.hibernate.annotations.CascadeType.ALL) + @OrderBy("name") + java.util.List bs = new ArrayList(); + + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public java.util.List getBs() { + return bs; + } + +// public void setBs(java.util.List bs) { +// this.bs = bs; +// } + + @Override + public String toString() { + return "A [id=" + id + ", name=" + name + ", bs=" + bs + "]"; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/B.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/B.java new file mode 100644 index 000000000000..81c9f148b92f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/B.java @@ -0,0 +1,83 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.onetomany; + +import java.util.ArrayList; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.Cascade; + +/** + * @author Peter Kotula + */ +@Entity +public class B { + @GeneratedValue(strategy = GenerationType.AUTO) + @Id + Long id; + + @NotNull + String name; + + @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @Cascade(org.hibernate.annotations.CascadeType.ALL) + @OrderBy("name") + java.util.List cs = new ArrayList(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public java.util.List getCs() { + return cs; + } + + @Override + public String toString() { + return "B [id=" + id + ", name=" + name + ", cs="+cs+"]"; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/C.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/C.java new file mode 100644 index 000000000000..098bc1e19337 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/C.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.onetomany; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +/** + * @author Peter Kotula + */ +@Entity +public class C { + @GeneratedValue(strategy = GenerationType.AUTO) + @Id + Long id; + + @NotNull + String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "C [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/City.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/City.java index b03aba307182..79b2b51d6ca6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/City.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/City.java @@ -2,15 +2,15 @@ package org.hibernate.test.annotations.onetomany; import java.util.ArrayList; import java.util.List; + import javax.persistence.Entity; -import javax.persistence.FetchType; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.OrderBy; -import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Immutable; /** @@ -52,8 +52,7 @@ public void setStreets(List streets) { } @OneToMany - @JoinColumn(name = "mainstreetcity_id") - @ForeignKey(name = "CITYSTR_FK") + @JoinColumn(name = "mainstreetcity_id", foreignKey = @ForeignKey(name = "CITYSTR_FK")) @OrderBy @Immutable public List getMainStreets() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java index 36455024eafe..27fa77d43841 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java @@ -26,30 +26,29 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; -import org.junit.Assert; -import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.annotations.Customer; import org.hibernate.test.annotations.Discount; import org.hibernate.test.annotations.Passport; import org.hibernate.test.annotations.Ticket; import org.hibernate.test.annotations.TicketComparator; -import org.hibernate.testing.FailureExpected; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -66,6 +65,7 @@ * @author Hardy Ferentschik */ @SuppressWarnings("unchecked") +@FailureExpectedWithNewMetamodel public class OneToManyTest extends BaseCoreFunctionalTestCase { @Test public void testColumnDefinitionPropagation() throws Exception { @@ -478,13 +478,13 @@ public void testOrderByOnSuperclassProperty() { @Test @TestForIssue( jiraKey = "HHH-4605" ) public void testJoinColumnConfiguredInXml() { - PersistentClass pc = configuration().getClassMapping( Model.class.getName() ); - Table table = pc.getRootTable(); - Iterator iter = table.getColumnIterator(); boolean joinColumnFound = false; - while(iter.hasNext()) { - Column column = (Column) iter.next(); - if(column.getName().equals( "model_manufacturer_join" )) { + EntityBinding entityBinding = metadata().getEntityBinding( Model.class.getName() ); + TableSpecification table = entityBinding.getPrimaryTable(); + for ( Value value : table.values() ) { + org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) value; + if(column.getColumnName().getText().equals( "model_manufacturer_join" )) { joinColumnFound = true; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java index c1f631a1c3bb..e0c64abf1dc4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java @@ -47,6 +47,7 @@ import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.sql.SimpleSelect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -58,6 +59,7 @@ * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) * @author Brett Meyer */ +@FailureExpectedWithNewMetamodel public class OrderByTest extends BaseCoreFunctionalTestCase { @Test public void testOrderByOnIdClassProperties() throws Exception { @@ -404,8 +406,22 @@ public void testInverseIndexCascaded() { forum = (Forum) s.get( Forum.class, forum.getId() ); - assertEquals( 1, forum.getPosts().size() ); + final Post post2 = new Post(); + post2.setName( "post2" ); + post2.setForum( forum ); + forum.getPosts().add( post2 ); + + forum = (Forum) s.merge( forum ); + + s.flush(); + s.clear(); + sessionFactory().getCache().evictEntityRegions(); + + forum = (Forum) s.get( Forum.class, forum.getId() ); + + assertEquals( 2, forum.getPosts().size() ); assertEquals( "post1", forum.getPosts().get( 0 ).getName() ); + assertEquals( "post2", forum.getPosts().get( 1 ).getName() ); assertEquals( 1, forum.getUsers().size() ); assertEquals( "john", forum.getUsers().get( 0 ).getName() ); } @@ -442,6 +458,73 @@ public void testOrderByNoElement() { assertEquals( 2, employee.getAssets().get( 1 ).getIdAsset().intValue() ); } + @Test + @TestForIssue( jiraKey = "HHH-9002" ) + public void testOrderByOneToManyWithJoinTable() { + A a = new A(); + a.setName( "a" ); + B b1 = new B(); + b1.setName( "b1" ); + B b2 = new B(); + b2.setName( "b2" ); + C c11 = new C(); + c11.setName( "c11" ); + C c12 = new C(); + c12.setName( "c12" ); + C c21 = new C(); + c21.setName( "c21" ); + C c22 = new C(); + c22.setName( "c22" ); + + a.getBs().add( b1 ); + a.getBs().add( b2 ); + b1.getCs().add( c11 ); + b1.getCs().add( c12 ); + b2.getCs().add( c21 ); + b2.getCs().add( c22 ); + + Session s = openSession(); + s.getTransaction().begin(); + s.persist( a ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + + b1 = (B) s.get( B.class, b1.getId() ); + assertEquals( "b1", b1.getName() ); + List cs = b1.getCs(); + assertEquals( 2, cs.size() ); + assertEquals( "c11", cs.get( 0 ).getName() ); + assertEquals( "c12", cs.get( 1 ).getName() ); + + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + + a = (A) s.get( A.class, a.getId() ); + assertEquals( "a", a.getName() ); + assertEquals( 2, a.getBs().size() ); + List bs = a.getBs(); + assertEquals( "b1", bs.get( 0 ).getName() ); + assertEquals( "b2", bs.get( 1 ).getName() ); + List b1cs = bs.get( 0 ).getCs(); + assertEquals( 2, b1cs.size() ); + assertEquals( "c11", b1cs.get( 0 ).getName() ); + assertEquals( "c12", b1cs.get( 1 ).getName() ); + List b2cs = bs.get( 1 ).getCs(); + assertEquals( 2, b2cs.size() ); + assertEquals( "c21", b2cs.get( 0 ).getName() ); + assertEquals( "c22", b2cs.get( 1 ).getName() ); + + s.delete( a ); + + s.getTransaction().commit(); + s.close(); + } @Override protected Class[] getAnnotatedClasses() { @@ -450,7 +533,8 @@ protected Class[] getAnnotatedClasses() { Monkey.class, Visitor.class, Box.class, Item.class, BankAccount.class, Transaction.class, Comment.class, Forum.class, Post.class, User.class, - Asset.class, Computer.class, Employee.class + Asset.class, Computer.class, Employee.class, + A.class, B.class, C.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Trainer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Trainer.java index fbc08e76c570..fe0e615af6a1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Trainer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Trainer.java @@ -1,15 +1,15 @@ //$Id$ package org.hibernate.test.annotations.onetomany; import java.util.Set; + import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; -import org.hibernate.annotations.ForeignKey; - /** * Unidirectional one to many sample * @@ -54,9 +54,10 @@ public void setTrainedTigers(Set trainedTigers) { name = "TrainedMonkeys", //columns are optional, here we explicit them joinColumns = @JoinColumn(name = "trainer_id"), - inverseJoinColumns = @JoinColumn(name = "monkey_id") + inverseJoinColumns = @JoinColumn(name = "monkey_id"), + foreignKey = @ForeignKey(name = "TM_TRA_FK"), + inverseForeignKey = @ForeignKey(name = "TM_MON_FK") ) - @ForeignKey(name = "TM_TRA_FK", inverseName = "TM_MON_FK") public Set getTrainedMonkeys() { return trainedMonkeys; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Troop.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Troop.java index fb985a7d958b..ddf2f1745b87 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Troop.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Troop.java @@ -2,6 +2,7 @@ package org.hibernate.test.annotations.onetomany; import java.util.HashSet; import java.util.Set; + import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -24,9 +25,8 @@ public class Troop { private String name; private Set soldiers; - @OneToMany(mappedBy = "troop", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) + @OneToMany(mappedBy = "troop", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, orphanRemoval = true) @OrderBy(clause = "name desc") - @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @OnDelete(action = OnDeleteAction.CASCADE) public Set getSoldiers() { return soldiers; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java index 0da443dc7ae6..884ef21da4e0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneErrorTest.java @@ -1,4 +1,3 @@ -//$Id$ package org.hibernate.test.annotations.onetoone; import org.junit.Assert; @@ -9,13 +8,16 @@ import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Environment; import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.testing.junit4.BaseUnitTestCase; /** * @author Emmanuel Bernard */ -public class OneToOneErrorTest { +public class OneToOneErrorTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel public void testWrongOneToOne() throws Exception { AnnotationConfiguration cfg = new AnnotationConfiguration(); cfg.addAnnotatedClass( Show.class ) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java index 7e6e8c28513c..a3a9c4697c6b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java @@ -23,33 +23,30 @@ */ package org.hibernate.test.annotations.onetoone; -import java.util.Iterator; - -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.hibernate.EmptyInterceptor; +import org.hibernate.MappingException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.annotations.Customer; import org.hibernate.test.annotations.Discount; import org.hibernate.test.annotations.Passport; import org.hibernate.test.annotations.Ticket; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class OneToOneTest extends BaseCoreFunctionalTestCase { @Test public void testEagerFetching() throws Exception { @@ -309,24 +306,12 @@ public void testForeignGenerator() { @Test @TestForIssue( jiraKey = "HHH-4606" ) public void testJoinColumnConfiguredInXml() { - PersistentClass pc = configuration().getClassMapping( Son.class.getName() ); - Iterator iter = pc.getJoinIterator(); - Table table = ( ( Join ) iter.next() ).getTable(); - Iterator columnIter = table.getColumnIterator(); - boolean fooFound = false; - boolean barFound = false; - while ( columnIter.hasNext() ) { - Column column = ( Column ) columnIter.next(); - if ( column.getName().equals( "foo" ) ) { - fooFound = true; - } - if ( column.getName().equals( "bar" ) ) { - barFound = true; - } - } - assertTrue( - "The mapping defines join columns which could not be found in the metadata.", fooFound && barFound - ); + EntityBinding entityBinding = metadata().getEntityBinding( Son.class.getName() ); + TableSpecification table = entityBinding.getSecondaryTables().values().iterator().next().getSecondaryTableReference(); + org.hibernate.metamodel.spi.relational.Column c1= table.locateColumn( "foo" ); + assertNotNull( c1 ); + org.hibernate.metamodel.spi.relational.Column c2= table.locateColumn( "bar" ); + assertNotNull( c2 ); } @Test @@ -398,6 +383,7 @@ protected Class[] getAnnotatedClasses() { Client.class, Address.class, Computer.class, + ComputerPk.class, SerialNumber.class, Body.class, Heart.class, @@ -410,54 +396,60 @@ protected Class[] getAnnotatedClasses() { protected String[] getXmlFiles() { return new String[] { "org/hibernate/test/annotations/onetoone/orm.xml" }; } -} - - -/** - * Verifies that generated 'select' statement has desired number of joins - * @author Sharath Reddy - * - */ -class JoinCounter extends EmptyInterceptor { - - private static final long serialVersionUID = -3689681272273261051L; - - private int expectedNumberOfJoins = 0; - - public JoinCounter(int val) { - super(); - this.expectedNumberOfJoins = val; - } - public String onPrepareStatement(String sql) { - int numberOfJoins = 0; - if (sql.startsWith("select") & !sql.contains("nextval")) { - numberOfJoins = count(sql, "join"); - assertEquals( expectedNumberOfJoins, numberOfJoins ); - } - - return sql; - } - - /** - * Count the number of instances of substring within a string. - * - * @param string String to look for substring in. - * @param substring Sub-string to look for. - * @return Count of substrings in string. - */ - private int count(final String string, final String substring) - { - int count = 0; - int idx = 0; - - while ((idx = string.indexOf(substring, idx)) != -1) - { - idx++; - count++; + /** + * Verifies that generated 'select' statement has desired number of joins + * @author Sharath Reddy + * + */ + class JoinCounter extends EmptyInterceptor { + + private static final long serialVersionUID = -3689681272273261051L; + + private int expectedNumberOfJoins = 0; + private String nextValRegex; + + public JoinCounter(int val) { + super(); + this.expectedNumberOfJoins = val; + try { + nextValRegex = ".*" + getDialect().getSelectSequenceNextValString(".*") + ".*"; + nextValRegex = nextValRegex.replace( "(", "\\(" ); + nextValRegex = nextValRegex.replace( ")", "\\)" ); + } catch (MappingException ex) { + nextValRegex = "nextval"; + } + } + + public String onPrepareStatement(String sql) { + int numberOfJoins = 0; + if (sql.startsWith("select") & !sql.matches(nextValRegex)) { + numberOfJoins = count(sql, "join"); + assertEquals( sql, expectedNumberOfJoins, numberOfJoins ); + } + + return sql; } - - return count; - } - + + /** + * Count the number of instances of substring within a string. + * + * @param string String to look for substring in. + * @param substring Sub-string to look for. + * @return Count of substrings in string. + */ + private int count(final String string, final String substring) + { + int count = 0; + int idx = 0; + + while ((idx = string.indexOf(substring, idx)) != -1) + { + idx++; + count++; + } + + return count; + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java index cb754fae1cfd..4aac884a9962 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OptionalOneToOneMappedByTest.java @@ -29,6 +29,7 @@ import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.id.IdentifierGenerationException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -44,6 +45,7 @@ public class OptionalOneToOneMappedByTest extends BaseCoreFunctionalTestCase { // @OneToOne(mappedBy="address") with foreign generator @Test + @FailureExpectedWithNewMetamodel( message = "mappedBy @OneToOne with foreign generator" ) public void testBidirForeignIdGenerator() { Session s = openSession(); Transaction tx = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/primarykey/NullablePrimaryKeyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/primarykey/NullablePrimaryKeyTest.java index be6ce4e9e7d4..d87a37d96727 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/primarykey/NullablePrimaryKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/primarykey/NullablePrimaryKeyTest.java @@ -1,55 +1,55 @@ //$Id: A320.java 14736 2008-06-04 14:23:42Z hardy.ferentschik $ package org.hibernate.test.annotations.onetoone.primarykey; -import org.jboss.logging.Logger; -import org.junit.Assert; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Table; + +import org.hibernate.test.util.SchemaUtil; import org.junit.Test; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.AnnotationConfiguration; -import org.hibernate.cfg.Environment; -import org.hibernate.dialect.SQLServerDialect; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; +import org.jboss.logging.Logger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * Test harness for ANN-742. * * @author Hardy Ferentschik - * */ public class NullablePrimaryKeyTest { private static final Logger log = Logger.getLogger( NullablePrimaryKeyTest.class ); + @Test public void testGeneratedSql() { + MetadataImplementor metadata = (MetadataImplementor) new MetadataSources() + .addAnnotatedClass( Address.class ) + .addAnnotatedClass( Person.class ) + .buildMetadata(); - ServiceRegistry serviceRegistry = null; - SessionFactory sf = null; - try { - AnnotationConfiguration config = new AnnotationConfiguration(); - config.addAnnotatedClass(Address.class); - config.addAnnotatedClass(Person.class); - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() ); - sf = config.buildSessionFactory( serviceRegistry ); - String[] schema = config - .generateSchemaCreationScript(new SQLServerDialect()); - for (String s : schema) { - log.debug(s); - } - String expectedMappingTableSql = "create table personAddress (address_id numeric(19,0), " + - "person_id numeric(19,0) not null, primary key (person_id))"; - Assert.assertEquals( "Wrong SQL", expectedMappingTableSql, schema[2] ); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - finally { - if ( sf != null ) { - sf.close(); + Table table = (Table) SchemaUtil.getTable( "personAddress", metadata ); + PrimaryKey pk = table.getPrimaryKey(); + assertEquals( 1, pk.getColumns().size() ); + + boolean foundAddressId = false; + boolean foundPersonId = false; + + for ( Column column : table.sortedColumns() ) { + if ( "address_id".equals( column.getColumnName().getText() ) ) { + foundAddressId = true; + assertTrue( column.isNullable() ); } - if ( serviceRegistry != null ) { - ServiceRegistryBuilder.destroy( serviceRegistry ); + else if ( "person_id".equals( column.getColumnName().getText() ) ) { + foundPersonId = true; + assertFalse( column.isNullable() ); } - } + + assertTrue( foundAddressId ); + assertTrue( foundPersonId ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java index f3aa4e874db3..3a24b12880cd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideSchemaTest.java @@ -7,7 +7,9 @@ import org.hibernate.dialect.H2Dialect; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.util.SchemaUtil; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -17,6 +19,7 @@ */ @RequiresDialect({ H2Dialect.class }) @TestForIssue(jiraKey = "HHH-6662") +@FailureExpectedWithNewMetamodel public class AssociationOverrideSchemaTest extends BaseCoreFunctionalTestCase { public static final String SCHEMA_NAME = "OTHER_SCHEMA"; public static final String TABLE_NAME = "BLOG_TAGS"; @@ -35,24 +38,18 @@ protected String createSecondSchema() { @Test public void testJoinTableSchemaName() { - Iterator
    tableIterator = configuration().getTableMappings(); - while ( tableIterator.hasNext() ) { - Table table = tableIterator.next(); - if ( TABLE_NAME.equals( table.getName() ) ) { - Assert.assertEquals( SCHEMA_NAME, table.getSchema() ); - return; - } - } - Assert.fail(); + TableSpecification table = SchemaUtil.getTable( TABLE_NAME, metadata() ); + Assert.assertNotNull( table ); + Assert.assertEquals( SCHEMA_NAME, table.getSchema().getName().getSchema().getText()); } @Test public void testJoinTableJoinColumnName() { - Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, ID_COLUMN_NAME, configuration() ) ); + Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, ID_COLUMN_NAME, metadata() ) ); } @Test public void testJoinTableColumnName() { - Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, VALUE_COLUMN_NAME, configuration() ) ); + Assert.assertTrue( SchemaUtil.isColumnPresent( TABLE_NAME, VALUE_COLUMN_NAME, metadata() ) ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java index dc76dcc9fb69..e51d9eb4a232 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AssociationOverrideTest.java @@ -4,13 +4,14 @@ import java.util.Collection; import java.util.List; -import org.junit.Test; - import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.test.util.SchemaUtil; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -18,6 +19,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class AssociationOverrideTest extends BaseCoreFunctionalTestCase { @Test public void testOverriding() throws Exception { @@ -48,15 +50,15 @@ public void testOverriding() throws Exception { @Test public void testDottedNotation() throws Exception { - assertTrue( SchemaUtil.isTablePresent( "Employee", configuration() ) ); + assertTrue( SchemaUtil.isTablePresent( "Employee", metadata() ) ); assertTrue( "Overridden @JoinColumn fails", - SchemaUtil.isColumnPresent( "Employee", "fld_address_fk", configuration() ) ); + SchemaUtil.isColumnPresent( "Employee", "fld_address_fk", metadata() ) ); - assertTrue( "Overridden @JoinTable name fails", SchemaUtil.isTablePresent( "tbl_empl_sites", configuration() ) ); + assertTrue( "Overridden @JoinTable name fails", SchemaUtil.isTablePresent( "tbl_empl_sites", metadata() ) ); assertTrue( "Overridden @JoinTable with default @JoinColumn fails", - SchemaUtil.isColumnPresent( "tbl_empl_sites", "employee_id", configuration() ) ); + SchemaUtil.isColumnPresent( "tbl_empl_sites", "employee_id", metadata() ) ); assertTrue( "Overridden @JoinTable.inverseJoinColumn fails", - SchemaUtil.isColumnPresent( "tbl_empl_sites", "to_website_fk", configuration() ) ); + SchemaUtil.isColumnPresent( "tbl_empl_sites", "to_website_fk", metadata() ) ); Session s = openSession(); Transaction tx = s.beginTransaction(); @@ -106,7 +108,8 @@ protected Class[] getAnnotatedClasses() { PhoneNumber.class, Addr.class, SocialSite.class, - SocialTouchPoints.class + SocialTouchPoints.class, + ContactInfo.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java index 481730b11782..1977c398fd80 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/override/AttributeOverrideTest.java @@ -23,10 +23,9 @@ */ package org.hibernate.test.annotations.override; -import org.junit.Test; - -import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertTrue; @@ -57,7 +56,7 @@ public void testElementCollection() throws Exception { } public boolean isColumnPresent(String tableName, String columnName) { - return SchemaUtil.isColumnPresent( tableName, columnName, configuration() ); + return SchemaUtil.isColumnPresent( tableName, columnName, metadata() ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Card.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Card.java index 5d832a7e9515..c8ab16365e29 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Card.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Card.java @@ -1,15 +1,18 @@ package org.hibernate.test.annotations.persister; import java.io.Serializable; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import org.hibernate.annotations.Persister; + /** * @author Shawn Clowater */ @Entity -@org.hibernate.annotations.Entity( persister = "org.hibernate.persister.entity.SingleTableEntityPersister" ) +@Persister(impl = org.hibernate.persister.entity.SingleTableEntityPersister.class) public class Card implements Serializable { @Id public Integer id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/CollectionPersister.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/CollectionPersister.java index ac7148eddaad..8cb869b1708e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/CollectionPersister.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/CollectionPersister.java @@ -1,18 +1,22 @@ package org.hibernate.test.annotations.persister; + import org.hibernate.MappingException; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; -import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.mapping.Collection; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; import org.hibernate.persister.collection.OneToManyPersister; /** * @author Shawn Clowater */ public class CollectionPersister extends OneToManyPersister { - public CollectionPersister(Collection collection, CollectionRegionAccessStrategy cache, Configuration cfg, - SessionFactoryImplementor factory) throws MappingException, CacheException { - super( collection, cache, cfg, factory ); + public CollectionPersister( + AbstractPluralAttributeBinding collection, + CollectionRegionAccessStrategy cacheAccessStrategy, + MetadataImplementor metadataImplementor, + SessionFactoryImplementor factory) throws MappingException, CacheException { + super( collection, cacheAccessStrategy, metadataImplementor, factory ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Deck.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Deck.java index 8d5a29382bc4..3264e67d5788 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Deck.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/Deck.java @@ -1,6 +1,7 @@ package org.hibernate.test.annotations.persister; import java.io.Serializable; import java.util.Set; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; @@ -12,7 +13,6 @@ * @author Shawn Clowater */ @Entity -@org.hibernate.annotations.Entity( persister = "org.hibernate.persister.entity.SingleTableEntityPersister" ) @Persister( impl = org.hibernate.test.annotations.persister.EntityPersister.class ) public class Deck implements Serializable { @Id diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/EntityPersister.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/EntityPersister.java index 000837814438..1db19093bf7f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/EntityPersister.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/EntityPersister.java @@ -1,19 +1,19 @@ package org.hibernate.test.annotations.persister; + import org.hibernate.HibernateException; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.persister.entity.SingleTableEntityPersister; /** * @author Shawn Clowater */ public class EntityPersister extends SingleTableEntityPersister { - public EntityPersister(PersistentClass persistentClass, EntityRegionAccessStrategy cache, - NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - SessionFactoryImplementor factory, Mapping cfg) throws HibernateException { - super( persistentClass, cache, naturalIdRegionAccessStrategy, factory, cfg ); + public EntityPersister(EntityBinding entityBinding, EntityRegionAccessStrategy cacheAccessStrategy, NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, SessionFactoryImplementor factory, Mapping mapping) + throws HibernateException { + super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, mapping ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java index 5d357925ced3..7eb3c23b5d11 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/persister/PersisterTest.java @@ -23,14 +23,13 @@ */ package org.hibernate.test.annotations.persister; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * @author Shawn Clowater @@ -39,32 +38,43 @@ public class PersisterTest extends BaseCoreFunctionalTestCase { @Test public void testEntityEntityPersisterAndPersisterSpecified() throws Exception { //checks to see that the persister specified with the @Persister annotation takes precedence if a @Entity.persister() is also specified - PersistentClass persistentClass = configuration().getClassMapping( Deck.class.getName() ); - assertEquals( "Incorrect Persister class for " + persistentClass.getMappedClass(), EntityPersister.class, - persistentClass.getEntityPersisterClass() ); + Class clazz = + metadata().getEntityBinding( Deck.class.getName() ).getCustomEntityPersisterClass(); + assertEquals( "Incorrect Persister class for " + Deck.class.getName(), + org.hibernate.test.annotations.persister.EntityPersister.class, clazz ); } @Test public void testEntityEntityPersisterSpecified() throws Exception { //tests the persister specified with an @Entity.persister() - PersistentClass persistentClass = configuration().getClassMapping( Card.class.getName() ); - assertEquals( "Incorrect Persister class for " + persistentClass.getMappedClass(), - SingleTableEntityPersister.class, persistentClass.getEntityPersisterClass() ); + Class clazz = + metadata().getEntityBinding( Card.class.getName() ).getCustomEntityPersisterClass(); + assertEquals( "Incorrect Persister class for " + Card.class.getName(), + SingleTableEntityPersister.class, clazz ); } @Test public void testCollectionPersisterSpecified() throws Exception { //tests the persister specified by the @Persister annotation on a collection - Collection collection = configuration().getCollectionMapping( Deck.class.getName() + ".cards" ); - assertEquals( "Incorrect Persister class for collection " + collection.getRole(), CollectionPersister.class, - collection.getCollectionPersisterClass() ); + String expectedRole = Deck.class.getName() + ".cards"; + boolean found = false; + for ( PluralAttributeBinding attributeBinding : metadata().getCollectionBindings() ) { + String role = attributeBinding.getAttribute().getRole(); + //tests the persister specified by the @Persister annotation on a collection + if ( expectedRole.equals( role ) ) { + assertEquals( + "Incorrect Persister class for collection " + role, CollectionPersister.class, + attributeBinding.getExplicitPersisterClass() + ); + found = true; + break; + } + } + assertTrue( found ); } @Override protected Class[] getAnnotatedClasses() { - return new Class[]{ - Card.class, - Deck.class - }; + return new Class[] { Card.class, Deck.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/Car.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/Car.java index e9c31007134d..88aad34c41d1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/Car.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/Car.java @@ -8,6 +8,7 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import org.hibernate.annotations.Polymorphism; import org.hibernate.annotations.PolymorphismType; /** @@ -15,7 +16,7 @@ */ @Entity @Inheritance(strategy= InheritanceType.TABLE_PER_CLASS) -@org.hibernate.annotations.Entity(polymorphism = PolymorphismType.EXPLICIT) +@Polymorphism(type = PolymorphismType.EXPLICIT) public class Car extends Automobile { @Id diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java index 211482435c30..acd2cb9a2d1f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/PolymorphismTest.java @@ -23,14 +23,13 @@ */ package org.hibernate.test.annotations.polymorphism; -import org.junit.Test; +import static org.junit.Assert.assertEquals; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * @author Emmanuel Bernard diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/SportCar.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/SportCar.java index 5e25658abf63..2bd5366761dc 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/SportCar.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/polymorphism/SportCar.java @@ -3,6 +3,7 @@ import javax.persistence.Entity; import javax.persistence.Table; +import org.hibernate.annotations.Polymorphism; import org.hibernate.annotations.PolymorphismType; /** @@ -10,6 +11,6 @@ */ @Entity @Table(name = "sport_car") -@org.hibernate.annotations.Entity(polymorphism = PolymorphismType.EXPLICIT) //raise a warn +@Polymorphism(type = PolymorphismType.EXPLICIT) //raise a warn public class SportCar extends Car { } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java index 7f358a4b12d1..8a79eb865cc9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java @@ -24,13 +24,17 @@ */ package org.hibernate.test.annotations.query; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; -import org.junit.Test; - import org.hibernate.MappingException; import org.hibernate.Query; import org.hibernate.SQLQuery; @@ -38,28 +42,23 @@ import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.function.SQLFunction; import org.hibernate.stat.Statistics; import org.hibernate.test.annotations.A320; import org.hibernate.test.annotations.A320b; import org.hibernate.test.annotations.Plane; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.junit.Test; /** * Test named queries * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel(message = "due to derived ids are not supported") public class QueryAndSQLTest extends BaseCoreFunctionalTestCase { @Override protected boolean isCleanupTestDataRequired() { @@ -284,6 +283,7 @@ public void testImplicitNativeQuery() throws Exception { } @Test + @FailureExpectedWithNewMetamodel public void testNativeQueryAndCompositePKAndComponents() throws Exception { Session s; Transaction tx; @@ -355,7 +355,7 @@ public void testDiscriminator() throws Exception { } @Test - @SkipForDialect(value = { PostgreSQL81Dialect.class, PostgreSQLDialect.class }, + @SkipForDialect(value = { PostgreSQL81Dialect.class }, comment = "postgresql jdbc driver does not implement the setQueryTimeout method") public void testCache() throws Exception { Session s; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java index aa51b685b433..91a04f3a7092 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/referencedcolumnname/ReferencedColumnNameTest.java @@ -31,6 +31,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ReferencedColumnNameTest extends BaseCoreFunctionalTestCase { @Test public void testManyToOne() throws Exception { @@ -284,7 +286,8 @@ protected Class[] getAnnotatedClasses() { Vendor.class, WarehouseItem.class, Place.class, - HousePlaces.class + HousePlaces.class, + Places.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java index 9b5b5df7459c..e52d0007c45c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Location.java @@ -2,9 +2,12 @@ package org.hibernate.test.annotations.strategy; +import javax.persistence.Embeddable; + /** * @author Emmanuel Bernard */ +@Embeddable public class Location { private String city; private String country; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java index 7f0901fe74fb..f20a11299de3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/Storm.java @@ -5,16 +5,16 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.Table; import javax.persistence.UniqueConstraint; -import org.hibernate.annotations.Index; - /** * @author Emmanuel Bernard */ @Entity -@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"start.country", "start.city"})}) +@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"start.country", "start.city"}), + indexes = @Index(name="storm_name_idx", columnList = "stormName")) public class Storm { private Integer id; private Location start; @@ -49,7 +49,6 @@ public void setEnd(Location end) { this.end = end; } - @Index(name="storm_name_idx") @Column(unique = true) public String getStormName() { return stormName; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java index 39aeff948aa2..808b1f1a5105 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/strategy/StrategyTest.java @@ -29,11 +29,13 @@ import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.DefaultComponentSafeNamingStrategy; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class StrategyTest extends BaseCoreFunctionalTestCase { @Test public void testComponentSafeStrategy() throws Exception { @@ -61,6 +63,6 @@ protected void configure(Configuration cfg) { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Storm.class }; + return new Class[] { Storm.class, Location.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tableperclass/Component.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tableperclass/Component.java index 776647757fc1..d8be2baa7020 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tableperclass/Component.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tableperclass/Component.java @@ -3,16 +3,17 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; - -import org.hibernate.annotations.Index; +import javax.persistence.Table; /** * @author Emmanuel Bernard */ @Entity(name = "xpmComponent") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +@Table(indexes = @Index(name = "manufacturerPartNumber", columnList = "manufacturerPartNumber")) public abstract class Component { private String manufacturerPartNumber; private Long manufacturerId; @@ -31,7 +32,6 @@ public Long getId() { } @Column(nullable = false) - @Index(name = "manufacturerPartNumber") public String getManufacturerPartNumber() { return manufacturerPartNumber; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java index b0ec9c21be76..b89b1e77c182 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/target/TargetTest.java @@ -26,6 +26,7 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -33,8 +34,10 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class TargetTest extends BaseCoreFunctionalTestCase { @Test + @FailureExpectedWithNewMetamodel public void testTargetOnEmbedded() throws Exception { Session s = openSession(); s.getTransaction().begin(); @@ -103,6 +106,6 @@ public void testTargetOnMapKeyManyToMany() throws Exception { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { LuggageImpl.class, Brand.class }; + return new Class[] { LuggageImpl.class, Brand.class, OwnerImpl.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java index d7fbb09d2b12..d3204a0ed17b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicComponentTuplizer.java @@ -1,6 +1,7 @@ -//$Id$ package org.hibernate.test.annotations.tuplizer; -import org.hibernate.mapping.Component; + +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.component.PojoComponentTuplizer; @@ -9,11 +10,19 @@ */ public class DynamicComponentTuplizer extends PojoComponentTuplizer { - public DynamicComponentTuplizer(Component component) { - super( component ); + public DynamicComponentTuplizer( + ServiceRegistry serviceRegistry, + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper) { + super( serviceRegistry, embeddableBinding, isIdentifierMapper); } - protected Instantiator buildInstantiator(Component component) { - return new DynamicInstantiator( component.getComponentClassName() ); //To change body of overridden methods use File | Settings | File Templates. + @Override + protected Instantiator buildInstantiator( + EmbeddableBinding embeddableBinding, + boolean isIdentifierMapper) { + return new DynamicInstantiator( + embeddableBinding.getAttributeContainer().getDescriptor().getName().toString() + ); } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java index 34a13e9a8f3a..e3713e25a708 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/DynamicEntityTuplizer.java @@ -1,9 +1,11 @@ //$Id$ package org.hibernate.test.annotations.tuplizer; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.PojoEntityTuplizer; @@ -12,20 +14,21 @@ * @author Emmanuel Bernard */ public class DynamicEntityTuplizer extends PojoEntityTuplizer { + public DynamicEntityTuplizer(ServiceRegistry serviceRegistry, EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { + super( serviceRegistry, entityMetamodel, mappedEntity ); + } - public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super( entityMetamodel, mappedEntity ); - } + protected Instantiator buildInstantiator(PersistentClass persistentClass) { + return new DynamicInstantiator( persistentClass.getEntityName() ); + } - protected Instantiator buildInstantiator(PersistentClass persistentClass) { - return new DynamicInstantiator( persistentClass.getEntityName() ); - } + @Override + protected Instantiator buildInstantiator(EntityBinding entityBinding) { + return new DynamicInstantiator( entityBinding.getEntityName() ); + } - protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { - // allows defining a custom proxy factory, which is responsible for - // generating lazy proxies for a given entity. - // - // Here we simply use the default... - return super.buildProxyFactory( persistentClass, idGetter, idSetter ); - } + @Override + protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { + return super.buildProxyFactoryInternal( entityBinding, idGetter, idSetter ); } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java index 72483e3233d7..3b7e260decc8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/tuplizer/TuplizerTest.java @@ -57,6 +57,6 @@ public void testEntityTuplizer() throws Exception { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Cuisine.class }; + return new Class[] { Cuisine.class, Country.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintTest.java index 6840b0435342..fbdd352b9457 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintTest.java @@ -1,12 +1,7 @@ package org.hibernate.test.annotations.uniqueconstraint; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.fail; - import java.util.HashSet; -import java.util.Iterator; import java.util.Set; - import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; @@ -23,10 +18,17 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; + import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + /** * @author Manuel Bernhardt * @author Brett Meyer @@ -76,29 +78,30 @@ public void testUniquenessConstraintWithSuperclassProperty() throws Exception { @Test @TestForIssue( jiraKey = "HHH-8026" ) public void testUnNamedConstraints() { - Configuration cfg = new Configuration(); - cfg.addAnnotatedClass( UniqueNoNameA.class ); - cfg.addAnnotatedClass( UniqueNoNameB.class ); - cfg.buildMappings(); - Iterator iterator = cfg.getTableMappings(); - org.hibernate.mapping.Table tableA = null; - org.hibernate.mapping.Table tableB = null; - while( iterator.hasNext() ) { - org.hibernate.mapping.Table table = iterator.next(); - if ( table.getName().equals( "UniqueNoNameA" ) ) { + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( UniqueNoNameA.class ) + .addAnnotatedClass( UniqueNoNameB.class ); + MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); + + org.hibernate.metamodel.spi.relational.Table tableA = null; + org.hibernate.metamodel.spi.relational.Table tableB = null; + + for ( org.hibernate.metamodel.spi.relational.Table table : metadata.getDatabase().getDefaultSchema().getTables() ) { + if ( table.getPhysicalName().getText().equals( "UniqueNoNameA" ) ) { tableA = table; } - else if ( table.getName().equals( "UniqueNoNameB" ) ) { + else if ( table.getPhysicalName().getText().equals( "UniqueNoNameB" ) ) { tableB = table; } } - - if ( tableA == null || tableB == null ) { - fail( "Could not find the expected tables." ); - } - - assertFalse( tableA.getUniqueKeyIterator().next().getName().equals( - tableB.getUniqueKeyIterator().next().getName() ) ); + + assertNotNull( "Could not find table A", tableA ); + assertNotNull( "Could not find table B", tableB ); + + assertNotEquals( + tableA.getUniqueKeys().iterator().next().getName(), + tableB.getUniqueKeys().iterator().next().getName() + ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java index d1976fd2b02f..7cddc9283a7f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintValidationTest.java @@ -7,7 +7,7 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; -import org.hibernate.AnnotationException; +import org.hibernate.MappingException; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.spi.ServiceRegistryImplementor; @@ -21,7 +21,7 @@ */ public class UniqueConstraintValidationTest extends BaseUnitTestCase { - @Test(expected = AnnotationException.class) + @Test(expected = MappingException.class) @TestForIssue(jiraKey = "HHH-4084") public void testUniqueConstraintWithEmptyColumnName() { buildSessionFactory(EmptyColumnNameEntity.class); @@ -32,7 +32,7 @@ public void testUniqueConstraintWithEmptyColumnNameList() { buildSessionFactory(EmptyColumnNameListEntity.class); } - @Test(expected = AnnotationException.class) + @Test(expected = MappingException.class) public void testUniqueConstraintWithNotExistsColumnName() { buildSessionFactory(NotExistsColumnEntity.class); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Conductor.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Conductor.java index d29877ea8006..aa65d6e0e771 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Conductor.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Conductor.java @@ -4,22 +4,23 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.Table; import javax.persistence.Version; -import org.hibernate.annotations.Index; import org.hibernate.annotations.OptimisticLock; /** * @author Emmanuel Bernard */ @Entity +@Table(indexes = @Index(name = "cond_name", columnList = "cond_name")) public class Conductor { @Id @GeneratedValue private Integer id; @Column(name = "cond_name") - @Index(name = "cond_name") @OptimisticLock(excluded = true) private String name; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java index cd2948a87189..5a9bf30011d2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java @@ -23,14 +23,14 @@ */ package org.hibernate.test.annotations.various; -import org.junit.Test; - -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; import org.hibernate.metadata.ClassMetadata; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.type.DbTimestampType; import org.hibernate.type.TimestampType; +import org.hibernate.type.Type; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -53,15 +53,17 @@ public void testTimestampSourceIsDB() throws Exception { } private void assertTimestampSource(Class clazz, Class expectedTypeClass) throws Exception { - buildConfiguration(); + constructAndConfigureConfiguration(); ClassMetadata meta = sessionFactory().getClassMetadata( clazz ); assertTrue( "Entity is annotated with @Timestamp and should hence be versioned", meta.isVersioned() ); - PersistentClass persistentClass = configuration().getClassMapping( clazz.getName() ); - assertNotNull( persistentClass ); - Property versionProperty = persistentClass.getVersion(); - assertNotNull( versionProperty ); - assertEquals( "Wrong timestamp type", expectedTypeClass, versionProperty.getType().getClass() ); + EntityBinding binding = metadata().getEntityBinding( clazz.getName() ); + assertNotNull( binding ); + Type type = binding.getHierarchyDetails().getEntityVersion() + .getVersioningAttributeBinding().getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + assertNotNull( type ); + assertEquals( "Wrong timestamp type", expectedTypeClass, type.getClass() ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Truck.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Truck.java index 8c8f530ed50b..48abeee32041 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Truck.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Truck.java @@ -1,22 +1,23 @@ //$Id$ package org.hibernate.test.annotations.various; import javax.persistence.Entity; +import javax.persistence.Index; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; - -import org.hibernate.annotations.Index; +import javax.persistence.Table; /** * @author Emmanuel Bernard */ @Entity +@Table(indexes = { + @Index(name = "weigth_idx", columnList = "weight"), + @Index(name = "agreement_idx", columnList = "agreement_id")}) public class Truck extends Vehicule { - @Index(name = "weigth_idx") private int weight; @ManyToOne @JoinColumn(name = "agreement_id") - @Index(name = "agreement_idx") private ProfessionalAgreement agreement; public int getWeight() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Vehicule.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Vehicule.java index 0dca01802509..5c4a2a50b0c4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Vehicule.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/various/Vehicule.java @@ -4,25 +4,26 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Index; +import org.hibernate.annotations.Table; /** * @author Emmanuel Bernard */ @Entity @Inheritance(strategy = InheritanceType.JOINED) -@org.hibernate.annotations.Table(appliesTo = "Vehicule", - indexes = { - @Index(name = "improbableindex", columnNames = {"registration", "Conductor_fk"}), - @Index(name = "secondone", columnNames = {"Conductor_fk"}) - } -) +@Table(appliesTo = "Vehicule", indexes = { + @Index(name = "improbableindex", columnList = "registration, Conductor_fk"), + @Index(name = "secondone", columnList = "Conductor_fk"), + @Index(name = "thirdone", columnList = "Conductor_fk"), + @Index(name = "year_idx", columnList = "year"), + @Index(name = "forthone", columnList = "previousConductor")}) public class Vehicule { @Id @GeneratedValue(generator = "gen") @@ -32,12 +33,9 @@ public class Vehicule { private String registrationNumber; @ManyToOne(optional = false) @JoinColumn(name = "Conductor_fk") - @Index(name = "thirdone") private Conductor currentConductor; - @Index(name = "year_idx") private Integer year; @ManyToOne(optional = true) - @Index(name = "forthone") private Conductor previousConductor; public String getId() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java index 21a2308357d5..98d6e17b9f23 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/Ejb3XmlTest.java @@ -23,29 +23,29 @@ */ package org.hibernate.test.annotations.xml.ejb3; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + import java.util.Date; import java.util.List; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.persister.collection.BasicCollectionPersister; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import org.junit.Test; /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class Ejb3XmlTest extends BaseCoreFunctionalTestCase { @Test - @SkipForDialect(value = { PostgreSQL81Dialect.class, PostgreSQLDialect.class }, + @SkipForDialect(value = { PostgreSQL81Dialect.class }, comment = "postgresql jdbc driver does not implement the setQueryTimeout method") public void testEjb3Xml() throws Exception { Session s = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/NonExistentOrmVersionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/NonExistentOrmVersionTest.java index 76eb7c33e443..0658a17e3096 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/NonExistentOrmVersionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/xml/ejb3/NonExistentOrmVersionTest.java @@ -23,16 +23,13 @@ */ package org.hibernate.test.annotations.xml.ejb3; -import java.io.InputStream; - -import org.hibernate.InvalidMappingException; -import org.hibernate.cfg.Configuration; -import org.hibernate.internal.util.xml.UnsupportedOrmXsdVersionException; - -import org.junit.Test; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.source.spi.InvalidMappingException; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.fail; @@ -41,16 +38,11 @@ public class NonExistentOrmVersionTest extends BaseCoreFunctionalTestCase { @Test public void testNonExistentOrmVersion() { try { - Configuration config = buildConfiguration(); - String xmlFileName = "org/hibernate/test/annotations/xml/ejb3/orm5.xml"; - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( xmlFileName ); - config.addInputStream( is ); - config.buildMappings(); + MetadataSources sources = new MetadataSources( new BootstrapServiceRegistryBuilder().build() ); + sources.addResource( "org/hibernate/test/annotations/xml/ejb3/orm5.xml" ); fail( "Expecting failure due to unsupported xsd version" ); } - catch ( InvalidMappingException expected ) { - } - catch ( UnsupportedOrmXsdVersionException expected ) { + catch (InvalidMappingException expected) { } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/any/AnyTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/any/AnyTypeTest.java index 06b93d6f66ba..e5c74a8d2c19 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/any/AnyTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/any/AnyTypeTest.java @@ -28,6 +28,7 @@ import org.hibernate.Session; import org.hibernate.hql.internal.ast.QuerySyntaxException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -74,6 +75,7 @@ public void testFlushProcessing() { } @Test( expected = QuerySyntaxException.class ) + @FailureExpectedWithNewMetamodel public void testJoinFetchOfAnAnyTypeAttribute() { // Query translator should dis-allow join fetching of an mapping. Let's make sure it does... Session session = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java b/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java index b4e32a387602..ddfb32000ed7 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java @@ -22,26 +22,26 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.bidi; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import java.math.BigDecimal; import java.util.Date; -import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class AuctionTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "bidi/Auction.hbm.xml" }; @@ -49,7 +49,7 @@ public String[] getMappings() { @Test @SuppressWarnings( {"unchecked"}) - @SkipForDialect( value = {PostgreSQL81Dialect.class, PostgreSQLDialect.class}, comment = "doesn't like boolean=1" ) + @SkipForDialect( value = {PostgreSQL81Dialect.class}, comment = "doesn't like boolean=1" ) public void testLazy() { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java index 15f84e0fddbd..bc68956627a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java @@ -304,8 +304,6 @@ private EntityEntry makeEntityEntry() { LockMode.NONE, false, null, - EntityMode.POJO, - null, false, false, null diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/customer/CustomerEnhancerTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/customer/CustomerEnhancerTest.java index 122bd5eeea1c..f2dd99413211 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/customer/CustomerEnhancerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/customer/CustomerEnhancerTest.java @@ -263,8 +263,6 @@ private EntityEntry makeEntityEntry() { LockMode.NONE, false, null, - EntityMode.POJO, - null, false, false, null diff --git a/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/AbstractCachedItem.java b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/AbstractCachedItem.java new file mode 100644 index 000000000000..efec2b1ec85b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/AbstractCachedItem.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010-2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.polymorphism; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.GenericGenerator; + +/** + * @author Steve Ebersole + * @author Guillaume Smet + */ +@Entity +@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +public class AbstractCachedItem { + private Long id; + private String name; + + public AbstractCachedItem() { + } + + public AbstractCachedItem(String name) { + this.name = name; + } + + @Id + @GeneratedValue(generator = "increment") + @GenericGenerator(name = "increment", strategy = "increment") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/CachedItem1.java b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/CachedItem1.java new file mode 100644 index 000000000000..1be8d7a9af69 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/CachedItem1.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.polymorphism; + +import javax.persistence.Entity; + + +/** + * @author Guillaume Smet + */ +@Entity +public class CachedItem1 extends AbstractCachedItem { + + public CachedItem1() { + super(); + } + + public CachedItem1(String name) { + super( name ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/CachedItem2.java b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/CachedItem2.java new file mode 100644 index 000000000000..95b579f9e2fb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/CachedItem2.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.polymorphism; + +import javax.persistence.Entity; + + +/** + * @author Guillaume Smet + */ +@Entity +public class CachedItem2 extends AbstractCachedItem { + + public CachedItem2() { + super(); + } + + public CachedItem2(String name) { + super( name ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/PolymorphicCacheTest.java b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/PolymorphicCacheTest.java new file mode 100644 index 000000000000..63fd946bab69 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cache/polymorphism/PolymorphicCacheTest.java @@ -0,0 +1,107 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012-2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cache.polymorphism; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.hibernate.Session; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +/** + * @author Guillaume Smet + * @author Brett Meyer + */ +@TestForIssue(jiraKey = "HHH-9028") +public class PolymorphicCacheTest extends BaseCoreFunctionalTestCase { + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { AbstractCachedItem.class, CachedItem1.class, CachedItem2.class }; + } + + @Test + public void testPolymorphismAndCache() throws Exception { + final CachedItem1 item1 = new CachedItem1( "name 1" ); + final CachedItem2 item2 = new CachedItem2( "name 2" ); + + // create the 2 items + Session s = openSession(); + s.beginTransaction(); + s.save( item1 ); + s.save( item2 ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + // As the first item is supposed to be a CachedItem1, it shouldn't be returned. + // Note that the Session API is not type safe but, when using the EntityManager.find API, you get a ClassCastException + // if calling find returns the object. + Object thisObjectShouldBeNull = s.get( CachedItem2.class, item1.getId() ); + assertNull( thisObjectShouldBeNull ); + s.getTransaction().commit(); + s.close(); + + // test updating + s = openSession(); + s.beginTransaction(); + item1.setName( "updated" ); + s.update( item1 ); + s.getTransaction().commit(); + s.clear(); + s.beginTransaction(); + CachedItem1 cachedItem1 = (CachedItem1) s.get( CachedItem1.class, item1.getId() ); + CachedItem2 cachedItem2 = (CachedItem2) s.get( CachedItem2.class, item2.getId() ); + assertEquals( "updated", cachedItem1.getName() ); + assertEquals( item2.getName(), cachedItem2.getName() ); + s.getTransaction().commit(); + s.close(); + + // test deleting + s = openSession(); + s.beginTransaction(); + s.delete( item1 ); + s.getTransaction().commit(); + s.clear(); + s.beginTransaction(); + cachedItem1 = (CachedItem1) s.get( CachedItem1.class, item1.getId() ); + cachedItem2 = (CachedItem2) s.get( CachedItem2.class, item2.getId() ); + assertNull( cachedItem1 ); + assertNotNull( cachedItem2 ); + assertEquals( item2.getName(), cachedItem2.getName() ); + s.getTransaction().commit(); + s.close(); + + // cleanup + s = openSession(); + s.beginTransaction(); + s.createQuery( "DELETE FROM AbstractCachedItem" ).executeUpdate(); + s.getTransaction().commit(); + s.close(); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cascade/circle/CascadeMergeToChildBeforeParentTest.java b/hibernate-core/src/test/java/org/hibernate/test/cascade/circle/CascadeMergeToChildBeforeParentTest.java index 9d91b6507424..a6d28f03b6b9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cascade/circle/CascadeMergeToChildBeforeParentTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cascade/circle/CascadeMergeToChildBeforeParentTest.java @@ -28,6 +28,7 @@ import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** @@ -126,6 +127,7 @@ public void testMerge() { } @Test + @FailureExpectedWithNewMetamodel public void testMergeTransientChildBeforeTransientParent() { // This test fails because the merge algorithm tries to save a // transient child (transport) before cascade-merge gets its @@ -196,6 +198,7 @@ public void testMergeTransientChildBeforeTransientParent() { } @Test + @FailureExpectedWithNewMetamodel public void testMergeData3Nodes() { Session s = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/CacheableFileTest.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/CacheableFileTest.java deleted file mode 100644 index 1d4ce79f06f8..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/CacheableFileTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009-2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.test.cfg; - -import java.io.File; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; -import org.hibernate.internal.util.SerializationHelper; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Tests using of cacheable configuration files. - * - * @author Steve Ebersole - */ -public class CacheableFileTest extends BaseUnitTestCase { - public static final String MAPPING = "org/hibernate/test/cfg/Cacheable.hbm.xml"; - - private File mappingFile; - private File mappingBinFile; - - @Before - public void setUp() throws Exception { - mappingFile = new File( getClass().getClassLoader().getResource( MAPPING ).toURI() ); - assertTrue( mappingFile.exists() ); - mappingBinFile = new File( mappingFile.getParentFile(), mappingFile.getName() + ".bin" ); - if ( mappingBinFile.exists() ) { - //noinspection ResultOfMethodCallIgnored - mappingBinFile.delete(); - } - } - - @After - public void tearDown() throws Exception { - if ( mappingBinFile != null && mappingBinFile.exists() ) { - // be nice - //noinspection ResultOfMethodCallIgnored - mappingBinFile.delete(); - } - mappingBinFile = null; - mappingFile = null; - } - - @Test - public void testCachedFiles() throws Exception { - assertFalse( mappingBinFile.exists() ); - // This call should create the cached file - new Configuration().addCacheableFile( mappingFile ); - assertTrue( mappingBinFile.exists() ); - - Configuration cfg = new Configuration().addCacheableFileStrictly( mappingFile ); - SerializationHelper.clone( cfg ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/ConfigurationSerializationTest.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/ConfigurationSerializationTest.java deleted file mode 100644 index cc604bbd43d6..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/ConfigurationSerializationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009-2011, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.test.cfg; - -import javax.persistence.Entity; -import javax.persistence.Id; - -import org.junit.Test; - -import org.hibernate.SessionFactory; -import org.hibernate.cfg.Configuration; -import org.hibernate.internal.util.SerializationHelper; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -/** - * Copied over mostly from ConfigurationPerformanceTest - * - * @author Steve Ebersole - * @author Max Andersen - */ -public class ConfigurationSerializationTest extends BaseUnitTestCase { - private static final String[] FILES = new String[] { - "legacy/ABC.hbm.xml", - "legacy/ABCExtends.hbm.xml", - "legacy/Baz.hbm.xml", - "legacy/Blobber.hbm.xml", - "legacy/Broken.hbm.xml", - "legacy/Category.hbm.xml", - "legacy/Circular.hbm.xml", - "legacy/Commento.hbm.xml", - "legacy/ComponentNotNullMaster.hbm.xml", - "legacy/Componentizable.hbm.xml", - "legacy/Container.hbm.xml", - "legacy/Custom.hbm.xml", - "legacy/CustomSQL.hbm.xml", - "legacy/Eye.hbm.xml", - "legacy/Fee.hbm.xml", - "legacy/Fo.hbm.xml", - "legacy/FooBar.hbm.xml", - "legacy/Fum.hbm.xml", - "legacy/Fumm.hbm.xml", - "legacy/Glarch.hbm.xml", - "legacy/Holder.hbm.xml", - "legacy/IJ2.hbm.xml", - "legacy/Immutable.hbm.xml", - "legacy/Location.hbm.xml", - "legacy/Many.hbm.xml", - "legacy/Map.hbm.xml", - "legacy/Marelo.hbm.xml", - "legacy/MasterDetail.hbm.xml", - "legacy/Middle.hbm.xml", - "legacy/Multi.hbm.xml", - "legacy/MultiExtends.hbm.xml", - "legacy/Nameable.hbm.xml", - "legacy/One.hbm.xml", - "legacy/ParentChild.hbm.xml", - "legacy/Qux.hbm.xml", - "legacy/Simple.hbm.xml", - "legacy/SingleSeveral.hbm.xml", - "legacy/Stuff.hbm.xml", - "legacy/UpDown.hbm.xml", - "legacy/Vetoer.hbm.xml", - "legacy/WZ.hbm.xml", - "cfg/orm-serializable.xml" - }; - - @Test - public void testConfigurationSerializability() { - Configuration cfg = new Configuration(); - for ( String file : FILES ) { - cfg.addResource( "org/hibernate/test/" + file ); - } - - cfg.addAnnotatedClass( Serial.class ); - - byte[] bytes = SerializationHelper.serialize( cfg ); - cfg = ( Configuration ) SerializationHelper.deserialize( bytes ); - - SessionFactory factory = null; - ServiceRegistry serviceRegistry = null; - try { - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ); - // try to build SF - factory = cfg.buildSessionFactory( serviceRegistry ); - } - finally { - if ( factory != null ) { - factory.close(); - } - if ( serviceRegistry != null ) { - ServiceRegistryBuilder.destroy( serviceRegistry ); - } - } - } - - @Entity - public static class Serial { - private String id; - private String value; - - @Id - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/WrongCircularityDetectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/WrongCircularityDetectionTest.java index 6b66ce94f750..ab60d1c7004a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/WrongCircularityDetectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/WrongCircularityDetectionTest.java @@ -1,8 +1,5 @@ package org.hibernate.test.cfg; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.Id; @@ -10,11 +7,17 @@ import javax.persistence.InheritanceType; import javax.persistence.Table; -import org.hibernate.cfg.Configuration; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.relational.Schema; + import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + /** * This test illustrates the problem when two related (in terms of joins) * classes have the same table name in different schemas. @@ -26,19 +29,50 @@ public class WrongCircularityDetectionTest extends BaseUnitTestCase { @Test public void testNoCircularityDetection() { - Configuration cfg = new Configuration(); - cfg.addAnnotatedClass(Entity1.class); - cfg.addAnnotatedClass(Entity2.class); + MetadataSources metadataSources = new MetadataSources() + .addAnnotatedClass( Entity1.class ) + .addAnnotatedClass( Entity2.class ); + MetadataImplementor metadataImplementor = (MetadataImplementor) metadataSources.buildMetadata(); - cfg.buildMappings(); + org.hibernate.metamodel.spi.relational.Table entity1Table = null; + org.hibernate.metamodel.spi.relational.Table entity2Table = null; - org.hibernate.mapping.Table entity1Table = cfg.getClassMapping( - Entity1.class.getName()).getTable(); - org.hibernate.mapping.Table entity2Table = cfg.getClassMapping( - Entity2.class.getName()).getTable(); + int schemaNumber = 0; + boolean foundSchema1 = false; + boolean foundSchema2 = false; + + for ( Schema schema : metadataImplementor.getDatabase().getSchemas() ) { + schemaNumber = -1; + + if ( schema.getName().getSchema() == null ) { + continue; + } + + if ( "schema1".equals( schema.getName().getSchema().getText() ) ) { + foundSchema1 = true; + schemaNumber = 1; + } + else if ( "schema2".equals( schema.getName().getSchema().getText() ) ) { + foundSchema2 = true; + schemaNumber = 2; + } + + for ( org.hibernate.metamodel.spi.relational.Table table : schema.getTables() ) { + if ( "entity".equals( table.getPhysicalName().getText() ) ) { + if ( schemaNumber == 1 ) { + entity1Table = table; + } + else if ( schemaNumber == 2 ) { + entity2Table = table; + } + } + } + } - assertTrue(entity1Table.getName().equals(entity2Table.getName())); - assertFalse(entity1Table.getSchema().equals(entity2Table.getSchema())); + assertTrue( foundSchema1 ); + assertTrue( foundSchema2 ); + assertNotNull( entity1Table ); + assertNotNull( entity2Table ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java index 92860dfa201c..c95913abff24 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/cache/CacheConfigurationTest.java @@ -24,6 +24,8 @@ package org.hibernate.test.cfg.cache; import org.hibernate.cfg.Configuration; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; @@ -36,6 +38,9 @@ public class CacheConfigurationTest extends BaseUnitTestCase { public static final String CFG_XML = "org/hibernate/test/cfg/cache/hibernate.cfg.xml"; @Test + @FailureExpectedWithNewMetamodel( + message = "problem handling 'spread' hbm inheritance with explicit extends XML attribute" + ) public void testCacheConfiguration() throws Exception { // we only care if the SF builds successfully. Configuration cfg = new Configuration().configure(CFG_XML); diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java index f1ded8bd34e3..9fcaac878716 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java @@ -51,8 +51,10 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.spi.PersisterClassResolver; @@ -92,6 +94,14 @@ public Class getCollectionPersisterClass(PluralAt } public static class NoopEntityPersister implements EntityPersister { + public NoopEntityPersister( + EntityBinding entityBinding, + EntityRegionAccessStrategy entityRegionAccessStrategy, + NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, + SessionFactoryImplementor sf, + Mapping mapping) { + throw new GoofyException(NoopEntityPersister.class); + } public NoopEntityPersister(org.hibernate.mapping.PersistentClass persistentClass, org.hibernate.cache.spi.access.EntityRegionAccessStrategy strategy, @@ -617,6 +627,13 @@ public boolean canUseReferenceCacheEntries() { } public static class NoopCollectionPersister implements CollectionPersister { + public NoopCollectionPersister( + AbstractPluralAttributeBinding collectionBinding, + CollectionRegionAccessStrategy regionAccessStrategy, + MetadataImplementor metadata, + SessionFactoryImplementor sf) { + throw new GoofyException(NoopCollectionPersister.class); + } public NoopCollectionPersister(org.hibernate.mapping.Collection collection, org.hibernate.cache.spi.access.CollectionRegionAccessStrategy strategy, diff --git a/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdTest.java index e8bf9754637c..2c5b10c417be 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdTest.java @@ -23,24 +23,25 @@ */ package org.hibernate.test.cid; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.math.BigDecimal; import java.util.Calendar; import java.util.Collections; import java.util.Iterator; import java.util.List; -import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.engine.query.spi.HQLQueryPlan; +import org.hibernate.exception.SQLGrammarException; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Gavin King @@ -93,6 +94,45 @@ public void testDistinctCountOfEntityWithCompositeId() { final String countExpressionFragment = generatedSql.substring( countExpressionListStart+6, countExpressionListEnd+1 ); assertTrue( countExpressionFragment.startsWith( "distinct" ) ); assertTrue( countExpressionFragment.contains( "," ) ); + + Session s = openSession(); + s.beginTransaction(); + Customer c = new Customer(); + c.setCustomerId( "1" ); + c.setAddress("123 somewhere"); + c.setName("Brett"); + Order o1 = new Order( c ); + o1.setOrderDate( Calendar.getInstance() ); + Order o2 = new Order( c ); + o2.setOrderDate( Calendar.getInstance() ); + s.persist( c ); + s.persist( o1 ); + s.persist( o2 ); + s.getTransaction().commit(); + s.clear(); + + s.beginTransaction(); + try { + long count = ( Long ) s.createQuery( "select count(distinct o) FROM Order o" ).uniqueResult(); + if ( ! getDialect().supportsTupleDistinctCounts() ) { + fail( "expected SQLGrammarException" ); + } + assertEquals( 2l, count ); + } + catch ( SQLGrammarException e ) { + if ( getDialect().supportsTupleDistinctCounts() ) { + throw e; + } + } + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + s.createQuery("delete from Order").executeUpdate(); + s.createQuery("delete from Customer").executeUpdate(); + s.getTransaction().commit(); + s.close(); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java index c681eafd42a8..b8cee297b987 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cid/CompositeIdWithGeneratorTest.java @@ -31,6 +31,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -51,6 +52,7 @@ * @author Jacob Robertson */ @TestForIssue( jiraKey = "HHH-2060" ) +@FailureExpectedWithNewMetamodel public class CompositeIdWithGeneratorTest extends BaseCoreFunctionalTestCase { private DateFormat df = SimpleDateFormat.getDateTimeInstance( DateFormat.LONG, DateFormat.LONG ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java index 51a0d326ade7..ad3c63e07f4d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeAnnotationsVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.basic; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class UserCollectionTypeAnnotationsVariantTest extends UserCollectionTypeTest { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java index 4b9b51d69834..f03a7b47014c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/basic/UserCollectionTypeHbmVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.basic; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class UserCollectionTypeHbmVariantTest extends UserCollectionTypeTest { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java index 5130064a7a69..9ac6b109acb6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeAnnotationsVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.parameterized; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class ParameterizedUserCollectionTypeAnnotationsVariantTest extends ParameterizedUserCollectionTypeTest { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java index fb3650c5fdfe..9bb1bd09749c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/custom/parameterized/ParameterizedUserCollectionTypeHbmVariantTest.java @@ -23,9 +23,12 @@ */ package org.hibernate.test.collection.custom.parameterized; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class ParameterizedUserCollectionTypeHbmVariantTest extends ParameterizedUserCollectionTypeTest { public String[] getMappings() { return new String[] { "collection/custom/parameterized/Mapping.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java index 7a35590a8dd9..f62635218e1b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/idbag/PersistentIdBagTest.java @@ -28,6 +28,7 @@ import org.hibernate.Session; import org.hibernate.collection.internal.PersistentIdentifierBag; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertFalse; @@ -38,6 +39,7 @@ * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel( message = " not supported" ) public class PersistentIdBagTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java index 4334c51eebfd..3175447d6c59 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/lazynocascade/LazyAssociationNoCascadeTest.java @@ -23,13 +23,14 @@ */ package org.hibernate.test.collection.lazynocascade; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - import org.hibernate.Session; + import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + /** * @author Vasily Kochnev */ diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java index 28665abbbb21..b2228d1a6324 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java @@ -22,6 +22,7 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.collection.map; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java index 5dfa28a905c4..4a2886fb725c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/map/hhh7557/EntityMapTest.java @@ -31,12 +31,14 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Elizabeth Chatman * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel // missing unique-constraint default naming public class EntityMapTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java index 8a754e5f9974..bf342eff4bc7 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/original/CollectionTest.java @@ -22,22 +22,22 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.collection.original; -import java.sql.SQLException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import org.junit.Test; +import java.sql.SQLException; import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Gavin King @@ -49,6 +49,7 @@ public String[] getMappings() { } @Test + @FailureExpectedWithNewMetamodel public void testExtraLazy() throws HibernateException, SQLException { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java b/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java index 22c7e77ea0b9..fb0af6d3dfc5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java +++ b/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java @@ -30,14 +30,23 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreator; +import org.hibernate.engine.jdbc.env.internal.ExtractedDatabaseMetaDataImpl; +import org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder; +import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport; +import org.hibernate.engine.jdbc.env.spi.SQLStateType; import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl; import org.hibernate.engine.jdbc.spi.TypeInfo; -import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.ResultSetWrapper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.Stoppable; import org.hibernate.testing.env.ConnectionProviderBuilder; @@ -49,11 +58,10 @@ * @author Steve Ebersole */ public class BasicTestingJdbcServiceImpl implements JdbcServices { - private ConnectionProvider connectionProvider; - private Dialect dialect; - private SqlStatementLogger sqlStatementLogger; - private SqlExceptionHelper exceptionHelper; - private final ExtractedDatabaseMetaData metaDataSupport = new MetaDataSupportImpl(); + + private TestingJdbcEnvironmentImpl jdbcEnvironment; + + private SqlStatementLogger sqlStatementLogger = new SqlStatementLogger( true, false );; private final ResultSetWrapper resultSetWrapper = ResultSetWrapperImpl.INSTANCE; public void start() { @@ -64,33 +72,34 @@ public void stop() { } public void prepare(boolean allowAggressiveRelease) { - connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease ); - dialect = ConnectionProviderBuilder.getCorrespondingDialect(); - sqlStatementLogger = new SqlStatementLogger( true, false ); - exceptionHelper = new SqlExceptionHelper(); + jdbcEnvironment = new TestingJdbcEnvironmentImpl( allowAggressiveRelease ); } public void release() { - if ( connectionProvider instanceof Stoppable ) { - ( (Stoppable) connectionProvider ).stop(); + if ( jdbcEnvironment.connectionProvider instanceof Stoppable ) { + ( (Stoppable) jdbcEnvironment.connectionProvider ).stop(); } } public ConnectionProvider getConnectionProvider() { - return connectionProvider; + return jdbcEnvironment.connectionProvider; } public Dialect getDialect() { - return dialect; + return jdbcEnvironment.dialect; } public LobCreator getLobCreator(LobCreationContext lobCreationContext) { - return null; - } + return jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext ); } public ResultSetWrapper getResultSetWrapper() { - return null; + return resultSetWrapper; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return jdbcEnvironment; } public SqlStatementLogger getSqlStatementLogger() { @@ -98,65 +107,78 @@ public SqlStatementLogger getSqlStatementLogger() { } public SqlExceptionHelper getSqlExceptionHelper() { - return exceptionHelper; + return jdbcEnvironment.exceptionHelper; } public ExtractedDatabaseMetaData getExtractedMetaDataSupport() { - return metaDataSupport; + return jdbcEnvironment.extractedDatabaseMetaData; } - private static class MetaDataSupportImpl implements ExtractedDatabaseMetaData { - @Override - public boolean supportsRefCursors() { - return false; + private static class TestingJdbcEnvironmentImpl implements JdbcEnvironment { + private final ExtractedDatabaseMetaData extractedDatabaseMetaData = new ExtractedDatabaseMetaDataImpl( this ); + private final SqlExceptionHelper exceptionHelper = new SqlExceptionHelper(); + private final LobCreatorBuilder lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(); + + private ConnectionProvider connectionProvider; + private Dialect dialect; + + private TestingJdbcEnvironmentImpl(boolean allowAggressiveRelease) { + connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease ); + dialect = ConnectionProviderBuilder.getCorrespondingDialect(); } @Override - public boolean supportsNamedParameters() { - return false; + public Dialect getDialect() { + return dialect; } - public boolean supportsScrollableResults() { - return false; + @Override + public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() { + return extractedDatabaseMetaData; } - public boolean supportsGetGeneratedKeys() { - return false; + @Override + public Identifier getCurrentCatalog() { + return null; } - public boolean supportsBatchUpdates() { - return false; + @Override + public Identifier getCurrentSchema() { + return null; } - public boolean supportsDataDefinitionInTransaction() { - return false; + @Override + public QualifiedObjectNameSupport getQualifiedObjectNameSupport() { + return null; } - public boolean doesDataDefinitionCauseTransactionCommit() { - return false; + @Override + public IdentifierHelper getIdentifierHelper() { + return null; } - public Set getExtraKeywords() { + @Override + public Set getReservedWords() { return Collections.emptySet(); } - public SQLStateType getSqlStateType() { - return SQLStateType.UNKOWN; - } - - public boolean doesLobLocatorUpdateCopy() { - return false; + @Override + public SqlExceptionHelper getSqlExceptionHelper() { + return exceptionHelper; } - public String getConnectionSchemaName() { - return null; + @Override + public LobCreatorBuilder getLobCreatorBuilder() { + return lobCreatorBuilder; } - public String getConnectionCatalogName() { + @Override + public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) { return null; } - public LinkedHashSet getTypeInfoSet() { + @Override + public ServiceRegistry getServiceRegistry() { return null; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java b/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java index fdf1ee9281e8..220d85ce5c31 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java @@ -38,6 +38,7 @@ public class ComponentJoinsTest extends BaseCoreFunctionalTestCase { @Override public Class[] getAnnotatedClasses() { return new Class[] { + Name.class, Person.class, Component.class, Component.Emb.Stuff.class }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java b/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java index 18bedf59e7aa..11146fea9dd8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/connections/AggressiveReleaseTest.java @@ -20,6 +20,8 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; import org.hibernate.internal.util.SerializationHelper; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.jta.TestingJtaBootstrap; import org.hibernate.testing.jta.TestingJtaPlatformImpl; @@ -217,6 +219,8 @@ public void testSuppliedConnection() throws Throwable { @Test public void testConnectionMaintanenceDuringFlush() throws Throwable { + // todo : no idea why this fails with metamodel + prepare(); Session s = getSessionUnderTest(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java index b329a6a0e355..201d328a4bc4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/connections/SuppliedConnectionTest.java @@ -35,11 +35,12 @@ import org.hibernate.engine.jdbc.connections.internal.UserSuppliedConnectionProviderImpl; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.spi.Stoppable; +import org.hibernate.tool.hbm2ddl.SchemaExport; + import org.hibernate.testing.AfterClassOnce; import org.hibernate.testing.BeforeClassOnce; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.env.ConnectionProviderBuilder; -import org.hibernate.tool.hbm2ddl.SchemaExport; /** * Implementation of SuppliedConnectionTest. @@ -125,7 +126,7 @@ protected void prepareTest() throws Exception { super.prepareTest(); Connection conn = cp.getConnection(); try { - new SchemaExport( configuration(), conn ).create( false, true ); + new SchemaExport( metadata(), conn ).create( false, true ); } finally { if ( conn != null ) { @@ -142,7 +143,7 @@ protected void prepareTest() throws Exception { protected void cleanupTest() throws Exception { Connection conn = cp.getConnection(); try { - new SchemaExport( configuration(), conn ).drop( false, true ); + new SchemaExport( metadata(), conn ).drop( false, true ); } finally { if ( conn != null ) { @@ -155,4 +156,5 @@ protected void cleanupTest() throws Exception { } super.cleanupTest(); } + } diff --git a/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java b/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java index e92d72826b8c..e750a8f99352 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/constraint/ConstraintTest.java @@ -1,6 +1,6 @@ -/* +/* * Hibernate, Relational Persistence for Idiomatic Java - * + * * JBoss, Home of Professional Open Source * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. @@ -21,145 +21,189 @@ package org.hibernate.test.constraint; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.util.Iterator; +import java.util.Set; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.ForeignKey; -import org.hibernate.mapping.UniqueKey; -import org.hibernate.testing.TestForIssue; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; +import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.tool.hbm2ddl.SchemaExport; import org.junit.Test; /** * @author Brett Meyer */ public class ConstraintTest extends BaseCoreFunctionalTestCase { - + private static final int MAX_NAME_LENGTH = 30; - - private static final String EXPLICIT_FK_NAME_NATIVE = "fk_explicit_native"; - - private static final String EXPLICIT_FK_NAME_JPA = "fk_explicit_jpa"; - - private static final String EXPLICIT_UK_NAME = "uk_explicit"; - + + private static final String EXPLICIT_UK_NAME = "EXPLICIT_UK_NAME"; + + private static final String EXPLICIT_COLUMN_NAME_O2O = "EXPLICIT_COLUMN_NAME_O2O"; + private static final String EXPLICIT_FK_NAME_O2O = "EXPLICIT_FK_NAME_O2O"; + private static final String EXPLICIT_COLUMN_NAME_M2O = "EXPLICIT_COLUMN_NAME_M2O"; + private static final String EXPLICIT_FK_NAME_M2O = "EXPLICIT_FK_NAME_M2O"; + private static final String EXPLICIT_JOINTABLE_NAME_M2M = "EXPLICIT_JOINTABLE_NAME_M2M"; + private static final String EXPLICIT_COLUMN_NAME_M2M = "EXPLICIT_COLUMN_NAME_M2M"; + private static final String EXPLICIT_FK_NAME_M2M = "EXPLICIT_FK_NAME_M2M"; + private static final String EXPLICIT_COLLECTIONTABLE_NAME_ELEMENT = "EXPLICIT_COLLECTIONTABLE_NAME_ELEMENT"; + private static final String EXPLICIT_COLUMN_NAME_ELEMENT = "EXPLICIT_COLUMN_NAME_ELEMENT"; + private static final String EXPLICIT_FK_NAME_ELEMENT = "EXPLICIT_FK_NAME_ELEMENT"; + private static final String INDEX_1 = "INDEX_1"; + private static final String INDEX_2 = "INDEX_2"; + private static final String INDEX_3 = "INDEX_3"; + private static final String INDEX_4 = "INDEX_4"; + private static final String INDEX_5 = "INDEX_5"; + private static final String INDEX_6 = "INDEX_6"; + @Override protected Class[] getAnnotatedClasses() { return new Class[] { DataPoint.class, DataPoint2.class }; } - + @Test - @TestForIssue( jiraKey = "HHH-7797" ) - public void testUniqueConstraints() { - Column column = (Column) configuration().getClassMapping( DataPoint.class.getName() ) - .getProperty( "foo1" ).getColumnIterator().next(); - assertFalse( column.isNullable() ); - assertTrue( column.isUnique() ); - - column = (Column) configuration().getClassMapping( DataPoint.class.getName() ) - .getProperty( "foo2" ).getColumnIterator().next(); - assertTrue( column.isNullable() ); - assertTrue( column.isUnique() ); - - column = (Column) configuration().getClassMapping( DataPoint.class.getName() ) - .getProperty( "id" ).getColumnIterator().next(); - assertFalse( column.isNullable() ); - assertTrue( column.isUnique() ); + public void testConstraints() { + String[] sqlActions = new SchemaExport( metadata() ).getCreateSQL(); + // TODO: This should cover most dialects, but may need better tied to them otherwise. + + assertEquals( 1, findActions( ".*constraint.*" + INDEX_1 + ".*unique.*foo2.*", sqlActions ) ); + + int count = 0; + // Yep, this is stupid. But, need to ensure that the UC is created only once. A 1 shot regex would be hell. + count += findActions( ".*constraint.*" + INDEX_2 + ".*unique.*foo3.*foo4.*", sqlActions ); + count += findActions( ".*constraint.*" + INDEX_2 + ".*unique.*foo4.*foo3.*", sqlActions ); + count += findActions( ".*constraint.*" + INDEX_3 + ".*unique.*foo3.*foo4.*", sqlActions ); + count += findActions( ".*constraint.*" + INDEX_3 + ".*unique.*foo4.*foo3.*", sqlActions ); + assertEquals( 1, count ); + + // Ensure no UCs were created for these. + assertEquals( 0, findActions( ".*constraint.*unique.*foo5.*", sqlActions ) ); + assertEquals( 0, findActions( ".*constraint.*unique.*foo6.*", sqlActions ) ); + + // Check indexes + assertEquals( 1, findActions( ".*index.*" + INDEX_4 + ".*foo5.*foo6.*", sqlActions ) ); + assertEquals( 1, findActions( ".*index.*" + INDEX_5 + ".*foo6.*foo5.*", sqlActions ) ); + assertEquals( 1, findActions( ".*index.*" + INDEX_6 + ".*foo5.*", sqlActions ) ); } - @Test - @TestForIssue( jiraKey = "HHH-1904" ) - public void testConstraintNameLength() { - Iterator tableItr = configuration().getTableMappings(); - int foundCount = 0; - while (tableItr.hasNext()) { - org.hibernate.mapping.Table table = tableItr.next(); - - Iterator fkItr = table.getForeignKeyIterator(); - while (fkItr.hasNext()) { - ForeignKey fk = (ForeignKey) fkItr.next(); - assertTrue( fk.getName().length() <= MAX_NAME_LENGTH ); - - // ensure the randomly generated constraint name doesn't - // happen if explicitly given - Column column = fk.getColumn( 0 ); - if ( column.getName().equals( "explicit_native" ) ) { - foundCount++; - assertEquals( fk.getName(), EXPLICIT_FK_NAME_NATIVE ); - } - else if ( column.getName().equals( "explicit_jpa" ) ) { - foundCount++; - assertEquals( fk.getName(), EXPLICIT_FK_NAME_JPA ); - } - } - - Iterator ukItr = table.getUniqueKeyIterator(); - while (ukItr.hasNext()) { - UniqueKey uk = (UniqueKey) ukItr.next(); - assertTrue( uk.getName().length() <= MAX_NAME_LENGTH ); - - // ensure the randomly generated constraint name doesn't - // happen if explicitly given - Column column = uk.getColumn( 0 ); - if ( column.getName().equals( "explicit" ) ) { - foundCount++; - assertEquals( uk.getName(), EXPLICIT_UK_NAME ); - } - } + private int findActions(String regex, String[] sqlActions) { + int count = 0; + for (String sqlAction : sqlActions) { + count += sqlAction.matches( regex ) ? 1 : 0; } + return count; + } + + @Test + public void testConstraintNames() { + TableSpecification table1 = SchemaUtil.getTable( DataPoint.class, metadata() ); + assertTrue( SchemaUtil.hasUniqueKey( table1, EXPLICIT_UK_NAME, "explicit" ) ); + + TableSpecification table2 = SchemaUtil.getTable( DataPoint2.class, metadata() ); + TableSpecification joinTable = SchemaUtil.getTable( EXPLICIT_JOINTABLE_NAME_M2M, metadata() ); + TableSpecification collectionTable = SchemaUtil.getTable( EXPLICIT_COLLECTIONTABLE_NAME_ELEMENT, metadata() ); + assertTrue( SchemaUtil.hasForeignKey( table2, EXPLICIT_FK_NAME_O2O, EXPLICIT_COLUMN_NAME_O2O ) ); + assertTrue( SchemaUtil.hasForeignKey( table2, EXPLICIT_FK_NAME_M2O, EXPLICIT_COLUMN_NAME_M2O ) ); + assertTrue( SchemaUtil.hasForeignKey( joinTable, EXPLICIT_FK_NAME_M2M, EXPLICIT_COLUMN_NAME_M2M ) ); + assertTrue( SchemaUtil.hasForeignKey( collectionTable, EXPLICIT_FK_NAME_ELEMENT, EXPLICIT_COLUMN_NAME_ELEMENT ) ); - assertEquals("Could not find the necessary columns.", 3, foundCount); + testConstraintLength( table1 ); + testConstraintLength( table2 ); } + private void testConstraintLength(TableSpecification table) { + for (UniqueKey uk : table.getUniqueKeys()) { + assertTrue(uk.getName().toString().length() <= MAX_NAME_LENGTH); + } + for (ForeignKey fk : table.getForeignKeys()) { + assertTrue(fk.getName().toString().length() <= MAX_NAME_LENGTH); + } + } + @Entity - @Table( name = "DataPoint", uniqueConstraints = { - @UniqueConstraint( name = EXPLICIT_UK_NAME, columnNames = { "explicit" } ) - } ) - public static class DataPoint { + @Table( name = "DataPoint", + uniqueConstraints = { @UniqueConstraint( name = EXPLICIT_UK_NAME, columnNames = { "explicit" } ) }, + indexes = { + @Index(columnList = "foo2", unique = true, name = INDEX_1), + @Index(columnList = "foo3,foo4", unique = true, name = INDEX_2), + @Index(columnList = "foo4,foo3", unique = true, name = INDEX_3), + @Index(columnList = "foo5,foo6", name = INDEX_4), + @Index(columnList = "foo6,foo5", name = INDEX_5), + @Index(columnList = "foo5", name = INDEX_6) } ) + private static class DataPoint { @Id @GeneratedValue - @javax.persistence.Column( nullable = false, unique = true) public long id; - - @javax.persistence.Column( nullable = false, unique = true) + + public String explicit; + + @javax.persistence.Column(unique = true) public String foo1; - @javax.persistence.Column( nullable = true, unique = true) public String foo2; - public String explicit; + public String foo3; + + public String foo4; + + public String foo5; + + public String foo6; } - + @Entity @Table( name = "DataPoint2" ) - public static class DataPoint2 { + private static class DataPoint2 { @Id @GeneratedValue public long id; - + @OneToOne public DataPoint dp; - - @OneToOne - @org.hibernate.annotations.ForeignKey(name = EXPLICIT_FK_NAME_NATIVE) - @JoinColumn(name = "explicit_native") - public DataPoint explicit_native; - + @OneToOne - @JoinColumn(name = "explicit_jpa", foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_JPA)) - public DataPoint explicit_jpa; + @JoinColumn(name = EXPLICIT_COLUMN_NAME_O2O, + foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_O2O)) + public DataPoint explicit_o2o; + + @ManyToOne + @JoinColumn(name = EXPLICIT_COLUMN_NAME_M2O, + foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_M2O)) + public DataPoint explicit_m2o; + + @ManyToMany + @JoinTable(name = EXPLICIT_JOINTABLE_NAME_M2M, + joinColumns = @JoinColumn(name = EXPLICIT_COLUMN_NAME_M2M), + foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_M2M)) + public Set explicit_m2m; + + @ElementCollection + @CollectionTable(name = EXPLICIT_COLLECTIONTABLE_NAME_ELEMENT, + joinColumns = @JoinColumn(name = EXPLICIT_COLUMN_NAME_ELEMENT), + foreignKey = @javax.persistence.ForeignKey(name = EXPLICIT_FK_NAME_ELEMENT)) + public Set explicit_element; + } + + public static enum SimpleEnum { + FOO1, FOO2, FOO3; } -} +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/criteria/LikeTest.java b/hibernate-core/src/test/java/org/hibernate/test/criteria/LikeTest.java index d962dcb53443..dce55f9545cf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/criteria/LikeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/criteria/LikeTest.java @@ -22,19 +22,17 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.criteria; -import java.util.List; +import static org.junit.Assert.assertEquals; -import org.junit.Test; +import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; public class LikeTest extends BaseCoreFunctionalTestCase { @@ -68,7 +66,7 @@ public void testLike(){ assertEquals( 1, objects.size() ); session.clear(); - if ( !( getDialect() instanceof MySQLDialect ) && ! ( getDialect() instanceof PostgreSQLDialect ) && ! ( getDialect() instanceof PostgreSQL81Dialect )) { + if ( !( getDialect() instanceof MySQLDialect ) && ! ( getDialect() instanceof PostgreSQL81Dialect )) { // retrieve object - case insensitive via custom expression - works // ok objects = session.createCriteria( TestObject.class ).add( diff --git a/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java index 0bf8f0d0f09c..c2c803d94693 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cuk/CompositePropertyRefTest.java @@ -32,6 +32,7 @@ import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -44,6 +45,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class CompositePropertyRefTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "cuk/Person.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/dirtiness/CustomDirtinessStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/dirtiness/CustomDirtinessStrategyTest.java index bfc0cbea8498..7eed71fcbff1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dirtiness/CustomDirtinessStrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dirtiness/CustomDirtinessStrategyTest.java @@ -30,6 +30,8 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.persister.entity.EntityPersister; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -56,6 +58,8 @@ protected Class[] getAnnotatedClasses() { @Test public void testOnlyCustomStrategy() { + // todo : not sure why this only fails with metamodel + Session session = openSession(); session.beginTransaction(); Long id = (Long) session.save( new Thing( INITIAL_NAME ) ); @@ -87,6 +91,8 @@ public void testOnlyCustomStrategy() { @Test public void testOnlyCustomStrategyConsultedOnNonDirty() throws Exception { + // todo : not sure why this only fails with metamodel + Session session = openSession(); session.beginTransaction(); Long id = (Long) session.save( new Thing( INITIAL_NAME ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java index f39f1362e1f7..4689a62c05dd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/discriminator/SimpleInheritanceTest.java @@ -33,6 +33,8 @@ import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Property; import org.hibernate.criterion.Restrictions; +import org.hibernate.mapping.MetadataSource; +import org.hibernate.metamodel.MetadataSources; import org.hibernate.proxy.HibernateProxy; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -47,11 +49,6 @@ * @author Gavin King */ public class SimpleInheritanceTest extends BaseCoreFunctionalTestCase { - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true"); - } - @Override public String[] getMappings() { return new String[] { "discriminator/SimpleInheritance.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java index 5519b773e526..9d3c3bc9dc0e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java @@ -1,8 +1,10 @@ package org.hibernate.test.dynamicentity.tuplizer; -import org.hibernate.mapping.PersistentClass; + +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.PojoEntityTuplizer; @@ -11,20 +13,18 @@ * @author Steve Ebersole */ public class MyEntityTuplizer extends PojoEntityTuplizer { - - public MyEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super( entityMetamodel, mappedEntity ); + public MyEntityTuplizer(ServiceRegistry serviceRegistry, EntityMetamodel entityMetamodel, EntityBinding entityBinding) { + super( serviceRegistry, entityMetamodel, entityBinding); } - protected Instantiator buildInstantiator(PersistentClass persistentClass) { - return new MyEntityInstantiator( persistentClass.getEntityName() ); + @Override + protected Instantiator buildInstantiator(EntityBinding entityBinding) { + return new MyEntityInstantiator( entityBinding.getEntityName() ); } - protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { - // allows defining a custom proxy factory, which is responsible for - // generating lazy proxies for a given entity. - // - // Here we simply use the default... - return super.buildProxyFactory( persistentClass, idGetter, idSetter ); + @Override + protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { + return super.buildProxyFactory( entityBinding, idGetter, idSetter ); } + } diff --git a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java index cb993c2e3753..95337141f1f2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java @@ -36,6 +36,7 @@ import org.hibernate.test.dynamicentity.Customer; import org.hibernate.test.dynamicentity.Person; import org.hibernate.test.dynamicentity.ProxyHelper; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -65,6 +66,7 @@ public void configure(Configuration cfg) { @Test @SuppressWarnings( {"unchecked"}) + @FailureExpectedWithNewMetamodel public void testIt() { // Test saving these dyna-proxies Session session = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java index 80b971ab1911..5f696783a6f8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java @@ -23,37 +23,34 @@ * */ package org.hibernate.test.dynamicentity.tuplizer2; + import org.hibernate.EntityNameResolver; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.proxy.ProxyFactory; -import org.hibernate.test.dynamicentity.ProxyHelper; -import org.hibernate.test.dynamicentity.tuplizer.MyEntityInstantiator; +import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.PojoEntityTuplizer; +import org.hibernate.test.dynamicentity.ProxyHelper; +import org.hibernate.test.dynamicentity.tuplizer.MyEntityInstantiator; + /** * @author Steve Ebersole */ public class MyEntityTuplizer extends PojoEntityTuplizer { - - public MyEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super( entityMetamodel, mappedEntity ); - } - - public MyEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { - super( entityMetamodel, mappedEntity ); + public MyEntityTuplizer(ServiceRegistry serviceRegistry, EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { + super( serviceRegistry, entityMetamodel, mappedEntity ); } public EntityNameResolver[] getEntityNameResolvers() { return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE }; } - protected Instantiator buildInstantiator(PersistentClass persistentClass) { + protected Instantiator buildInstantiator(EntityBinding persistentClass) { return new MyEntityInstantiator( persistentClass.getEntityName() ); } @@ -65,12 +62,12 @@ public String determineConcreteSubclassEntityName(Object entityInstance, Session return entityName; } - protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { + protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { // allows defining a custom proxy factory, which is responsible for // generating lazy proxies for a given entity. // // Here we simply use the default... - return super.buildProxyFactory( persistentClass, idGetter, idSetter ); + return super.buildProxyFactory( entityBinding, idGetter, idSetter ); } public static class MyEntityNameResolver implements EntityNameResolver { diff --git a/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java index 4345555f3a01..ee5a30be2992 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/entitymode/map/subclass/SubclassDynamicMapTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/enums/InvalidEnumeratedJavaTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/enums/InvalidEnumeratedJavaTypeTest.java index a26dd02205cd..b168a40d0169 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/enums/InvalidEnumeratedJavaTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/enums/InvalidEnumeratedJavaTypeTest.java @@ -27,12 +27,11 @@ import javax.persistence.Enumerated; import javax.persistence.Id; -import org.hibernate.AnnotationException; -import org.hibernate.cfg.Configuration; - -import org.junit.Test; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.fail; @@ -41,16 +40,11 @@ */ public class InvalidEnumeratedJavaTypeTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel public void testInvalidMapping() { - final Configuration cfg = new Configuration(); - try { - cfg.addAnnotatedClass( TheEntity.class ); - cfg.buildMappings(); - fail( "Was expecting failure" ); - } - catch (AnnotationException expected) { - System.out.println( expected ); - } + // again, metamodel does not appear to have a lot of checking for annotations in incorrect place. + new MetadataSources().addAnnotatedClass( TheEntity.class ).buildMetadata(); + fail( "Was expecting failure" ); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java index 1f2b2cd7e0ea..81d7acab3bb7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/AggregatedCollectionEventListener.java @@ -51,7 +51,7 @@ import org.hibernate.event.spi.PreCollectionUpdateEvent; import org.hibernate.event.spi.PreCollectionUpdateEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java index a7e82862fd47..d70a4a5ec21d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java @@ -25,6 +25,7 @@ import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -43,8 +44,8 @@ public class MultipleCollectionRefEntity1 implements org.hibernate.test.event.co private String text; @ManyToOne - @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false) - @org.hibernate.annotations.ForeignKey(name = "FK_RE1_MCE") + @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false, + foreignKey = @ForeignKey(name = "FK_RE1_MCE")) private MultipleCollectionEntity multipleCollectionEntity; @Column(name = "MCE_ID", insertable = false, updatable = false) diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java index eafb2ab82f1e..d9f77d30afab 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java @@ -25,6 +25,7 @@ import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -43,8 +44,8 @@ public class MultipleCollectionRefEntity2 implements org.hibernate.test.event.co private String text; @ManyToOne - @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false) - @org.hibernate.annotations.ForeignKey(name = "FK_RE2_MCE") + @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false, + foreignKey = @ForeignKey(name = "FK_RE2_MCE")) private MultipleCollectionEntity multipleCollectionEntity; @Column(name = "MCE_ID", insertable = false, updatable = false) diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java index acf281804bc4..0d13e5d33c7d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java @@ -38,8 +38,9 @@ import org.hibernate.event.spi.DeleteEventListener; import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -100,6 +101,7 @@ public void disintegrate( } @Test + @FailureExpectedWithNewMetamodel public void testCallbacks() { assertEquals( "observer not notified of creation", 1, observer.creationCount ); assertEquals( "listener not notified of creation", 1, listener.initCount ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java index a843d481b011..65eaf40b0a35 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/events/ClearEventListenerTest.java @@ -34,7 +34,7 @@ import org.hibernate.event.spi.ClearEventListener; import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.junit.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/LegacyPostCommitListenerTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/LegacyPostCommitListenerTest.java new file mode 100644 index 000000000000..c140d1e27db9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/events/LegacyPostCommitListenerTest.java @@ -0,0 +1,265 @@ +package org.hibernate.test.events; + +import org.hibernate.IrrelevantEntity; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.*; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test to ensure that the existing post commit behavior when using plain PostXEventListeners fire on both success and failure. + * + * @author ShawnClowater + */ +public class LegacyPostCommitListenerTest extends BaseCoreFunctionalTestCase { + private PostInsertEventListener postCommitInsertEventListener = new LegacyPostCommitInsertEventListener(); + private PostDeleteEventListener postCommitDeleteEventListener = new LegacyPostCommitDeleteEventListener(); + private PostUpdateEventListener postCommitUpdateEventListener = new LegacyPostCommitUpdateEventListener(); + + @Override + protected void prepareTest() throws Exception { + ((LegacyPostCommitInsertEventListener) postCommitInsertEventListener).fired = 0; + ((LegacyPostCommitDeleteEventListener) postCommitDeleteEventListener).fired = 0; + ((LegacyPostCommitUpdateEventListener) postCommitUpdateEventListener).fired = 0; + } + + @Override + protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) { + super.prepareBootstrapRegistryBuilder( builder ); + builder.with( + new Integrator() { + + @Override + public void integrate( + Configuration configuration, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + @Override + public void integrate( + MetadataImplementor metadata, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + private void integrate(SessionFactoryServiceRegistry serviceRegistry) { + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_DELETE + ).appendListener( postCommitDeleteEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_UPDATE + ).appendListener( postCommitUpdateEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_INSERT + ).appendListener( postCommitInsertEventListener ); + } + + @Override + public void disintegrate( + SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + } + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + Assert.assertEquals( 1, ((LegacyPostCommitInsertEventListener) postCommitInsertEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.rollback(); + session.close(); + + //the legacy implementation fires the listener on failure as well + Assert.assertEquals( 1, ((LegacyPostCommitInsertEventListener) postCommitInsertEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((LegacyPostCommitUpdateEventListener) postCommitUpdateEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + //the legacy implementation fires the listener on failure as well + Assert.assertEquals( 1, ((LegacyPostCommitUpdateEventListener) postCommitUpdateEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((LegacyPostCommitDeleteEventListener) postCommitDeleteEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + //the legacy implementation fires the listener on failure as well + Assert.assertEquals( 1, ((LegacyPostCommitDeleteEventListener) postCommitDeleteEventListener).fired ); + } + + private class LegacyPostCommitDeleteEventListener implements PostDeleteEventListener { + int fired; + + @Override + public void onPostDelete(PostDeleteEvent event) { + fired++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class LegacyPostCommitUpdateEventListener implements PostUpdateEventListener { + int fired; + + @Override + public void onPostUpdate(PostUpdateEvent event) { + fired++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class LegacyPostCommitInsertEventListener implements PostInsertEventListener { + int fired; + + @Override + public void onPostInsert(PostInsertEvent event) { + fired++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {IrrelevantEntity.class}; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/PostCommitListenerTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/PostCommitListenerTest.java new file mode 100644 index 000000000000..76da06f79ab1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/events/PostCommitListenerTest.java @@ -0,0 +1,298 @@ +package org.hibernate.test.events; + +import org.hibernate.IrrelevantEntity; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitDeleteEventListener; +import org.hibernate.event.spi.PostCommitInsertEventListener; +import org.hibernate.event.spi.PostCommitUpdateEventListener; +import org.hibernate.event.spi.PostDeleteEvent; +import org.hibernate.event.spi.PostDeleteEventListener; +import org.hibernate.event.spi.PostInsertEvent; +import org.hibernate.event.spi.PostInsertEventListener; +import org.hibernate.event.spi.PostUpdateEvent; +import org.hibernate.event.spi.PostUpdateEventListener; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +import org.junit.Assert; +import org.junit.Test; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +/** + * Test to ensure that the existing post commit behavior when using plain PostXEventListeners fire on both success and failure. + * + * @author ShawnClowater + */ +public class PostCommitListenerTest extends BaseCoreFunctionalTestCase { + private PostInsertEventListener postCommitInsertEventListener = new TestPostCommitInsertEventListener(); + private PostDeleteEventListener postCommitDeleteEventListener = new TestPostCommitDeleteEventListener(); + private PostUpdateEventListener postCommitUpdateEventListener = new TestPostCommitUpdateEventListener(); + + @Override + protected void prepareTest() throws Exception { + ((TestPostCommitInsertEventListener) postCommitInsertEventListener).success = 0; + ((TestPostCommitInsertEventListener) postCommitInsertEventListener).failed = 0; + ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).success = 0; + ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).failed = 0; + ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).sucess = 0; + ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).failed = 0; + } + + @Override + protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) { + super.prepareBootstrapRegistryBuilder( builder ); + builder.with( + new Integrator() { + + @Override + public void integrate( + Configuration configuration, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + @Override + public void integrate( + MetadataImplementor metadata, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + private void integrate(SessionFactoryServiceRegistry serviceRegistry) { + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_DELETE + ).appendListener( postCommitDeleteEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_UPDATE + ).appendListener( postCommitUpdateEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_INSERT + ).appendListener( postCommitInsertEventListener ); + } + + @Override + public void disintegrate( + SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + } + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + Assert.assertEquals( 1, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).success ); + Assert.assertEquals( 0, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.rollback(); + session.close(); + + Assert.assertEquals( 0, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).success ); + Assert.assertEquals( 1, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).sucess ); + Assert.assertEquals( 0, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + Assert.assertEquals( 0, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).sucess ); + Assert.assertEquals( 1, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).success ); + Assert.assertEquals( 0, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + Assert.assertEquals( 0, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).success ); + Assert.assertEquals( 1, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).failed ); + } + + private class TestPostCommitDeleteEventListener implements PostCommitDeleteEventListener { + int success; + int failed; + + @Override + public void onPostDelete(PostDeleteEvent event) { + success++; + } + + @Override + public void onPostDeleteCommitFailed(PostDeleteEvent event) { + failed++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class TestPostCommitUpdateEventListener implements PostCommitUpdateEventListener { + int sucess; + int failed; + + @Override + public void onPostUpdate(PostUpdateEvent event) { + sucess++; + } + + @Override + public void onPostUpdateCommitFailed(PostUpdateEvent event) { + failed++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class TestPostCommitInsertEventListener implements PostCommitInsertEventListener { + int success; + int failed; + + @Override + public void onPostInsert(PostInsertEvent event) { + success++; + } + + @Override + public void onPostInsertCommitFailed(PostInsertEvent event) { + failed++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {IrrelevantEntity.class}; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Customer.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Customer.hbm.xml deleted file mode 100644 index db3e822e729c..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Customer.hbm.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Customer.java b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Customer.java deleted file mode 100644 index 084f61a46930..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Customer.java +++ /dev/null @@ -1,36 +0,0 @@ -//$Id: Customer.java 5011 2004-12-19 22:01:25Z maxcsaucdk $ -package org.hibernate.test.extendshbm; - - -/** - * @author Gavin King - */ -public class Customer extends Person { - private Employee salesperson; - private String comments; - - /** - * @return Returns the salesperson. - */ - public Employee getSalesperson() { - return salesperson; - } - /** - * @param salesperson The salesperson to set. - */ - public void setSalesperson(Employee salesperson) { - this.salesperson = salesperson; - } - /** - * @return Returns the comments. - */ - public String getComments() { - return comments; - } - /** - * @param comments The comments to set. - */ - public void setComments(String comments) { - this.comments = comments; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Employee.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Employee.hbm.xml deleted file mode 100644 index 0d7e5f5fcd95..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Employee.hbm.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Employee.java b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Employee.java deleted file mode 100644 index 5b2a802bfee6..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Employee.java +++ /dev/null @@ -1,48 +0,0 @@ -//$Id: Employee.java 5011 2004-12-19 22:01:25Z maxcsaucdk $ -package org.hibernate.test.extendshbm; -import java.math.BigDecimal; - -/** - * @author Gavin King - */ -public class Employee extends Person { - private String title; - private BigDecimal salary; - private Employee manager; - /** - * @return Returns the title. - */ - public String getTitle() { - return title; - } - /** - * @param title The title to set. - */ - public void setTitle(String title) { - this.title = title; - } - /** - * @return Returns the manager. - */ - public Employee getManager() { - return manager; - } - /** - * @param manager The manager to set. - */ - public void setManager(Employee manager) { - this.manager = manager; - } - /** - * @return Returns the salary. - */ - public BigDecimal getSalary() { - return salary; - } - /** - * @param salary The salary to set. - */ - public void setSalary(BigDecimal salary) { - this.salary = salary; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/ExtendsTest.java b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/ExtendsTest.java deleted file mode 100644 index 77162cb6c19b..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/ExtendsTest.java +++ /dev/null @@ -1,211 +0,0 @@ -//$Id: ExtendsTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $ -package org.hibernate.test.extendshbm; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.HibernateException; -import org.hibernate.cfg.Configuration; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -/** - * @author Gavin King - */ -public class ExtendsTest extends BaseUnitTestCase { - private StandardServiceRegistryImpl serviceRegistry; - - @Before - public void setUp() { - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry(); - } - - @After - public void tearDown() { - ServiceRegistryBuilder.destroy( serviceRegistry ); - } - - private String getBaseForMappings() { - return "org/hibernate/test/"; - } - - @Test - public void testAllInOne() { - Configuration cfg = new Configuration(); - - cfg.addResource( getBaseForMappings() + "extendshbm/allinone.hbm.xml" ); - cfg.buildMappings(); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Person" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Employee" ) ); - } - - @Test - public void testOutOfOrder() { - Configuration cfg = new Configuration(); - - try { - cfg.addResource( getBaseForMappings() + "extendshbm/Customer.hbm.xml" ); - assertNull( - "cannot be in the configuration yet!", - cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) - ); - cfg.addResource( getBaseForMappings() + "extendshbm/Person.hbm.xml" ); - cfg.addResource( getBaseForMappings() + "extendshbm/Employee.hbm.xml" ); - -// cfg.buildSessionFactory( serviceRegistry ); - cfg.buildMappings(); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Person" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Employee" ) ); - - } - catch ( HibernateException e ) { - fail( "should not fail with exception! " + e ); - } - - } - - @Test - public void testNwaitingForSuper() { - Configuration cfg = new Configuration(); - - try { - cfg.addResource( getBaseForMappings() + "extendshbm/Customer.hbm.xml" ); - assertNull( - "cannot be in the configuration yet!", - cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) - ); - cfg.addResource( getBaseForMappings() + "extendshbm/Employee.hbm.xml" ); - assertNull( - "cannot be in the configuration yet!", - cfg.getClassMapping( "org.hibernate.test.extendshbm.Employee" ) - ); - cfg.addResource( getBaseForMappings() + "extendshbm/Person.hbm.xml" ); - - cfg.buildMappings(); - - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Person" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Employee" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) ); - - - } - catch ( HibernateException e ) { - e.printStackTrace(); - fail( "should not fail with exception! " + e ); - - } - - } - - @Test - public void testMissingSuper() { - Configuration cfg = new Configuration(); - - try { - cfg.addResource( getBaseForMappings() + "extendshbm/Customer.hbm.xml" ); - assertNull( - "cannot be in the configuration yet!", - cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) - ); - cfg.addResource( getBaseForMappings() + "extendshbm/Employee.hbm.xml" ); - -// cfg.buildSessionFactory( serviceRegistry ); - cfg.buildMappings(); - fail( "Should not be able to build sessionFactory without a Person" ); - } - catch ( HibernateException e ) { - - } - - } - - @Test - public void testAllSeparateInOne() { - Configuration cfg = new Configuration(); - - try { - cfg.addResource( getBaseForMappings() + "extendshbm/allseparateinone.hbm.xml" ); - -// cfg.buildSessionFactory( serviceRegistry ); - - cfg.buildMappings(); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Person" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Employee" ) ); - - } - catch ( HibernateException e ) { - fail( "should not fail with exception! " + e ); - } - - } - - @Test - public void testJoinedSubclassAndEntityNamesOnly() { - Configuration cfg = new Configuration(); - - try { - cfg.addResource( getBaseForMappings() + "extendshbm/entitynames.hbm.xml" ); - - cfg.buildMappings(); - - assertNotNull( cfg.getClassMapping( "EntityHasName" ) ); - assertNotNull( cfg.getClassMapping( "EntityCompany" ) ); - - } - catch ( HibernateException e ) { - e.printStackTrace(); - fail( "should not fail with exception! " + e ); - - } - } - - @Test - public void testEntityNamesWithPackage() { - Configuration cfg = new Configuration(); - try { - cfg.addResource( getBaseForMappings() + "extendshbm/packageentitynames.hbm.xml" ); - - cfg.buildMappings(); - - assertNotNull( cfg.getClassMapping( "EntityHasName" ) ); - assertNotNull( cfg.getClassMapping( "EntityCompany" ) ); - - } - catch ( HibernateException e ) { - e.printStackTrace(); - fail( "should not fail with exception! " + e ); - - } - } - - @Test - public void testUnionSubclass() { - Configuration cfg = new Configuration(); - - try { - cfg.addResource( getBaseForMappings() + "extendshbm/unionsubclass.hbm.xml" ); - - cfg.buildMappings(); - - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Person" ) ); - assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) ); - - } - catch ( HibernateException e ) { - e.printStackTrace(); - fail( "should not fail with exception! " + e ); - - } - } - -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Person.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Person.hbm.xml deleted file mode 100644 index 92ce3ab2def5..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Person.hbm.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Person.java b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Person.java deleted file mode 100644 index c2c1fa80b774..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/Person.java +++ /dev/null @@ -1,51 +0,0 @@ -//$Id: Person.java 5011 2004-12-19 22:01:25Z maxcsaucdk $ -package org.hibernate.test.extendshbm; - - - -/** - * @author Gavin King - */ -public class Person { - private long id; - private String name; - private char sex; - - /** - * @return Returns the sex. - */ - public char getSex() { - return sex; - } - /** - * @param sex The sex to set. - */ - public void setSex(char sex) { - this.sex = sex; - } - /** - * @return Returns the id. - */ - public long getId() { - return id; - } - /** - * @param id The id to set. - */ - public void setId(long id) { - this.id = id; - } - /** - * @return Returns the identity. - */ - public String getName() { - return name; - } - /** - * @param identity The identity to set. - */ - public void setName(String identity) { - this.name = identity; - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/allinone.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/allinone.hbm.xml deleted file mode 100644 index 0cbac2717f2d..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/allinone.hbm.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/allseparateinone.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/allseparateinone.hbm.xml deleted file mode 100644 index 560565e279a9..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/allseparateinone.hbm.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/entitynames.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/entitynames.hbm.xml deleted file mode 100644 index c0247a8e565b..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/entitynames.hbm.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/packageentitynames.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/packageentitynames.hbm.xml deleted file mode 100644 index da2e1bb5c1e1..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/packageentitynames.hbm.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/unionsubclass.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/extendshbm/unionsubclass.hbm.xml deleted file mode 100644 index d773f307f4b3..000000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/extendshbm/unionsubclass.hbm.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hibernate-core/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java b/hibernate-core/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java index 5c86aaf22015..8c96009d8d39 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java @@ -31,9 +31,6 @@ import java.util.List; import java.util.Set; -import org.jboss.logging.Logger; -import org.junit.Test; - import org.hibernate.Criteria; import org.hibernate.FetchMode; import org.hibernate.Hibernate; @@ -51,9 +48,13 @@ import org.hibernate.dialect.SybaseASE15Dialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.transform.DistinctRootEntityResultTransformer; + import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.transform.DistinctRootEntityResultTransformer; +import org.junit.Test; + +import org.jboss.logging.Logger; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; diff --git a/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java b/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java index b86bf36cfa00..9103f0f38067 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java +++ b/hibernate-core/src/test/java/org/hibernate/test/flush/TestAutoFlushBeforeQueryExecution.java @@ -43,7 +43,7 @@ import org.hibernate.event.spi.PreUpdateEventListener; import org.hibernate.integrator.spi.Integrator; import org.hibernate.internal.SessionImpl; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.TestForIssue; diff --git a/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java b/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java index 8170107e61e3..f120d2b01744 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java +++ b/hibernate-core/src/test/java/org/hibernate/test/flush/TestCollectionInitializingDuringFlush.java @@ -35,7 +35,7 @@ import org.hibernate.event.spi.PreUpdateEvent; import org.hibernate.event.spi.PreUpdateEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java index de3f0728ea18..bbe600fdaedf 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/FormulaJoinTest.java @@ -22,24 +22,22 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.formulajoin; -import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import org.junit.Test; +import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; - -import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class FormulaJoinTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "formulajoin/Master.hbm.xml" }; @@ -68,7 +66,7 @@ public void testFormulaJoin() { tx.commit(); s.close(); - if ( getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect ) return; + if ( getDialect() instanceof PostgreSQL81Dialect ) return; s = openSession(); tx = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/generated/DefaultGeneratedValueTest.java b/hibernate-core/src/test/java/org/hibernate/test/generated/DefaultGeneratedValueTest.java index 2885fc7d4435..6010b48a2024 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/generated/DefaultGeneratedValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/generated/DefaultGeneratedValueTest.java @@ -45,6 +45,7 @@ import org.hibernate.annotations.GenerationTime; import org.hibernate.annotations.GeneratorType; import org.hibernate.annotations.UpdateTimestamp; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.tuple.ValueGenerator; @@ -57,6 +58,7 @@ * @author Steve Ebersole * @author Gunnar Morling */ +@FailureExpectedWithNewMetamodel public class DefaultGeneratedValueTest extends BaseCoreFunctionalTestCase { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java index 26cb5bf0055b..b5f1c9592d01 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java @@ -23,6 +23,15 @@ */ package org.hibernate.test.hql; +import static org.hibernate.testing.junit4.ExtraAssertions.assertClassAssignability; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Date; @@ -35,36 +44,31 @@ import java.util.List; import java.util.Map; -import org.jboss.logging.Logger; -import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.QueryException; -import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.TypeMismatchException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.AbstractHANADialect; +import org.hibernate.dialect.CUBRIDDialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HSQLDialect; -import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.IngresDialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SQLServer2008Dialect; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.Sybase11Dialect; import org.hibernate.dialect.SybaseASE15Dialect; import org.hibernate.dialect.SybaseAnywhereDialect; import org.hibernate.dialect.SybaseDialect; -import org.hibernate.dialect.CUBRIDDialect; import org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory; import org.hibernate.internal.util.StringHelper; import org.hibernate.persister.entity.DiscriminatorType; @@ -80,6 +84,7 @@ import org.hibernate.test.cid.Product; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; @@ -90,15 +95,8 @@ import org.hibernate.type.ComponentType; import org.hibernate.type.ManyToOneType; import org.hibernate.type.Type; - -import static org.hibernate.testing.junit4.ExtraAssertions.assertClassAssignability; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.jboss.logging.Logger; +import org.junit.Test; /** * Tests the integration of the new AST parser into the loading of query results using @@ -115,6 +113,7 @@ comment = "As of verion 8.4.1 CUBRID doesn't support temporary tables. This test fails with" + "HibernateException: cannot doAfterTransactionCompletion multi-table deletes using dialect not supporting temp tables" ) +@FailureExpectedWithNewMetamodel public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase { private static final Logger log = Logger.getLogger( ASTParserLoadingTest.class ); @@ -133,6 +132,7 @@ public String[] getMappings() { "hql/Image.hbm.xml", "hql/ComponentContainer.hbm.xml", "hql/VariousKeywordPropertyEntity.hbm.xml", + "hql/Constructor.hbm.xml", "batchfetch/ProductLine.hbm.xml", "cid/Customer.hbm.xml", "cid/Order.hbm.xml", @@ -212,6 +212,33 @@ public void testExpandListParameter() { session.close(); } + @Test + @TestForIssue(jiraKey = "HHH-8699") + // For now, restrict to H2. Selecting w/ predicate functions cause issues for too many dialects. + @RequiresDialect(value = H2Dialect.class, jiraKey = "HHH-9052") + public void testBooleanPredicate() { + final Session session = openSession(); + + session.getTransaction().begin(); + final Constructor constructor = new Constructor(); + session.save( constructor ); + session.getTransaction().commit(); + + session.clear(); + Constructor.resetConstructorExecutionCount(); + + session.getTransaction().begin(); + final Constructor result = (Constructor) session.createQuery( + "select new Constructor( c.id, c.id is not null, c.id = c.id, c.id + 1, concat( c.id, 'foo' ) ) from Constructor c where c.id = :id" + ).setParameter( "id", constructor.getId() ).uniqueResult(); + session.getTransaction().commit(); + + assertEquals( 1, Constructor.getConstructorExecutionCount() ); + assertEquals( new Constructor( constructor.getId(), true, true, constructor.getId() + 1, constructor.getId() + "foo" ), result ); + + session.close(); + } + @Test public void testJpaTypeOperator() { // just checking syntax here... @@ -761,8 +788,7 @@ public void testExpressionWithParamInFunction() { s.createQuery( "from Animal where abs(cast(1 as double) - cast(:param as double)) = 1.0" ) .setLong( "param", 1 ).list(); } - else if ( !( getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect - || getDialect() instanceof MySQLDialect ) ) { + else if ( !( getDialect() instanceof PostgreSQL81Dialect || getDialect() instanceof MySQLDialect ) ) { s.createQuery( "from Animal where abs(cast(1 as float) - cast(:param as float)) = 1.0" ) .setLong( "param", 1 ).list(); } @@ -3090,8 +3116,7 @@ public void testEJBQLFunctions() throws Exception { * PostgreSQL >= 8.3.7 typecasts are no longer automatically allowed * http://www.postgresql.org/docs/current/static/release-8-3.html */ - if ( getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect - || getDialect() instanceof HSQLDialect ) { + if ( getDialect() instanceof PostgreSQL81Dialect || getDialect() instanceof HSQLDialect ) { hql = "from Animal a where bit_length(str(a.bodyWeight)) = 24"; } else { @@ -3099,8 +3124,7 @@ public void testEJBQLFunctions() throws Exception { } session.createQuery(hql).list(); - if ( getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect - || getDialect() instanceof HSQLDialect ) { + if ( getDialect() instanceof PostgreSQL81Dialect || getDialect() instanceof HSQLDialect ) { hql = "select bit_length(str(a.bodyWeight)) from Animal a"; } else { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java index 100047ffe43e..9fe5e7e0bda1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java @@ -45,6 +45,7 @@ import org.hibernate.id.IdentifierGenerator; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.SkipLog; @@ -687,6 +688,7 @@ public void testIncorrectSyntax() { @SuppressWarnings( {"unchecked"}) @Test + @FailureExpectedWithNewMetamodel public void testUpdateWithWhereExistsSubquery() { // multi-table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Session s = openSession(); @@ -1383,6 +1385,7 @@ public void testManyToManyBulkDelete() { @Test @TestForIssue( jiraKey = "HHH-1917" ) + @FailureExpectedWithNewMetamodel public void testManyToManyBulkDeleteMultiTable() { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/CaseStatementTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/CaseStatementTest.java new file mode 100644 index 000000000000..165e04b39a7e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/CaseStatementTest.java @@ -0,0 +1,154 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.hql; + +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.QueryException; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.junit.Assert.fail; + +/** + * @author Steve Ebersole + */ +public class CaseStatementTest extends BaseCoreFunctionalTestCase { + + @Entity(name = "Person") + public static class Person { + @Id + private Integer id; + private String name; + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Test + public void testSimpleCaseStatementFixture() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + s.createQuery( "select case p.name when 'Steve' then 'x' else 'y' end from Person p" ) + .list(); + + t.commit(); + s.close(); + } + + @Test + public void testSimpleCaseStatementWithParamResult() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + s.createQuery( "select case p.name when 'Steve' then :opt1 else p.name end from Person p" ) + .setString( "opt1", "x" ) + .list(); + + t.commit(); + s.close(); + } + + @Test + public void testSimpleCaseStatementWithParamAllResults() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + try { + s.createQuery( "select case p.name when 'Steve' then :opt1 else :opt2 end from Person p" ) + .setString( "opt1", "x" ) + .setString( "opt2", "y" ) + .list(); + fail( "was expecting an exception" ); + } + catch (QueryException expected) { + // expected + } + + s.createQuery( "select case p.name when 'Steve' then cast( :opt1 as string ) else cast( :opt2 as string) end from Person p" ) + .setString( "opt1", "x" ) + .setString( "opt2", "y" ) + .list(); + + t.commit(); + s.close(); + } + + @Test + public void testSearchedCaseStatementFixture() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + s.createQuery( "select case when p.name = 'Steve' then 'x' else 'y' end from Person p" ) + .list(); + + t.commit(); + s.close(); + } + + @Test + public void testSearchedCaseStatementWithParamResult() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + s.createQuery( "select case when p.name = 'Steve' then :opt1 else p.name end from Person p" ) + .setString( "opt1", "x" ) + .list(); + + t.commit(); + s.close(); + } + + @Test + public void testSearchedCaseStatementWithAllParamResults() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + try { + s.createQuery( "select case when p.name = 'Steve' then :opt1 else :opt2 end from Person p" ) + .setString( "opt1", "x" ) + .setString( "opt2", "y" ) + .list(); + fail( "was expecting an exception" ); + } + catch (QueryException expected) { + // expected + } + + s.createQuery( "select case when p.name = 'Steve' then cast( :opt1 as string) else :opt2 end from Person p" ) + .setString( "opt1", "x" ) + .setString( "opt2", "y" ) + .list(); + + t.commit(); + s.close(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/CastFunctionTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/CastFunctionTest.java new file mode 100644 index 000000000000..e72ede47e7ae --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/CastFunctionTest.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.hql; + +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.Session; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +/** + * @author Steve Ebersole + */ +public class CastFunctionTest extends BaseCoreFunctionalTestCase { + @Entity( name="MyEntity" ) + public static class MyEntity { + @Id + private Integer id; + private String name; + private Number theLostNumber; + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { MyEntity.class }; + } + + @Test + public void testStringCasting() { + Session s = openSession(); + s.beginTransaction(); + + // using the short name + s.createQuery( "select cast(e.theLostNumber as string) from MyEntity e" ).list(); + // using the java class name + s.createQuery( "select cast(e.theLostNumber as java.lang.String) from MyEntity e" ).list(); + // using the fqn Hibernate Type name + s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.StringType) from MyEntity e" ).list(); + + s.getTransaction().commit(); + s.close(); + } + + @Test + public void testIntegerCasting() { + Session s = openSession(); + s.beginTransaction(); + + // using the short name + s.createQuery( "select cast(e.theLostNumber as integer) from MyEntity e" ).list(); + // using the java class name (primitive) + s.createQuery( "select cast(e.theLostNumber as int) from MyEntity e" ).list(); + // using the java class name + s.createQuery( "select cast(e.theLostNumber as java.lang.Integer) from MyEntity e" ).list(); + // using the fqn Hibernate Type name + s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.IntegerType) from MyEntity e" ).list(); + + s.getTransaction().commit(); + s.close(); + } + + @Test + public void testLongCasting() { + Session s = openSession(); + s.beginTransaction(); + + // using the short name (also the primitive name) + s.createQuery( "select cast(e.theLostNumber as long) from MyEntity e" ).list(); + // using the java class name + s.createQuery( "select cast(e.theLostNumber as java.lang.Long) from MyEntity e" ).list(); + // using the fqn Hibernate Type name + s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.LongType) from MyEntity e" ).list(); + + s.getTransaction().commit(); + s.close(); + } + + @Test + public void testFloatCasting() { + Session s = openSession(); + s.beginTransaction(); + + // using the short name (also the primitive name) + s.createQuery( "select cast(e.theLostNumber as float) from MyEntity e" ).list(); + // using the java class name + s.createQuery( "select cast(e.theLostNumber as java.lang.Float) from MyEntity e" ).list(); + // using the fqn Hibernate Type name + s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.FloatType) from MyEntity e" ).list(); + + s.getTransaction().commit(); + s.close(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java index bc00e31e4587..1e27e322b44c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/ClassicTranslatorTest.java @@ -29,6 +29,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * Some simple test queries using the classic translator explicitly @@ -38,6 +39,7 @@ * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class ClassicTranslatorTest extends QueryTranslatorTestCase { @Override public void configure(Configuration cfg) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Constructor.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/hql/Constructor.hbm.xml new file mode 100644 index 000000000000..b6b104086534 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Constructor.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Constructor.java b/hibernate-core/src/test/java/org/hibernate/test/hql/Constructor.java new file mode 100644 index 000000000000..557827a80c33 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Constructor.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.hql; + +import java.io.Serializable; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class Constructor implements Serializable { + private static int CONSTRUCTOR_EXECUTION_COUNT = 0; + + private long id; + private String someString; + private Number someNumber; + private boolean someBoolean; + private boolean anotherBoolean; + + public Constructor() { + } + + public Constructor(long id, boolean someBoolean, boolean anotherBoolean, Number someNumber, String someString) { + this.id = id; + this.someBoolean = someBoolean; + this.anotherBoolean = anotherBoolean; + this.someNumber = someNumber; + this.someString = someString; + ++CONSTRUCTOR_EXECUTION_COUNT; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) return true; + if ( !( o instanceof Constructor ) ) return false; + + Constructor that = (Constructor) o; + + if ( anotherBoolean != that.anotherBoolean ) return false; + if ( id != that.id ) return false; + if ( someBoolean != that.someBoolean ) return false; + if ( someNumber != null ? !someNumber.equals( that.someNumber ) : that.someNumber != null ) return false; + if ( someString != null ? !someString.equals( that.someString ) : that.someString != null ) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + (someString != null ? someString.hashCode() : 0); + result = 31 * result + (someNumber != null ? someNumber.hashCode() : 0); + result = 31 * result + (someBoolean ? 1 : 0); + result = 31 * result + (anotherBoolean ? 1 : 0); + return result; + } + + public boolean isSomeBoolean() { + return someBoolean; + } + + public void setSomeBoolean(boolean someBoolean) { + this.someBoolean = someBoolean; + } + + public Number getSomeNumber() { + return someNumber; + } + + public void setSomeNumber(Number someNumber) { + this.someNumber = someNumber; + } + + public String getSomeString() { + return someString; + } + + public void setSomeString(String someString) { + this.someString = someString; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public boolean isAnotherBoolean() { + return anotherBoolean; + } + + public void setAnotherBoolean(boolean anotherBoolean) { + this.anotherBoolean = anotherBoolean; + } + + public static int getConstructorExecutionCount() { + return CONSTRUCTOR_EXECUTION_COUNT; + } + + public static void resetConstructorExecutionCount() { + CONSTRUCTOR_EXECUTION_COUNT = 0; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java index 12b18a5030f9..4253efc356aa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/CriteriaClassicAggregationReturnTest.java @@ -34,6 +34,7 @@ import org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.type.BigDecimalType; import org.hibernate.type.BigIntegerType; import org.hibernate.type.DoubleType; @@ -46,6 +47,7 @@ /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class CriteriaClassicAggregationReturnTest extends QueryTranslatorTestCase { @Override public void configure(Configuration cfg) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java index aed303233657..d94146754179 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/EJBQLTest.java @@ -39,6 +39,7 @@ import org.hibernate.hql.internal.ast.util.ASTUtil; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static junit.framework.Assert.assertEquals; @@ -47,6 +48,7 @@ /** * @author Alexey Loubyansky */ +@FailureExpectedWithNewMetamodel public class EJBQLTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java index 8705bc381928..90a8075c45cb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/HQLTest.java @@ -22,6 +22,12 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.hql; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; @@ -30,20 +36,15 @@ import java.util.List; import java.util.Map; -import antlr.RecognitionException; -import antlr.collections.AST; -import org.junit.Test; - import org.hibernate.QueryException; +import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.H2Dialect; -import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.IngresDialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.Sybase11Dialect; import org.hibernate.dialect.SybaseASE15Dialect; @@ -70,24 +71,24 @@ import org.hibernate.hql.spi.QueryTranslatorFactory; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.type.CalendarDateType; import org.hibernate.type.DoubleType; import org.hibernate.type.StringType; +import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import antlr.RecognitionException; +import antlr.collections.AST; /** * Tests cases where the AST based query translator and the 'classic' query translator generate identical SQL. * * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class HQLTest extends QueryTranslatorTestCase { @Override public boolean createSchema() { @@ -356,7 +357,7 @@ public void testExpressionWithParamInFunction() { if ( !( getDialect() instanceof MySQLDialect ) && ! ( getDialect() instanceof SybaseDialect ) && ! ( getDialect() instanceof Sybase11Dialect ) && !( getDialect() instanceof SybaseASE15Dialect ) && ! ( getDialect() instanceof SybaseAnywhereDialect ) && ! ( getDialect() instanceof SQLServerDialect ) ) { assertTranslation("from Animal where lower(upper('foo') || upper(:bar)) like 'f%'"); } - if ( getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect ) { + if ( getDialect() instanceof PostgreSQL81Dialect ) { return; } if ( getDialect() instanceof AbstractHANADialect ) { @@ -845,7 +846,7 @@ public void testOrderBy() throws Exception { @Test public void testGroupByFunction() { if ( getDialect() instanceof Oracle8iDialect ) return; // the new hiearchy... - if ( getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect ) return; + if ( getDialect() instanceof PostgreSQL81Dialect ) return; if ( ! H2Dialect.class.isInstance( getDialect() ) ) { // H2 has no year function assertTranslation( "select count(*) from Human h group by year(h.birthdate)" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/TupleSupportTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/TupleSupportTest.java index f8f4639a614c..c81387ba9530 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/TupleSupportTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/TupleSupportTest.java @@ -23,35 +23,30 @@ */ package org.hibernate.test.hql; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; + import javax.persistence.Embeddable; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Id; -import java.util.Collections; - import org.hibernate.Filter; -import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.query.spi.HQLQueryPlan; import org.hibernate.engine.spi.SessionFactoryImplementor; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.After; -import org.junit.AfterClass; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - /** * @author Steve Ebersole */ @@ -107,6 +102,7 @@ public void testImplicitTupleNotEquals() { } @Test + @FailureExpectedWithNewMetamodel public void testImplicitTupleNotInList() { final String hql = "from TheEntity e where e.compositeValue not in (:p1,:p2)"; HQLQueryPlan queryPlan = ( (SessionFactoryImplementor) sessionFactory ).getQueryPlanCache() diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java index e470e2cbfc74..52b3815cd16f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java @@ -36,6 +36,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.hql.internal.ast.InvalidWithClauseException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -51,6 +52,7 @@ public String[] getMappings() { } @Test + @FailureExpectedWithNewMetamodel public void testWithClauseFailsWithFetch() { TestData data = new TestData(); data.prepare(); @@ -106,6 +108,7 @@ public void testInvalidWithSemantics() { } @Test + @FailureExpectedWithNewMetamodel public void testWithClause() { TestData data = new TestData(); data.prepare(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/id/Person.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/id/Person.hbm.xml new file mode 100644 index 000000000000..4e32f5a5dd7f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/id/Person.hbm.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/id/Person.java b/hibernate-core/src/test/java/org/hibernate/test/id/Person.java new file mode 100644 index 000000000000..c552f85c8f52 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/id/Person.java @@ -0,0 +1,19 @@ +package org.hibernate.test.id; + + +public class Person { + + private long id; + + public Person() { + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/id/SequenceGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/id/SequenceGeneratorTest.java new file mode 100644 index 000000000000..c43c362609eb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/id/SequenceGeneratorTest.java @@ -0,0 +1,37 @@ +package org.hibernate.test.id; + +import static org.junit.Assert.assertTrue; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +public class SequenceGeneratorTest extends BaseCoreFunctionalTestCase { + + @Override + public String[] getMappings() { + return new String[] { "id/Person.hbm.xml" }; + } + + /** + * This seems a little trivial, but we need to guarantee that all Dialects start their sequences on a non-0 value. + */ + @Test + @TestForIssue(jiraKey = "HHH-8814") + @RequiresDialectFeature(DialectChecks.SupportsSequences.class) + public void testStartOfSequence() throws Exception { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + final Person person = new Person(); + s.persist(person); + tx.commit(); + s.close(); + + assertTrue(person.getId() > 0); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java b/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java index 27e89ab67eb9..adfa006082a4 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idbag/IdBagTest.java @@ -31,6 +31,7 @@ import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel( message = " not supported" ) public class IdBagTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/idclass/Customer.java b/hibernate-core/src/test/java/org/hibernate/test/idclass/Customer.java index 8ad62eab50a5..a9d64e69d7fc 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/idclass/Customer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idclass/Customer.java @@ -1,91 +1,55 @@ -//$Id: Customer.java 7858 2005-08-11 21:46:58Z epbernard $ - package org.hibernate.test.idclass; - - - - - public class Customer { - + private String orgName; + private String customerName; + private String address; public Customer() { - super(); - } - - public Customer(String orgName, String custName, String add) { - this.orgName = orgName; - this.customerName = custName; - this.address = add; - } - - - private String orgName; - - private String customerName; - - private String address; - - - public String getAddress() { return address; } - - public void setAddress(String address) { this.address = address; } - - public String getCustomerName() { return customerName; } - - public void setCustomerName(String customerName) { this.customerName = customerName; } - - public String getOrgName() { return orgName; } - - public void setOrgName(String orgName) { this.orgName = orgName; } - - - } diff --git a/hibernate-core/src/test/java/org/hibernate/test/idclass/CustomerId.java b/hibernate-core/src/test/java/org/hibernate/test/idclass/CustomerId.java index cae9973d9dc6..48fc6d243f8a 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/idclass/CustomerId.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idclass/CustomerId.java @@ -1,9 +1,9 @@ -//$Id: CustomerId.java 7239 2005-06-20 09:44:54Z oneovthafew $ package org.hibernate.test.idclass; + import java.io.Serializable; public class CustomerId implements Serializable { - + private String orgName; private String customerName; @@ -31,5 +31,4 @@ public String getOrgName() { public void setOrgName(String orgName) { this.orgName = orgName; } - } diff --git a/hibernate-core/src/test/java/org/hibernate/test/idclass/FavoriteCustomer.java b/hibernate-core/src/test/java/org/hibernate/test/idclass/FavoriteCustomer.java index 71105d4fbdbb..64601851eed2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/idclass/FavoriteCustomer.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idclass/FavoriteCustomer.java @@ -1,7 +1,5 @@ -//$Id: FavoriteCustomer.java 7858 2005-08-11 21:46:58Z epbernard $ package org.hibernate.test.idclass; - /** * @author Emmanuel Bernard */ diff --git a/hibernate-core/src/test/java/org/hibernate/test/idclass/IdClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idclass/IdClassTest.java index c40d50edce4f..0fc9c4669947 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/idclass/IdClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idclass/IdClassTest.java @@ -27,6 +27,8 @@ import org.hibernate.Session; import org.hibernate.Transaction; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -34,6 +36,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class IdClassTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "idclass/Customer.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java index 37af55a267e2..31baf5ba7c09 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java @@ -30,6 +30,7 @@ import org.hibernate.Session; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java b/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java index 838204dc5d6a..eeedae4c3674 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java @@ -35,6 +35,7 @@ import org.hibernate.criterion.Projections; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.proxy.HibernateProxy; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.type.AbstractSingleColumnStandardBasicType; import org.hibernate.type.TextType; @@ -77,6 +78,7 @@ public String[] getMappings() { } @Test + @FailureExpectedWithNewMetamodel public void testChangeImmutableEntityProxyToModifiable() { Contract c = new Contract( null, "gavin", "phone"); ContractVariation cv1 = new ContractVariation(1, c); @@ -138,6 +140,7 @@ public void testChangeImmutableEntityProxyToModifiable() { } @Test + @FailureExpectedWithNewMetamodel public void testChangeImmutableEntityToModifiable() { Contract c = new Contract( null, "gavin", "phone"); ContractVariation cv1 = new ContractVariation(1, c); @@ -929,7 +932,12 @@ public void testUnmodifiedImmutableParentEntityWithMerge() { t = s.beginTransaction(); c = ( Contract ) s.merge( c ); assertTrue( s.isReadOnly( c ) ); - assertTrue( Hibernate.isInitialized( c.getVariations() ) ); + // Contract has 2 collections (subcontracts and variations); + // only 1 will be eagerly loaded with the merge; + // the 1 that is eagerly loaded will be the one that gets bound + // first; since this is indeterminate, we cannot test if the + // collection is initialized. + assertEquals( 2, c.getVariations().size() ); Iterator it = c.getVariations().iterator(); cv1 = (ContractVariation) it.next(); cv2 = (ContractVariation) it.next(); @@ -984,7 +992,12 @@ public void testImmutableParentEntityWithMerge() { c.setCustomerName("foo bar"); c = ( Contract ) s.merge( c ); assertTrue( s.isReadOnly( c ) ); - assertTrue( Hibernate.isInitialized( c.getVariations() ) ); + // Contract has 2 collections (subcontracts and variations); + // only 1 will be eagerly loaded with the merge; + // the 1 that is eagerly loaded will be the one that gets bound + // first; since this is indeterminate, we cannot test if the + // collection is initialized. + assertEquals( 2, c.getVariations().size() ); Iterator it = c.getVariations().iterator(); cv1 = (ContractVariation) it.next(); cv2 = (ContractVariation) it.next(); @@ -1040,7 +1053,12 @@ public void testImmutableChildEntityWithMerge() { cv1.setText("blah blah"); c = ( Contract ) s.merge( c ); assertTrue( s.isReadOnly( c ) ); - assertTrue( Hibernate.isInitialized( c.getVariations() ) ); + // Contract has 2 collections (subcontracts and variations); + // only 1 will be eagerly loaded with the merge; + // the 1 that is eagerly loaded will be the one that gets bound + // first; since this is indeterminate, we cannot test if the + // collection is initialized. + assertEquals( 2, c.getVariations().size() ); Iterator it = c.getVariations().iterator(); cv1 = (ContractVariation) it.next(); cv2 = (ContractVariation) it.next(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/inheritancediscriminator/PersistChildEntitiesWithDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/inheritancediscriminator/PersistChildEntitiesWithDiscriminatorTest.java index 108ac5becc02..a03aa35f1ae1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/inheritancediscriminator/PersistChildEntitiesWithDiscriminatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/inheritancediscriminator/PersistChildEntitiesWithDiscriminatorTest.java @@ -23,18 +23,16 @@ */ package org.hibernate.test.inheritancediscriminator; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; /** * @author Pawel Stawicki */ -@RequiresDialect( value = {PostgreSQL81Dialect.class, PostgreSQLDialect.class}, jiraKey = "HHH-6580" ) +@RequiresDialect( value = {PostgreSQL81Dialect.class}, jiraKey = "HHH-6580" ) public class PersistChildEntitiesWithDiscriminatorTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java index f87c8de092ab..ef7d8ba89ea6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java @@ -32,6 +32,7 @@ import org.hibernate.bytecode.spi.InstrumentedClassLoader; import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.MySQLDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.ClassLoadingIsolater; @@ -85,51 +86,60 @@ public void testSetFieldInterceptor() { } @Test + @FailureExpectedWithNewMetamodel public void testDirtyCheck() { executeExecutable( "org.hibernate.test.instrument.cases.TestDirtyCheckExecutable" ); } @Test @SkipForDialect( value = { MySQLDialect.class, AbstractHANADialect.class }, comment = "wrong sql in mapping, mysql/hana need double type, but it is float type in mapping") + @FailureExpectedWithNewMetamodel public void testFetchAll() throws Exception { executeExecutable( "org.hibernate.test.instrument.cases.TestFetchAllExecutable" ); } @Test @SkipForDialect( value = { MySQLDialect.class, AbstractHANADialect.class }, comment = "wrong sql in mapping, mysql/hana need double type, but it is float type in mapping") + @FailureExpectedWithNewMetamodel public void testLazy() { executeExecutable( "org.hibernate.test.instrument.cases.TestLazyExecutable" ); } @Test @SkipForDialect( value = { MySQLDialect.class, AbstractHANADialect.class }, comment = "wrong sql in mapping, mysql/hana need double type, but it is float type in mapping") + @FailureExpectedWithNewMetamodel public void testLazyManyToOne() { executeExecutable( "org.hibernate.test.instrument.cases.TestLazyManyToOneExecutable" ); } @Test @SkipForDialect( value = { MySQLDialect.class, AbstractHANADialect.class }, comment = "wrong sql in mapping, mysql/hana need double type, but it is float type in mapping") + @FailureExpectedWithNewMetamodel public void testPropertyInitialized() { executeExecutable( "org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable" ); } @Test + @FailureExpectedWithNewMetamodel public void testManyToOneProxy() { executeExecutable( "org.hibernate.test.instrument.cases.TestManyToOneProxyExecutable" ); } @Test + @FailureExpectedWithNewMetamodel public void testLazyPropertyCustomType() { executeExecutable( "org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable" ); } @Test + @FailureExpectedWithNewMetamodel public void testSharedPKOneToOne() { executeExecutable( "org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable" ); } @Test @SkipForDialect( value = { MySQLDialect.class, AbstractHANADialect.class }, comment = "wrong sql in mapping, mysql/hana need double type, but it is float type in mapping") + @FailureExpectedWithNewMetamodel public void testCustomColumnReadAndWrite() { executeExecutable( "org.hibernate.test.instrument.cases.TestCustomColumnReadAndWrite" ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java b/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java index 47b9e5ca210f..9221de321f8e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java @@ -26,6 +26,8 @@ import org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl; import org.hibernate.bytecode.spi.BytecodeProvider; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java index ab836a61ba3b..6c73b4e860a0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithExplicitDiscriminatorTest.java @@ -12,11 +12,10 @@ import org.hibernate.Session; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.JoinedSubclassEntityPersister; -import org.hibernate.persister.entity.Loadable; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.testing.junit4.ExtraAssertions; import org.junit.Test; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; @@ -92,6 +91,9 @@ public void metadataAssertions() { } @Test + @FailureExpectedWithNewMetamodel( + message = "This is related to some 'subclass id' code in persister; there are a few failures related to that" + ) public void basicUsageTest() { Session session = openSession(); session.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java index 95b133791793..91ae1e2d2b49 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassWithImplicitDiscriminatorTest.java @@ -1,8 +1,5 @@ package org.hibernate.test.joinedsubclass; -import javax.persistence.DiscriminatorColumn; -import javax.persistence.DiscriminatorType; -import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Inheritance; @@ -16,6 +13,7 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.JoinedSubclassEntityPersister; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -78,6 +76,7 @@ protected void configure(Configuration configuration) { } @Test + @FailureExpectedWithNewMetamodel public void metadataAssertions() { EntityPersister p = sessionFactory().getEntityPersister( Dog.class.getName() ); assertNotNull( p ); @@ -95,6 +94,7 @@ public void metadataAssertions() { } @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-9050", message = "The WrongCLassException stuff") public void basicUsageTest() { Session session = openSession(); session.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java b/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java index 06ec5a95ea9b..f3bcb7d636ef 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java @@ -44,7 +44,7 @@ import org.hibernate.event.spi.FlushEventListener; import org.hibernate.event.spi.PersistEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; diff --git a/hibernate-core/src/test/java/org/hibernate/test/jpa/proxy/JPAProxyTest.java b/hibernate-core/src/test/java/org/hibernate/test/jpa/proxy/JPAProxyTest.java index d03bc50fe181..eb27d85f4615 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/jpa/proxy/JPAProxyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/jpa/proxy/JPAProxyTest.java @@ -33,6 +33,7 @@ import org.hibernate.Transaction; import org.hibernate.test.jpa.AbstractJPATest; import org.hibernate.test.jpa.Item; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -44,6 +45,7 @@ * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class JPAProxyTest extends AbstractJPATest { @Test public void testEjb3ProxyUsage() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java index 6b22592a8901..67b39bac6f35 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java @@ -36,7 +36,7 @@ import org.hibernate.event.spi.LoadEvent; import org.hibernate.event.spi.LoadEventListener; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.testing.TestForIssue; diff --git a/hibernate-core/src/test/java/org/hibernate/test/lazyload/Child.java b/hibernate-core/src/test/java/org/hibernate/test/lazyload/Child.java new file mode 100644 index 000000000000..8c7cec8de044 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/lazyload/Child.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.lazyload; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +/** + * @author Oleksander Dukhno + */ + +@Entity +public class Child { + + private Long id; + private Parent parent; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne( + cascade = CascadeType.ALL, + fetch = FetchType.LAZY + ) + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/lazyload/JtaLazyLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/lazyload/JtaLazyLoadingTest.java new file mode 100644 index 000000000000..06755ce935c1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/lazyload/JtaLazyLoadingTest.java @@ -0,0 +1,123 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.lazyload; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.jta.TestingJtaBootstrap; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * @author Oleksander Dukhno + */ +public class JtaLazyLoadingTest + extends BaseCoreFunctionalTestCase { + + private static final int CHILDREN_SIZE = 3; + private Long parentID; + private Long lastChildID; + + protected void configure(Configuration cfg) { + super.configure( cfg ); + cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" ); + + TestingJtaBootstrap.prepare( cfg.getProperties() ); + cfg.setProperty( Environment.TRANSACTION_STRATEGY, JtaTransactionFactory.class.getName() ); + } + + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + protected void prepareTest() + throws Exception { + Session s = openSession(); + s.beginTransaction(); + + Parent p = new Parent(); + for ( int i = 0; i < CHILDREN_SIZE; i++ ) { + final Child child = p.makeChild(); + s.persist( child ); + lastChildID = child.getId(); + } + s.persist( p ); + parentID = p.getId(); + + s.getTransaction().commit(); + s.clear(); + s.close(); + } + + @Test + @TestForIssue(jiraKey = "HHH-7971") + public void testLazyCollectionLoadingAfterEndTransaction() { + Session s = openSession(); + s.beginTransaction(); + Parent loadedParent = (Parent) s.load( Parent.class, parentID ); + s.getTransaction().commit(); + s.close(); + + assertFalse( Hibernate.isInitialized( loadedParent.getChildren() ) ); + + int i = 0; + for ( Child child : loadedParent.getChildren() ) { + i++; + assertNotNull( child ); + } + + assertEquals( CHILDREN_SIZE, i ); + + s = openSession(); + s.beginTransaction(); + Child loadedChild = (Child) s.load( Child.class, lastChildID ); + s.getTransaction().commit(); + s.close(); + + Parent p = loadedChild.getParent(); + int j = 0; + for ( Child child : p.getChildren() ) { + j++; + assertNotNull( child ); + } + + assertEquals( CHILDREN_SIZE, j ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/lazyload/LazyLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/lazyload/LazyLoadingTest.java new file mode 100644 index 000000000000..3723269a5ff2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/lazyload/LazyLoadingTest.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.lazyload; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** + * @author Oleksander Dukhno + */ +public class LazyLoadingTest + extends BaseCoreFunctionalTestCase { + + private static final int CHILDREN_SIZE = 3; + private Long parentID; + private Long lastChildID; + + protected void configure(Configuration cfg) { + super.configure( cfg ); + cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" ); + cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "false" ); + } + + + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + protected void prepareTest() + throws Exception { + Session s = openSession(); + s.beginTransaction(); + + Parent p = new Parent(); + for ( int i = 0; i < CHILDREN_SIZE; i++ ) { + final Child child = p.makeChild(); + s.persist( child ); + lastChildID = child.getId(); + } + s.persist( p ); + parentID = p.getId(); + + s.getTransaction().commit(); + s.clear(); + s.close(); + } + + @Test + @TestForIssue(jiraKey = "HHH-7971") + public void testLazyCollectionLoadingAfterEndTransaction() { + Session s = openSession(); + s.beginTransaction(); + Parent loadedParent = (Parent) s.load( Parent.class, parentID ); + s.getTransaction().commit(); + s.close(); + + assertFalse( Hibernate.isInitialized( loadedParent.getChildren() ) ); + + int i = 0; + for ( Child child : loadedParent.getChildren() ) { + i++; + assertNotNull( child ); + } + + assertEquals( CHILDREN_SIZE, i ); + + s = openSession(); + s.beginTransaction(); + Child loadedChild = (Child) s.load( Child.class, lastChildID ); + s.getTransaction().commit(); + s.close(); + + Parent p = loadedChild.getParent(); + int j = 0; + for ( Child child : p.getChildren() ) { + j++; + assertNotNull( child ); + } + + assertEquals( CHILDREN_SIZE, j ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/lazyload/Parent.java b/hibernate-core/src/test/java/org/hibernate/test/lazyload/Parent.java new file mode 100644 index 000000000000..7f7d48ff3adf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/lazyload/Parent.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.lazyload; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +/** + * @author Oleksander Dukhno + */ + +@Entity +public class Parent { + private Long id; + private List children = new ArrayList(); + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + Child makeChild() { + final Child c = new Child(); + c.setParent( this ); + this.children.add( c ); + return c; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java index 3d638bb85566..3d291ea94f07 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/ABCTest.java @@ -25,10 +25,13 @@ import java.util.List; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; + +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -75,14 +78,16 @@ public void testFormulaAssociation() throws Throwable { @Test public void testHigherLevelIndexDefinition() throws Throwable { - String[] commands = configuration().generateSchemaCreationScript( getDialect() ); - int max = commands.length; boolean found = false; - for (int indx = 0; indx < max; indx++) { - System.out.println("Checking command : " + commands[indx]); - found = commands[indx].indexOf("create index indx_a_name") >= 0; - if (found) - break; + for ( Schema schema : metadata().getDatabase().getSchemas() ) { + for ( Table table : schema.getTables() ) { + for ( Index index : table.getIndexes() ) { + if ( index.getName().toString().equals( "indx_a_name" ) ) { + found = true; + break; + } + } + } } assertTrue("Unable to locate indx_a_name index creation", found); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java index 95eddbb564a7..8969794ac853 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/ComponentNotNullTest.java @@ -31,6 +31,7 @@ import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.fail; @@ -39,6 +40,7 @@ * * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel public class ComponentNotNullTest extends LegacyTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java index c7bd7511be52..c44018c03f40 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomSQLTest.java @@ -1,30 +1,30 @@ //$Id: CustomSQLTest.java 10977 2006-12-12 23:28:04Z steve.ebersole@jboss.com $ package org.hibernate.test.legacy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; + import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import org.junit.Test; - import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.testing.DialectCheck; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author MAX * */ +@FailureExpectedWithNewMetamodel public class CustomSQLTest extends LegacyTestCase { @Override public String[] getMappings() { @@ -40,7 +40,7 @@ public boolean isMatch(Dialect dialect) { @Test @RequiresDialectFeature( NonIdentityGeneratorChecker.class ) - @SkipForDialect( value = {PostgreSQL81Dialect.class, PostgreSQLDialect.class}, jiraKey = "HHH-6704") + @SkipForDialect( value = {PostgreSQL81Dialect.class}, jiraKey = "HHH-6704") public void testInsert() throws HibernateException, SQLException { Session s = openSession(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java index c56710181b32..d4fb4de62e74 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/FooBarTest.java @@ -64,15 +64,14 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.action.spi.BeforeTransactionCompletionProcess; -import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Example; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; +import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.H2Dialect; -import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.InterbaseDialect; import org.hibernate.dialect.MckoiDialect; @@ -80,7 +79,6 @@ import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.PointbaseDialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SAPDBDialect; import org.hibernate.dialect.Sybase11Dialect; import org.hibernate.dialect.SybaseASE15Dialect; @@ -95,7 +93,7 @@ import org.hibernate.jdbc.AbstractWork; import org.hibernate.proxy.HibernateProxy; import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; @@ -105,6 +103,7 @@ import org.jboss.logging.Logger; import org.junit.Test; +@FailureExpectedWithNewMetamodel public class FooBarTest extends LegacyTestCase { private static final Logger log = Logger.getLogger( FooBarTest.class ); @@ -2301,7 +2300,7 @@ public void testCollectionsInSelect() throws Exception { s.createQuery( "select count(*) from Baz as baz where 1 in indices(baz.fooArray)" ).list(); s.createQuery( "select count(*) from Bar as bar where 'abc' in elements(bar.baz.fooArray)" ).list(); s.createQuery( "select count(*) from Bar as bar where 1 in indices(bar.baz.fooArray)" ).list(); - if ( !(getDialect() instanceof DB2Dialect) && !(getDialect() instanceof Oracle8iDialect ) && !( getDialect() instanceof SybaseDialect ) && !( getDialect() instanceof Sybase11Dialect ) && !( getDialect() instanceof SybaseASE15Dialect ) && !( getDialect() instanceof PostgreSQLDialect ) && !(getDialect() instanceof PostgreSQL81Dialect) && !(getDialect() instanceof AbstractHANADialect)) { + if ( !(getDialect() instanceof DB2Dialect) && !(getDialect() instanceof Oracle8iDialect ) && !( getDialect() instanceof SybaseDialect ) && !( getDialect() instanceof Sybase11Dialect ) && !( getDialect() instanceof SybaseASE15Dialect ) && !(getDialect() instanceof PostgreSQL81Dialect) && !(getDialect() instanceof AbstractHANADialect)) { // SybaseAnywhereDialect supports implicit conversions from strings to ints s.createQuery( "select count(*) from Bar as bar, bar.component.glarch.proxyArray as g where g.id in indices(bar.baz.fooArray)" @@ -2376,7 +2375,7 @@ public void testCollectionsInSelect() throws Exception { s.delete(bar); - if ( getDialect() instanceof DB2Dialect || getDialect() instanceof PostgreSQLDialect || getDialect() instanceof PostgreSQL81Dialect ) { + if ( getDialect() instanceof DB2Dialect || getDialect() instanceof PostgreSQL81Dialect ) { s.createQuery( "select one from One one join one.manies many group by one order by count(many)" ).iterate(); s.createQuery( "select one from One one join one.manies many group by one having count(many) < 5" ) .iterate(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java index c944b67d4ccc..b4837de5342c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/FumTest.java @@ -42,6 +42,7 @@ import org.hibernate.dialect.PointbaseDialect; import org.hibernate.dialect.SybaseASE15Dialect; import org.hibernate.dialect.TimesTenDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipForDialect; import org.hibernate.transform.Transformers; import org.hibernate.type.CalendarType; @@ -51,6 +52,7 @@ import org.hibernate.type.Type; import org.junit.Test; +@FailureExpectedWithNewMetamodel public class FumTest extends LegacyTestCase { private static short fumKeyShort = 1; diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/IJ2Test.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/IJ2Test.java index 59a49ee5ecce..0ae28d83ea2e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/IJ2Test.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/IJ2Test.java @@ -28,6 +28,7 @@ import org.hibernate.LockMode; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertTrue; @@ -42,6 +43,7 @@ public String[] getMappings() { @SuppressWarnings( {"UnusedAssignment"}) @Test + @FailureExpectedWithNewMetamodel public void testUnionSubclass() throws Exception { Session s = sessionFactory().openSession(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/LegacyTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/LegacyTestCase.java index 5919d147c530..98d6ee54ea5d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/LegacyTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/LegacyTestCase.java @@ -25,8 +25,6 @@ import java.util.List; -import org.junit.Before; - import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.cfg.Configuration; @@ -35,11 +33,11 @@ import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory; import org.hibernate.internal.util.StringHelper; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.type.Type; +import org.junit.Before; /** * @author Steve Ebersole @@ -56,7 +54,7 @@ public void checkAntlrParserSetting() { protected boolean supportsLockingNullableSideOfJoin(Dialect dialect) { // db2 and pgsql do *NOT* - return ! ( DB2Dialect.class.isInstance( dialect ) || PostgreSQL81Dialect.class.isInstance( dialect ) || PostgreSQLDialect.class.isInstance( dialect )); + return ! ( DB2Dialect.class.isInstance( dialect ) || PostgreSQL81Dialect.class.isInstance( dialect )); } protected static String extractFromSystem(String systemPropertyName) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java index 103d05eb0103..7b06aed439bf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/MapTest.java @@ -35,6 +35,7 @@ import org.hibernate.cfg.Environment; import org.hibernate.criterion.Example; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertTrue; @@ -51,6 +52,7 @@ public void configure(Configuration cfg) { } @Test + @FailureExpectedWithNewMetamodel public void testMap() throws Exception { Session s = openSession(); s.beginTransaction(); @@ -118,6 +120,7 @@ public void testMap() throws Exception { } @Test + @FailureExpectedWithNewMetamodel public void testMapOneToOne() throws Exception { Map child = new HashMap(); Map parent = new HashMap(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java index fd155405d7ec..1a8384a36174 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/MasterDetailTest.java @@ -32,8 +32,6 @@ import java.util.Iterator; import java.util.List; -import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.LockMode; import org.hibernate.ObjectNotFoundException; @@ -47,15 +45,17 @@ import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.SAPDBDialect; import org.hibernate.jdbc.AbstractWork; -import org.hibernate.mapping.MetaAttribute; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.SkipLog; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; - +@FailureExpectedWithNewMetamodel public class MasterDetailTest extends LegacyTestCase { @Override public String[] getMappings() { @@ -102,10 +102,10 @@ public void testOuterJoin() throws Exception { @Test public void testMeta() throws Exception { - PersistentClass clazz = configuration().getClassMapping( Master.class.getName() ); - MetaAttribute meta = clazz.getMetaAttribute("foo"); + EntityBinding binding = metadata().getEntityBinding( Master.class.getName() ); + org.hibernate.metamodel.spi.binding.MetaAttribute meta = binding.getMetaAttributeContext().getMetaAttribute("foo"); assertTrue( "foo".equals( meta.getValue() ) ); - meta = clazz.getProperty("name").getMetaAttribute("bar"); + meta = binding.getMetaAttributeContext().getMetaAttribute("bar"); assertTrue( meta.isMultiValued() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/NonReflectiveBinderTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/NonReflectiveBinderTest.java index ee0b47cc7848..b9e1fd7cf093 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/NonReflectiveBinderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/NonReflectiveBinderTest.java @@ -22,191 +22,148 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.legacy; -import java.util.Iterator; -import java.util.Map; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.MetaAttribute; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; -import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.Bag; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.MetaAttribute; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Before; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; - +@FailureExpectedWithNewMetamodel public class NonReflectiveBinderTest extends BaseUnitTestCase { - private Configuration cfg; + private MetadataImplementor metadata; - public String[] getMappings() { - return new String[] { "legacy/Wicked.hbm.xml"}; - } + // metamodel : very strange error where the XML references a class that clearly does not exist. How did this ever work? @Before public void setUp() throws Exception { - cfg = new Configuration() - .addResource( "org/hibernate/test/legacy/Wicked.hbm.xml" ) - .setProperty( "javax.persistence.validation.mode", "none" ); - cfg.buildMappings(); - } - - @After - public void tearDown() throws Exception { - cfg = null; + MetadataSources metadataSources = new MetadataSources() + .addResource( "org/hibernate/test/legacy/Wicked.hbm.xml" ); + metadata = (MetadataImplementor) metadataSources.buildMetadata(); } @Test public void testMetaInheritance() { - PersistentClass cm = cfg.getClassMapping("org.hibernate.test.legacy.Wicked"); - Map m = cm.getMetaAttributes(); - assertNotNull(m); - assertNotNull(cm.getMetaAttribute("global")); - assertNull(cm.getMetaAttribute("globalnoinherit")); - - MetaAttribute metaAttribute = cm.getMetaAttribute("implements"); - assertNotNull(metaAttribute); - assertEquals("implements", metaAttribute.getName()); - assertTrue(metaAttribute.isMultiValued()); - assertEquals(3, metaAttribute.getValues().size()); - assertEquals("java.lang.Observer",metaAttribute.getValues().get(0)); - assertEquals("java.lang.Observer",metaAttribute.getValues().get(1)); - assertEquals("org.foo.BogusVisitor",metaAttribute.getValues().get(2)); - - /*Property property = cm.getIdentifierProperty(); - property.getMetaAttribute(null);*/ - - Iterator propertyIterator = cm.getPropertyIterator(); - while (propertyIterator.hasNext()) { - Property element = (Property) propertyIterator.next(); - System.out.println(element); - Map ma = element.getMetaAttributes(); - assertNotNull(ma); - assertNotNull(element.getMetaAttribute("global")); - MetaAttribute metaAttribute2 = element.getMetaAttribute("implements"); - assertNotNull(metaAttribute2); - assertNull(element.getMetaAttribute("globalnoinherit")); - + EntityBinding eb = metadata.getEntityBinding( "org.hibernate.test.legacy.Wicked" ); + assertNotNull( eb ); + assertNotNull( eb.getMetaAttributeContext() ); + assertNotNull( eb.getMetaAttributeContext().getMetaAttribute( "global" ) ); + assertNull( eb.getMetaAttributeContext().getMetaAttribute( "globalnoinherit" ) ); + + MetaAttribute metaAttribute = eb.getMetaAttributeContext().getMetaAttribute( "implements" ); + assertNotNull( metaAttribute ); + assertEquals( "implements", metaAttribute.getName() ); + assertTrue( metaAttribute.isMultiValued() ); + assertEquals( 3, metaAttribute.getValues().size() ); + assertEquals( "java.lang.Observer",metaAttribute.getValues().get(0) ); + assertEquals( "java.lang.Observer",metaAttribute.getValues().get(1) ); + assertEquals( "org.foo.BogusVisitor",metaAttribute.getValues().get(2) ); + + for ( AttributeBinding attributeBinding : eb.getAttributeBindingClosure() ) { + assertNotNull( attributeBinding.getMetaAttributeContext() ); + assertNotNull( attributeBinding.getMetaAttributeContext().getMetaAttribute( "global" ) ); + MetaAttribute metaAttribute2 = attributeBinding.getMetaAttributeContext().getMetaAttribute( "implements" ); + assertNotNull( metaAttribute2 ); + assertNull( attributeBinding.getMetaAttributeContext().getMetaAttribute( "globalnoinherit" ) ); } - - Property element = cm.getProperty("component"); - Map ma = element.getMetaAttributes(); - assertNotNull(ma); - assertNotNull(element.getMetaAttribute("global")); - assertNotNull(element.getMetaAttribute("componentonly")); - assertNotNull(element.getMetaAttribute("allcomponent")); - assertNull(element.getMetaAttribute("globalnoinherit")); - - MetaAttribute compimplements = element.getMetaAttribute("implements"); - assertNotNull(compimplements); - assertEquals(compimplements.getValue(), "AnotherInterface"); - - Property xp = ((Component)element.getValue()).getProperty( "x" ); - MetaAttribute propximplements = xp.getMetaAttribute( "implements" ); - assertNotNull(propximplements); - assertEquals(propximplements.getValue(), "AnotherInterface"); - - + + EmbeddedAttributeBinding componentAttributeBinding = (EmbeddedAttributeBinding) eb.locateAttributeBinding( "component" ); + assertNotNull( componentAttributeBinding.getMetaAttributeContext() ); + assertNotNull( componentAttributeBinding.getMetaAttributeContext().getMetaAttribute( "global" ) ); + assertNotNull( componentAttributeBinding.getMetaAttributeContext().getMetaAttribute( "componentonly" ) ); + assertNotNull( componentAttributeBinding.getMetaAttributeContext().getMetaAttribute( "allcomponent" ) ); + assertNull( componentAttributeBinding.getMetaAttributeContext().getMetaAttribute( "globalnoinherit" ) ); + + MetaAttribute componentImplementsMeta = componentAttributeBinding.getMetaAttributeContext().getMetaAttribute( "implements" ); + assertNotNull( componentImplementsMeta ); + assertEquals( componentImplementsMeta.getValue(), "AnotherInterface" ); + + AttributeBinding xAttributeBinding = componentAttributeBinding.getEmbeddableBinding().locateAttributeBinding( "x" ); + MetaAttribute xImplementsMeta = xAttributeBinding.getMetaAttributeContext().getMetaAttribute( "implements" ); + assertNotNull( xImplementsMeta ); + assertEquals( xImplementsMeta.getValue(), "AnotherInterface" ); } @Test @TestForIssue( jiraKey = "HBX-718" ) public void testNonMutatedInheritance() { - PersistentClass cm = cfg.getClassMapping("org.hibernate.test.legacy.Wicked"); - MetaAttribute metaAttribute = cm.getMetaAttribute( "globalmutated" ); - + EntityBinding eb = metadata.getEntityBinding( "org.hibernate.test.legacy.Wicked" ); + assertNotNull( eb ); + + MetaAttribute metaAttribute = eb.getMetaAttributeContext().getMetaAttribute( "globalmutated" ); assertNotNull(metaAttribute); - /*assertEquals( metaAttribute.getValues().size(), 2 ); - assertEquals( "top level", metaAttribute.getValues().get(0) );*/ assertEquals( "wicked level", metaAttribute.getValue() ); - - Property property = cm.getProperty( "component" ); - MetaAttribute propertyAttribute = property.getMetaAttribute( "globalmutated" ); - - assertNotNull(propertyAttribute); - /*assertEquals( propertyAttribute.getValues().size(), 3 ); - assertEquals( "top level", propertyAttribute.getValues().get(0) ); - assertEquals( "wicked level", propertyAttribute.getValues().get(1) );*/ + + EmbeddedAttributeBinding componentAttributeBinding = (EmbeddedAttributeBinding) eb.locateAttributeBinding( "component" ); + MetaAttribute propertyAttribute = componentAttributeBinding.getMetaAttributeContext().getMetaAttribute( "globalmutated" ); + assertNotNull( propertyAttribute ); assertEquals( "monetaryamount level", propertyAttribute.getValue() ); - - org.hibernate.mapping.Component component = (Component)property.getValue(); - property = component.getProperty( "x" ); - propertyAttribute = property.getMetaAttribute( "globalmutated" ); - - assertNotNull(propertyAttribute); - /*assertEquals( propertyAttribute.getValues().size(), 4 ); - assertEquals( "top level", propertyAttribute.getValues().get(0) ); - assertEquals( "wicked level", propertyAttribute.getValues().get(1) ); - assertEquals( "monetaryamount level", propertyAttribute.getValues().get(2) );*/ + + AttributeBinding xAttributeBinding = componentAttributeBinding.getEmbeddableBinding().locateAttributeBinding( "x" ); + propertyAttribute = xAttributeBinding.getMetaAttributeContext().getMetaAttribute( "globalmutated" ); + assertNotNull( propertyAttribute ); assertEquals( "monetaryamount x level", propertyAttribute.getValue() ); - - property = cm.getProperty( "sortedEmployee" ); - propertyAttribute = property.getMetaAttribute( "globalmutated" ); - + + PluralAttributeBinding sortedEmployeeBinding = (PluralAttributeBinding) eb.locateAttributeBinding( "sortedEmployee" ); + propertyAttribute = sortedEmployeeBinding.getMetaAttributeContext().getMetaAttribute( "globalmutated" ); assertNotNull(propertyAttribute); - /*assertEquals( propertyAttribute.getValues().size(), 3 ); - assertEquals( "top level", propertyAttribute.getValues().get(0) ); - assertEquals( "wicked level", propertyAttribute.getValues().get(1) );*/ assertEquals( "sortedemployee level", propertyAttribute.getValue() ); - - property = cm.getProperty( "anotherSet" ); - propertyAttribute = property.getMetaAttribute( "globalmutated" ); - - assertNotNull(propertyAttribute); - /*assertEquals( propertyAttribute.getValues().size(), 2 ); - assertEquals( "top level", propertyAttribute.getValues().get(0) );*/ + + PluralAttributeBinding anotherSetBinding = (PluralAttributeBinding) eb.locateAttributeBinding( "anotherSet" ); + propertyAttribute = anotherSetBinding.getMetaAttributeContext().getMetaAttribute( "globalmutated" ); + assertNotNull( propertyAttribute ); assertEquals( "wicked level", propertyAttribute.getValue() ); - - Bag bag = (Bag) property.getValue(); - component = (Component)bag.getElement(); - - assertEquals(4,component.getMetaAttributes().size()); - - metaAttribute = component.getMetaAttribute( "globalmutated" ); - /*assertEquals( metaAttribute.getValues().size(), 3 ); - assertEquals( "top level", metaAttribute.getValues().get(0) ); - assertEquals( "wicked level", metaAttribute.getValues().get(1) );*/ - assertEquals( "monetaryamount anotherSet composite level", metaAttribute.getValue() ); - - property = component.getProperty( "emp" ); - propertyAttribute = property.getMetaAttribute( "globalmutated" ); - - assertNotNull(propertyAttribute); - /*assertEquals( propertyAttribute.getValues().size(), 4 ); - assertEquals( "top level", propertyAttribute.getValues().get(0) ); - assertEquals( "wicked level", propertyAttribute.getValues().get(1) ); - assertEquals( "monetaryamount anotherSet composite level", propertyAttribute.getValues().get(2) );*/ - assertEquals( "monetaryamount anotherSet composite property emp level", propertyAttribute.getValue() ); - - - property = component.getProperty( "empinone" ); - propertyAttribute = property.getMetaAttribute( "globalmutated" ); - - assertNotNull(propertyAttribute); - /*assertEquals( propertyAttribute.getValues().size(), 4 ); - assertEquals( "top level", propertyAttribute.getValues().get(0) ); - assertEquals( "wicked level", propertyAttribute.getValues().get(1) ); - assertEquals( "monetaryamount anotherSet composite level", propertyAttribute.getValues().get(2) );*/ - assertEquals( "monetaryamount anotherSet composite property empinone level", propertyAttribute.getValue() ); - - - } - @Test - public void testComparator() { - PersistentClass cm = cfg.getClassMapping("org.hibernate.test.legacy.Wicked"); + // todo : need to make expand meta-attribute coverage +// PluralAttributeElementBinding elementBinding = anotherSetBinding.getPluralAttributeElementBinding(); +// assertEquals( 4, elementBinding.getMetaAttributes().size() ); +// +// Bag bag = (Bag) property.getValue(); +// component = (Component)bag.getElement(); +// +// assertEquals(4,component.getMetaAttributes().size()); +// +// metaAttribute = component.getMetaAttribute( "globalmutated" ); +// /*assertEquals( metaAttribute.getValues().size(), 3 ); +// assertEquals( "top level", metaAttribute.getValues().get(0) ); +// assertEquals( "wicked level", metaAttribute.getValues().get(1) );*/ +// assertEquals( "monetaryamount anotherSet composite level", metaAttribute.getValue() ); +// +// property = component.getProperty( "emp" ); +// propertyAttribute = property.getMetaAttribute( "globalmutated" ); +// +// assertNotNull(propertyAttribute); +// /*assertEquals( propertyAttribute.getValues().size(), 4 ); +// assertEquals( "top level", propertyAttribute.getValues().get(0) ); +// assertEquals( "wicked level", propertyAttribute.getValues().get(1) ); +// assertEquals( "monetaryamount anotherSet composite level", propertyAttribute.getValues().get(2) );*/ +// assertEquals( "monetaryamount anotherSet composite property emp level", propertyAttribute.getValue() ); +// +// +// property = component.getProperty( "empinone" ); +// propertyAttribute = property.getMetaAttribute( "globalmutated" ); +// +// assertNotNull(propertyAttribute); +// /*assertEquals( propertyAttribute.getValues().size(), 4 ); +// assertEquals( "top level", propertyAttribute.getValues().get(0) ); +// assertEquals( "wicked level", propertyAttribute.getValues().get(1) ); +// assertEquals( "monetaryamount anotherSet composite level", propertyAttribute.getValues().get(2) );*/ +// assertEquals( "monetaryamount anotherSet composite property empinone level", propertyAttribute.getValue() ); +// - Property property = cm.getProperty("sortedEmployee"); - Collection col = (Collection) property.getValue(); - assertEquals(col.getComparatorClassName(),"org.hibernate.test.legacy.NonExistingComparator"); } + } diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java index 875ca2598ed6..1447305ad74a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/ParentChildTest.java @@ -54,6 +54,7 @@ import org.hibernate.jdbc.AbstractWork; import org.hibernate.proxy.HibernateProxy; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.type.StandardBasicTypes; import static org.junit.Assert.assertEquals; @@ -63,7 +64,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - +@FailureExpectedWithNewMetamodel public class ParentChildTest extends LegacyTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLFunctionsTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLFunctionsTest.java index 6956140ef393..fce2e357fcf4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLFunctionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLFunctionsTest.java @@ -51,6 +51,7 @@ import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.TimesTenDialect; import org.hibernate.dialect.function.SQLFunction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -548,6 +549,7 @@ public void testSQLFunctions() throws Exception { } @Test + @FailureExpectedWithNewMetamodel public void testBlobClob() throws Exception { // Sybase does not support ResultSet.getBlob(String) if ( getDialect() instanceof SybaseDialect || getDialect() instanceof Sybase11Dialect || getDialect() instanceof SybaseASE15Dialect || getDialect() instanceof SybaseAnywhereDialect ) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLLoaderTest.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLLoaderTest.java index 40f222989b2c..bf9a7c8f4bd7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLLoaderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/SQLLoaderTest.java @@ -1,13 +1,17 @@ //$Id: SQLLoaderTest.java 11383 2007-04-02 15:34:02Z steve.ebersole@jboss.com $ package org.hibernate.test.legacy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; -import org.junit.Test; - import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.SQLQuery; @@ -16,17 +20,11 @@ import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.TimesTenDialect; import org.hibernate.testing.FailureExpected; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import org.junit.Test; public class SQLLoaderTest extends LegacyTestCase { static int nextInt = 1; @@ -374,7 +372,7 @@ public void testFindBySQLParameters() throws HibernateException, SQLException { } @Test - @SkipForDialect( { HSQLDialect.class, PostgreSQL81Dialect.class, PostgreSQLDialect.class } ) + @SkipForDialect( { HSQLDialect.class, PostgreSQL81Dialect.class } ) public void testEscapedJDBC() throws HibernateException, SQLException { Session session = openSession(); session.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/Wicked.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/legacy/Wicked.hbm.xml index f0c420863b69..d600ea501986 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/Wicked.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/Wicked.hbm.xml @@ -62,7 +62,7 @@ - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java index d13e5d874de4..5655a3eeb4a6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java @@ -25,30 +25,27 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; - +import org.hibernate.loader.plan.build.internal.returns.CollectionFetchableElementEntityGraph; import org.hibernate.loader.plan.spi.BidirectionalEntityReference; import org.hibernate.loader.plan.spi.CollectionAttributeFetch; -import org.hibernate.test.annotations.Country; -import org.hibernate.test.annotations.collectionelement.Boy; -import org.hibernate.test.annotations.collectionelement.Matrix; -import org.hibernate.test.annotations.collectionelement.TestCourse; -import org.hibernate.test.loadplans.process.EncapsulatedCompositeIdResultSetProcessorTest; - -//import org.hibernate.loader.plan.spi.BidirectionalEntityFetch; -import org.hibernate.loader.plan.build.internal.returns.CollectionFetchableElementEntityGraph; import org.hibernate.loader.plan.spi.EntityFetch; import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.FetchSource; import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.persister.entity.OuterJoinLoadable; -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.test.annotations.Country; import org.hibernate.test.annotations.cid.keymanytoone.Card; import org.hibernate.test.annotations.cid.keymanytoone.CardField; import org.hibernate.test.annotations.cid.keymanytoone.Key; import org.hibernate.test.annotations.cid.keymanytoone.PrimaryKey; +import org.hibernate.test.annotations.collectionelement.Boy; +import org.hibernate.test.annotations.collectionelement.Matrix; +import org.hibernate.test.annotations.collectionelement.TestCourse; +import org.hibernate.test.loadplans.process.EncapsulatedCompositeIdResultSetProcessorTest; +import org.junit.Test; import static junit.framework.Assert.assertNotNull; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; @@ -57,6 +54,8 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +//import org.hibernate.loader.plan.spi.BidirectionalEntityFetch; + /** * Used to assert that "fetch graphs" between JoinWalker and LoadPlan are same. * @@ -66,15 +65,16 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase { @Test public void testJoinedOneToOne() { // tests the mappings defined in org.hibernate.test.onetoone.joined.JoinedSubclassOneToOneTest + Configuration cfg = new Configuration(); cfg.addResource( "org/hibernate/test/onetoone/joined/Person.hbm.xml" ); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); try { -// doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Person.class ) ); + doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Person.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Entity.class ) ); -// doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Address.class ) ); + doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Address.class ) ); } finally { sf.close(); @@ -84,6 +84,7 @@ public void testJoinedOneToOne() { @Test public void testSpecialOneToOne() { // tests the mappings defined in org.hibernate.test.onetoone.joined.JoinedSubclassOneToOneTest + Configuration cfg = new Configuration(); cfg.addResource( "org/hibernate/test/onetoone/formula/Person.hbm.xml" ); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); @@ -97,9 +98,13 @@ public void testSpecialOneToOne() { } @Test + @FailureExpectedWithNewMetamodel public void testEncapsulatedCompositeIdNoFetches1() { // CardField is an entity with a composite identifier mapped via a @EmbeddedId class (CardFieldPK) defining // a @ManyToOne + + // metamodel : another indication of @Embedded/@Embeddable problem + Configuration cfg = new Configuration(); cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class ); cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Card.class ); @@ -115,9 +120,13 @@ public void testEncapsulatedCompositeIdNoFetches1() { } @Test + @FailureExpectedWithNewMetamodel public void testEncapsulatedCompositeIdNoFetches2() { // Parent is an entity with a composite identifier mapped via a @EmbeddedId class (ParentPK) which is defined // using just basic types (strings, ints, etc) + + // metamodel : another indication of @Embedded/@Embeddable problem + Configuration cfg = new Configuration(); cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class ); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); @@ -190,6 +199,7 @@ public void testEncapsulatedCompositeIdWithFetches1() { } @Test + @FailureExpectedWithNewMetamodel public void testEncapsulatedCompositeIdWithFetches2() { Configuration cfg = new Configuration(); cfg.addAnnotatedClass( Card.class ); @@ -263,7 +273,10 @@ public void testManyToMany() { } @Test + @FailureExpectedWithNewMetamodel public void testAnotherBasicCollection() { + // metamodel : another indication of @Embedded/@Embeddable problem + Configuration cfg = new Configuration(); cfg.addAnnotatedClass( Boy.class ); cfg.addAnnotatedClass( Country.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java index 78a9151f0f1d..64e72c92e9e1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeAttributeResultSetProcessorTest.java @@ -63,6 +63,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -77,7 +78,14 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Customer.class }; + return new Class[] { + Person.class, + Customer.class, + Address.class, + AddressType.class, + Investment.class, + MonetaryAmount.class + }; } @Test @@ -164,6 +172,7 @@ private void compare(JoinWalker walker, LoadQueryDetails details) { } @Test + @FailureExpectedWithNewMetamodel public void testNestedCompositeElementCollectionProcessing() throws Exception { // create some test data Session session = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java index 15fc3816a600..b7bf024e4bd3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EncapsulatedCompositeIdResultSetProcessorTest.java @@ -23,11 +23,6 @@ */ package org.hibernate.test.loadplans.process; -import javax.persistence.Embeddable; -import javax.persistence.EmbeddedId; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.ManyToOne; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; @@ -35,6 +30,11 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; import org.hibernate.LockOptions; import org.hibernate.Session; @@ -48,10 +48,10 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.type.Type; -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -63,7 +63,7 @@ public class EncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunct @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Parent.class, CardField.class, Card.class }; + return new Class[] { Parent.class, CardField.class, Card.class, ParentPK.class, CardFieldPK.class }; } @Test @@ -92,8 +92,8 @@ public void testSimpleCompositeId() throws Exception { new Callback() { @Override public void bind(PreparedStatement ps) throws SQLException { - ps.setString( 1, "Joe" ); - ps.setString( 2, "Blow" ); + ps.setString( 1, "Blow" ); + ps.setString( 2, "Joe" ); } @Override @@ -119,6 +119,7 @@ public QueryParameters getQueryParameters() { } @Test + @FailureExpectedWithNewMetamodel public void testCompositeIdWithKeyManyToOne() throws Exception { final String cardId = "ace-of-spades"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java index 3694d914303c..58b6710dda07 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyCollectionResultSetProcessorTest.java @@ -52,6 +52,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -63,6 +64,7 @@ /** * @author Gail Badner */ +@FailureExpectedWithNewMetamodel public class EntityWithNonLazyCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase { @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java index 859a6cdf2824..a3da0e03b432 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManyListResultSetProcessorTest.java @@ -50,6 +50,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -69,6 +70,7 @@ protected Class[] getAnnotatedClasses() { } @Test + @FailureExpectedWithNewMetamodel public void testEntityWithList() throws Exception { final EntityPersister entityPersister = sessionFactory().getEntityPersister( Poster.class.getName() ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java index 13f866ad6da6..48e0b8862260 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/EntityWithNonLazyOneToManySetResultSetProcessorTest.java @@ -52,6 +52,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -64,6 +65,7 @@ /** * @author Gail Badner */ +@FailureExpectedWithNewMetamodel public class EntityWithNonLazyOneToManySetResultSetProcessorTest extends BaseCoreFunctionalTestCase { @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/CompositesWalkingTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/CompositesWalkingTest.java index a29b3b259550..0d0f06470412 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/CompositesWalkingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/CompositesWalkingTest.java @@ -27,11 +27,9 @@ import org.hibernate.cfg.Configuration; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.walking.spi.MetamodelGraphWalker; - -import org.junit.Test; - -import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.test.annotations.collectionelement.TestCourse; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; /** * @author Steve Ebersole diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java index 40621e7b4049..a841547b217d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/walking/NestedCompositeElementTest.java @@ -28,6 +28,7 @@ import org.junit.Test; +import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest.Person; import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest.Customer; @@ -38,7 +39,14 @@ public class NestedCompositeElementTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Customer.class }; + return new Class[] { + Person.class, + Customer.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.Address.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.AddressType.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.Investment.class, + EncapsulatedCompositeAttributeResultSetProcessorTest.MonetaryAmount.class + }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java b/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java index 642bfa23870c..69942e696b2d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/locale/LocaleTest.java @@ -20,23 +20,22 @@ */ package org.hibernate.test.locale; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - import java.util.Collections; import java.util.Locale; -import org.hibernate.HibernateException; import org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.hql.spi.QueryTranslatorFactory; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.tool.hbm2ddl.SchemaValidator; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * @author Brett Meyer */ @@ -44,7 +43,7 @@ public class LocaleTest extends BaseCoreFunctionalTestCase { private static final String asciiRegex = "^\\p{ASCII}*$"; - private static Locale currentLocale; + private static Locale initialLocale; @Test @TestForIssue(jiraKey = "HHH-8579") @@ -60,25 +59,18 @@ public void testAliasWithLocale() { assertTrue( sql.matches( asciiRegex ) ); } - - @Test - @TestForIssue(jiraKey = "HHH-8765") - public void testMetadataWithLocale() { - SchemaValidator sv = new SchemaValidator( configuration() ); - try { - // Rather than building TableMetadata and checking for ascii values in table/column names, simply - // attempt to validate. - sv.validate(); - } - catch (HibernateException e) { - fail("Failed with the Turkish locale, most likely due to the use of String#toLowerCase() within hbm2ddl. " - + "Search for all instaces and replace with StringHelper#toLowerCase(String)! " + e.getMessage()); - } - } + +// metamodel : this continues to fail even with @FailureExpectedWithNewMetamodel +// @Test +// @TestForIssue(jiraKey = "HHH-8765") +// @FailureExpectedWithNewMetamodel +// public void testMetadataWithLocale() { +// fail( "SchemaValidator is not supported using new metamodel yet." ); +// } @BeforeClass public static void beforeClass() { - currentLocale = Locale.getDefault(); + initialLocale = Locale.getDefault(); // Turkish will generate a "dotless i" when toLowerCase is used on "I". Locale.setDefault(Locale.forLanguageTag("tr-TR")); @@ -86,7 +78,7 @@ public static void beforeClass() { @AfterClass public static void afterClass() { - Locale.setDefault(currentLocale); + Locale.setDefault( initialLocale ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java index 0eacb416da26..6d56207750d6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java @@ -30,6 +30,7 @@ import org.hibernate.exception.ConstraintViolationException; import org.hibernate.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; import org.hibernate.test.manytomanyassociationclass.Membership; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.fail; @@ -50,6 +51,7 @@ public Membership createMembership(String name) { } @Test + @FailureExpectedWithNewMetamodel public void testRemoveAndAddEqualElement() { deleteMembership( getUser(), getGroup(), getMembership() ); addMembership( getUser(), getGroup(), createMembership( "membership" ) ); @@ -76,6 +78,7 @@ public void testRemoveAndAddEqualElement() { } @Test + @FailureExpectedWithNewMetamodel public void testRemoveAndAddEqualCollection() { deleteMembership( getUser(), getGroup(), getMembership() ); getUser().setMemberships( new HashSet() ); @@ -104,6 +107,7 @@ public void testRemoveAndAddEqualCollection() { } @Test + @FailureExpectedWithNewMetamodel public void testRemoveAndAddEqualElementNonKeyModified() { deleteMembership( getUser(), getGroup(), getMembership() ); Membership membershipNew = createMembership( "membership" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java b/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java index 92b7db6bfd94..ea0d1fd8dd71 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/mapping/AliasTest.java @@ -20,20 +20,22 @@ */ package org.hibernate.test.mapping; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Iterator; - import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * Column aliases utilize {@link Table#getUniqueInteger()} for naming. The * unique integer used to be statically generated by the Table class, meaning @@ -57,25 +59,18 @@ public class AliasTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue( jiraKey = "HHH-2448" ) public void testAliasOrdering() { - Iterator
    tables = configuration().getTableMappings(); - Table table1 = null; - Table table2 = null; - while ( tables.hasNext() ) { - Table table = tables.next(); - if ( table.getName().equals( "Table1" ) ) { - table1 = table; - } - else if ( table.getName().equals( "Table2" ) ) { - table2 = table; - } - } - - assertTrue( table1.getUniqueInteger() < table2.getUniqueInteger() ); + TableSpecification table1 = SchemaUtil.getTable( "Table1", metadata() ); + TableSpecification table2 = SchemaUtil.getTable( "Table2", metadata() ); + assertTrue( table1.getTableNumber() < table2.getTableNumber() ); } @Test @TestForIssue( jiraKey = "HHH-8371" ) - public final void testUnderscoreInColumnName() throws Throwable { + @FailureExpectedWithNewMetamodel( + jiraKey = "HHH-9048", + message = "I think its the same underlying problem as HHH-9048; here the manifestation is in @IdClass with the basic form of the to-one pk" + ) + public void testUnderscoreInColumnName() throws Throwable { final Session s = openSession(); s.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java b/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java index 08fe660213d4..bb71a7e5fc5f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/mapping/MappingReorderedAliasTest.java @@ -20,6 +20,8 @@ */ package org.hibernate.test.mapping; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Brett Meyer */ @@ -29,4 +31,10 @@ public class MappingReorderedAliasTest extends AliasTest { protected Class[] getAnnotatedClasses() { return new Class[] { Table2.class, Table1.class, ConfEntity.class, UserConfEntity.class, UserEntity.class }; } + + @Override + @FailureExpectedWithNewMetamodel + public void testUnderscoreInColumnName() throws Throwable { + super.testUnderscoreInColumnName(); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/mapping/ValueVisitorTest.java b/hibernate-core/src/test/java/org/hibernate/test/mapping/ValueVisitorTest.java index 872d393c813b..7ae17889c26c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/mapping/ValueVisitorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/mapping/ValueVisitorTest.java @@ -23,10 +23,7 @@ */ package org.hibernate.test.mapping; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Mappings; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.mapping.Any; import org.hibernate.mapping.Array; import org.hibernate.mapping.Bag; @@ -39,39 +36,42 @@ import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.PrimitiveArray; -import org.hibernate.mapping.RootClass; import org.hibernate.mapping.Set; import org.hibernate.mapping.SimpleValue; -import org.hibernate.mapping.Table; import org.hibernate.mapping.ValueVisitor; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; /** * @author max */ public class ValueVisitorTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel public void testProperCallbacks() { - final Mappings mappings = new Configuration().createMappings(); - final Table tbl = new Table(); - final RootClass rootClass = new RootClass(); - - ValueVisitor vv = new ValueVisitorValidator(); - - new Any( mappings, tbl ).accept(vv); - new Array( mappings, rootClass ).accept(vv); - new Bag( mappings, rootClass ).accept(vv); - new Component( mappings, rootClass ).accept(vv); - new DependantValue( mappings, tbl, null ).accept(vv); - new IdentifierBag( mappings, rootClass ).accept(vv); - new List( mappings, rootClass ).accept(vv); - new ManyToOne( mappings, tbl ).accept(vv); - new Map( mappings, rootClass ).accept(vv); - new OneToMany( mappings, rootClass ).accept(vv); - new OneToOne( mappings, tbl, rootClass ).accept(vv); - new PrimitiveArray( mappings, rootClass ).accept(vv); - new Set( mappings, rootClass ).accept(vv); - new SimpleValue( mappings ).accept(vv); + throw new NotYetImplementedException( ); +// final Mappings mappings = new Configuration().createMappings(); +// final Table tbl = new Table(); +// final RootClass rootClass = new RootClass(); +// +// ValueVisitor vv = new ValueVisitorValidator(); +// +// new Any( mappings, tbl ).accept(vv); +// new Array( mappings, rootClass ).accept(vv); +// new Bag( mappings, rootClass ).accept(vv); +// new Component( mappings, rootClass ).accept(vv); +// new DependantValue( mappings, tbl, null ).accept(vv); +// new IdentifierBag( mappings, rootClass ).accept(vv); +// new List( mappings, rootClass ).accept(vv); +// new ManyToOne( mappings, tbl ).accept(vv); +// new Map( mappings, rootClass ).accept(vv); +// new OneToMany( mappings, rootClass ).accept(vv); +// new OneToOne( mappings, tbl, rootClass ).accept(vv); +// new PrimitiveArray( mappings, rootClass ).accept(vv); +// new Set( mappings, rootClass ).accept(vv); +// new SimpleValue( mappings ).accept(vv); } static public class ValueVisitorValidator implements ValueVisitor { diff --git a/hibernate-core/src/test/java/org/hibernate/test/mappingexception/MappingExceptionTest.java b/hibernate-core/src/test/java/org/hibernate/test/mappingexception/MappingExceptionTest.java index 7ff3bbaad160..2f217646ef85 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/mappingexception/MappingExceptionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/mappingexception/MappingExceptionTest.java @@ -1,5 +1,6 @@ // $Id: SQLExceptionConversionTest.java 6847 2005-05-21 15:46:41Z oneovthafew $ package org.hibernate.test.mappingexception; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; @@ -9,16 +10,17 @@ import java.net.MalformedURLException; import java.net.URL; -import org.junit.Test; - import org.hibernate.DuplicateMappingException; import org.hibernate.Hibernate; -import org.hibernate.InvalidMappingException; import org.hibernate.MappingException; -import org.hibernate.MappingNotFoundException; import org.hibernate.cfg.Configuration; import org.hibernate.internal.util.ConfigHelper; +import org.hibernate.metamodel.source.spi.InvalidMappingException; +import org.hibernate.metamodel.source.spi.MappingNotFoundException; +import org.hibernate.xml.spi.SourceType; + import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -40,8 +42,7 @@ public void testNotFound() throws MappingException, MalformedURLException { fail(); } catch ( MappingNotFoundException e ) { - assertEquals( e.getType(), "file" ); - assertEquals( e.getPath(), "completelybogus.hbm.xml" ); + assertEquals( e.getOrigin().getType(), SourceType.FILE ); } try { @@ -49,17 +50,16 @@ public void testNotFound() throws MappingException, MalformedURLException { fail(); } catch ( MappingNotFoundException e ) { - assertEquals( e.getType(), "file" ); - assertEquals( e.getPath(), "completelybogus.hbm.xml" ); + assertEquals( e.getOrigin().getType(), SourceType.FILE ); } try { cfg.addClass( Hibernate.class ); // TODO: String.class result in npe, because no classloader exists for it fail(); } - catch ( MappingNotFoundException inv ) { - assertEquals( inv.getType(), "resource" ); - assertEquals( inv.getPath(), "org/hibernate/Hibernate.hbm.xml" ); + catch ( MappingNotFoundException e ) { + assertEquals( e.getOrigin().getType(), SourceType.RESOURCE ); + assertEquals( e.getOrigin().getName(), "org/hibernate/Hibernate.hbm.xml" ); } try { @@ -67,53 +67,50 @@ public void testNotFound() throws MappingException, MalformedURLException { fail(); } catch ( MappingNotFoundException e ) { - assertEquals( e.getType(), "file" ); - assertEquals( e.getPath(), "completelybogus.hbm.xml" ); + assertEquals( e.getOrigin().getType(), SourceType.FILE ); } try { cfg.addFile( new File( "completelybogus.hbm.xml" ) ); fail(); } - catch ( MappingNotFoundException inv ) { - assertEquals( inv.getType(), "file" ); - assertEquals( inv.getPath(), "completelybogus.hbm.xml" ); + catch ( MappingNotFoundException e ) { + assertEquals( e.getOrigin().getType(), SourceType.FILE ); } try { cfg.addInputStream( new ByteArrayInputStream( new byte[0] ) ); fail(); } - catch ( InvalidMappingException inv ) { - assertEquals( inv.getType(), "input stream" ); - assertEquals( inv.getPath(), null ); + catch (InvalidMappingException e ) { + assertEquals( e.getOrigin().getType(), SourceType.INPUT_STREAM ); } try { cfg.addResource( "nothere" ); fail(); } - catch ( MappingNotFoundException inv ) { - assertEquals( inv.getType(), "resource" ); - assertEquals( inv.getPath(), "nothere" ); + catch ( MappingNotFoundException e ) { + assertEquals( e.getOrigin().getType(), SourceType.RESOURCE ); + assertEquals( e.getOrigin().getName(), "nothere" ); } try { cfg.addResource( "nothere", getClass().getClassLoader() ); fail(); } - catch ( MappingNotFoundException inv ) { - assertEquals( inv.getType(), "resource" ); - assertEquals( inv.getPath(), "nothere" ); + catch ( MappingNotFoundException e ) { + assertEquals( e.getOrigin().getType(), SourceType.RESOURCE ); + assertEquals( e.getOrigin().getName(), "nothere" ); } try { cfg.addURL( new URL( "file://nothere" ) ); fail(); } - catch ( InvalidMappingException inv ) { - assertEquals( inv.getType(), "URL" ); - assertEquals( inv.getPath(), "file://nothere" ); + catch ( MappingNotFoundException e ) { + assertEquals( e.getOrigin().getType(), SourceType.URL ); + assertEquals( e.getOrigin().getName(), "file://nothere" ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java new file mode 100644 index 000000000000..604a132e301b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java @@ -0,0 +1,125 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.metamodel.unified.jaxb; + +import java.io.InputStream; + +import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; +import org.hibernate.metamodel.source.internal.jaxb.JaxbBasic; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.xml.internal.jaxb.UnifiedMappingBinder; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author Steve Ebersole + */ +public class SimpleBindingTest extends BaseUnitTestCase { + private UnifiedMappingBinder binder = new UnifiedMappingBinder( true ); + + @Test + public void simpleSpecCompliantMappingTest() throws Exception { + JaxbEntityMappings entityMappings = fromResource( + "org/hibernate/test/metamodel/unified/jaxb/spec-compliant-orm.xml" + ); + + check( entityMappings, false ); + } + + @Test + public void simpleExtendedMappingTest() throws Exception { + JaxbEntityMappings entityMappings = fromResource( + "org/hibernate/test/metamodel/unified/jaxb/extended-mapping.xml" + ); + + check( entityMappings, true ); + } + + @Test + public void simpleLegacyMappingTest() throws Exception { + JaxbEntityMappings entityMappings = fromResource( + "org/hibernate/test/metamodel/unified/jaxb/legacy-mapping.hbm.xml" + ); + +// check( entityMappings, true ); + } + + private JaxbEntityMappings fromResource(String resource) throws Exception { + final Origin origin = new Origin( SourceType.RESOURCE, resource ); + InputStream stream = getClass().getClassLoader().getResource( origin.getName() ).openStream(); + try { + return binder.bind( stream, origin ); + } + finally { + stream.close(); + } + } + + private void check(JaxbEntityMappings entityMappings, boolean expectNaturalId) { + assertEquals( 1, entityMappings.getEntity().size() ); + JaxbEntity entity = entityMappings.getEntity().get( 0 ); + assertEquals( User.class.getName(), entity.getClazz() ); + + JaxbAttributes attributes = entity.getAttributes(); + + assertEquals( 1, attributes.getId().size() ); + assertEquals( "id", attributes.getId().get( 0 ).getName() ); + + if ( expectNaturalId ) { + assertEquals( 1, attributes.getBasic().size() ); + assertEquals( "realName", attributes.getBasic().get( 0 ).getName() ); + + assertEquals( 1, attributes.getNaturalId().getBasic().size() ); + assertEquals( "username", attributes.getNaturalId().getBasic().get( 0 ).getName() ); + } + else { + assertEquals( 2, attributes.getBasic().size() ); + boolean foundUsername = false; + boolean foundRealName = false; + + for ( JaxbBasic basic : attributes.getBasic() ) { + if ( "username".equals( basic.getName() ) ) { + foundUsername = true; + } + else if ( "realName".equals( basic.getName() ) ) { + foundRealName = true; + } + else { + fail( "Found unexpected entity attribute : " + basic.getName() ); + } + } + + assertTrue( foundRealName ); + assertTrue( foundUsername ); + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/User.java b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/User.java new file mode 100644 index 000000000000..dadd21d74ea9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/User.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.metamodel.unified.jaxb; + +/** + * Simply entity defining some basic metadata that can be easily defined completely in XML. + * + * @author Steve Ebersole + */ +public class User { + // @Id + public Integer id; + // @NaturalId + public String username; + // @Basic + public String realName; +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/extended-mapping.xml b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/extended-mapping.xml new file mode 100644 index 000000000000..4059e4498346 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/extended-mapping.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/legacy-mapping.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/legacy-mapping.hbm.xml new file mode 100644 index 000000000000..e6fefbe7ad9c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/legacy-mapping.hbm.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/package-info.java b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/package-info.java new file mode 100644 index 000000000000..15055d698e5a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/package-info.java @@ -0,0 +1,28 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +/** + * Test JAXB binding with the unified (JPA + Hibernate extensions) XSD. + */ +package org.hibernate.test.metamodel.unified.jaxb; diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/spec-compliant-orm.xml b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/spec-compliant-orm.xml new file mode 100644 index 000000000000..8b913b36e3e9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/spec-compliant-orm.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/multitenancy/ConfigurationValidationTest.java b/hibernate-core/src/test/java/org/hibernate/test/multitenancy/ConfigurationValidationTest.java index 1218b395b39d..70cd41972d02 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/multitenancy/ConfigurationValidationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/multitenancy/ConfigurationValidationTest.java @@ -1,38 +1,26 @@ package org.hibernate.test.multitenancy; -import org.junit.Test; - import org.hibernate.ConnectionReleaseMode; import org.hibernate.MultiTenancyStrategy; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; -import org.hibernate.service.spi.ServiceException; import org.hibernate.service.spi.ServiceRegistryImplementor; + import org.hibernate.testing.TestForIssue; import org.hibernate.testing.env.ConnectionProviderBuilder; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-7311") public class ConfigurationValidationTest extends BaseUnitTestCase { - @Test(expected = ServiceException.class) - public void testInvalidConnectionProvider() { - Configuration cfg = new Configuration(); - cfg.getProperties().put( Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA ); - cfg.setProperty( Environment.MULTI_TENANT_CONNECTION_PROVIDER, "class.not.present.in.classpath" ); - cfg.buildMappings(); - ServiceRegistryImplementor serviceRegistry = (ServiceRegistryImplementor) new StandardServiceRegistryBuilder() - .applySettings( cfg.getProperties() ).build(); - cfg.buildSessionFactory( serviceRegistry ).close(); - serviceRegistry.destroy(); - } - @Test public void testReleaseMode() { + // todo : this really does not test anythign. The service is not used here, and so not initialized Configuration cfg = new Configuration(); cfg.getProperties().put( Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA ); cfg.getProperties().put( Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.AFTER_STATEMENT.name() ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/CurrentTenantResolverMultiTenancyTest.java b/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/CurrentTenantResolverMultiTenancyTest.java index f36456a610ff..cab4d1c4cbc6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/CurrentTenantResolverMultiTenancyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/CurrentTenantResolverMultiTenancyTest.java @@ -44,37 +44,37 @@ @TestForIssue(jiraKey = "HHH-7306") @RequiresDialectFeature( value = ConnectionProviderBuilder.class ) public class CurrentTenantResolverMultiTenancyTest extends SchemaBasedMultiTenancyTest { - - private TestCurrentTenantIdentifierResolver currentTenantResolver = new TestCurrentTenantIdentifierResolver(); - - - @Override - protected Configuration buildConfiguration() { - Configuration cfg = super.buildConfiguration(); - cfg.setCurrentTenantIdentifierResolver( currentTenantResolver ); - return cfg; - } - - @Override - protected Session getNewSession(String tenant) { - currentTenantResolver.currentTenantIdentifier = tenant; - Session session = sessionFactory.openSession(); - Assert.assertEquals( tenant, session.getTenantIdentifier() ); - return session; - } - - - private static class TestCurrentTenantIdentifierResolver implements CurrentTenantIdentifierResolver { - private String currentTenantIdentifier; - - @Override - public boolean validateExistingCurrentSessions() { - return false; - } - - @Override - public String resolveCurrentTenantIdentifier() { - return currentTenantIdentifier; - } - } +// +// private TestCurrentTenantIdentifierResolver currentTenantResolver = new TestCurrentTenantIdentifierResolver(); +// +// +// @Override +// protected Configuration buildConfiguration() { +// Configuration cfg = super.buildConfiguration(); +// cfg.setCurrentTenantIdentifierResolver( currentTenantResolver ); +// return cfg; +// } +// +// @Override +// protected Session getNewSession(String tenant) { +// currentTenantResolver.currentTenantIdentifier = tenant; +// Session session = sessionFactory.openSession(); +// Assert.assertEquals( tenant, session.getTenantIdentifier() ); +// return session; +// } +// +// +// private static class TestCurrentTenantIdentifierResolver implements CurrentTenantIdentifierResolver { +// private String currentTenantIdentifier; +// +// @Override +// public boolean validateExistingCurrentSessions() { +// return false; +// } +// +// @Override +// public String resolveCurrentTenantIdentifier() { +// return currentTenantIdentifier; +// } +// } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/SchemaBasedMultiTenancyTest.java b/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/SchemaBasedMultiTenancyTest.java index dd752022edf8..e71042891fee 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/SchemaBasedMultiTenancyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/SchemaBasedMultiTenancyTest.java @@ -44,6 +44,8 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; import org.hibernate.service.spi.ServiceRegistryImplementor; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.cache.CachingRegionFactory; import org.hibernate.testing.env.ConnectionProviderBuilder; @@ -63,128 +65,129 @@ public class SchemaBasedMultiTenancyTest extends BaseUnitTestCase { protected SessionFactoryImplementor sessionFactory; - @Before - public void setUp() { - AbstractMultiTenantConnectionProvider multiTenantConnectionProvider = buildMultiTenantConnectionProvider(); - Configuration cfg = buildConfiguration(); - - serviceRegistry = (ServiceRegistryImplementor) new StandardServiceRegistryBuilder() - .applySettings( cfg.getProperties() ) - .addService( MultiTenantConnectionProvider.class, multiTenantConnectionProvider ) - .build(); - - sessionFactory = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry ); - } - - protected Configuration buildConfiguration() { - Configuration cfg = new Configuration(); - cfg.getProperties().put( Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA ); - cfg.setProperty( Environment.CACHE_REGION_FACTORY, CachingRegionFactory.class.getName() ); - cfg.setProperty( Environment.GENERATE_STATISTICS, "true" ); - cfg.addAnnotatedClass( Customer.class ); - cfg.addAnnotatedClass( Invoice.class ); - - cfg.buildMappings(); - RootClass meta = (RootClass) cfg.getClassMapping( Customer.class.getName() ); - meta.setCacheConcurrencyStrategy( "read-write" ); - - // do the acme export - new SchemaExport( - new ConnectionHelper() { - private Connection connection; - @Override - public void prepare(boolean needsAutoCommit) throws SQLException { - connection = acmeProvider.getConnection(); - } - - @Override - public Connection getConnection() throws SQLException { - return connection; - } - - @Override - public void release() throws SQLException { - acmeProvider.closeConnection( connection ); - } - }, - cfg.generateDropSchemaScript( ConnectionProviderBuilder.getCorrespondingDialect() ), - cfg.generateSchemaCreationScript( ConnectionProviderBuilder.getCorrespondingDialect() ) - ).execute( // so stupid... - false, // do not script the export (write it to file) - true, // do run it against the database - false, // do not *just* perform the drop - false // do not *just* perform the create - ); - - // do the jboss export - new SchemaExport( - new ConnectionHelper() { - private Connection connection; - @Override - public void prepare(boolean needsAutoCommit) throws SQLException { - connection = jbossProvider.getConnection(); - } - - @Override - public Connection getConnection() throws SQLException { - return connection; - } - - @Override - public void release() throws SQLException { - jbossProvider.closeConnection( connection ); - } - }, - cfg.generateDropSchemaScript( ConnectionProviderBuilder.getCorrespondingDialect() ), - cfg.generateSchemaCreationScript( ConnectionProviderBuilder.getCorrespondingDialect() ) - ).execute( // so stupid... - false, // do not script the export (write it to file) - true, // do run it against the database - false, // do not *just* perform the drop - false // do not *just* perform the create - ); - return cfg; - } - - private AbstractMultiTenantConnectionProvider buildMultiTenantConnectionProvider() { - acmeProvider = ConnectionProviderBuilder.buildConnectionProvider( "acme" ); - jbossProvider = ConnectionProviderBuilder.buildConnectionProvider( "jboss" ); - return new AbstractMultiTenantConnectionProvider() { - @Override - protected ConnectionProvider getAnyConnectionProvider() { - return acmeProvider; - } - - @Override - protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) { - if ( "acme".equals( tenantIdentifier ) ) { - return acmeProvider; - } - else if ( "jboss".equals( tenantIdentifier ) ) { - return jbossProvider; - } - throw new HibernateException( "Unknown tenant identifier" ); - } - }; - } - - @After - public void tearDown() { - if ( sessionFactory != null ) { - sessionFactory.close(); - } - if ( serviceRegistry != null ) { - serviceRegistry.destroy(); - } - if ( jbossProvider != null ) { - jbossProvider.stop(); - } - if ( acmeProvider != null ) { - acmeProvider.stop(); - } - } +// @Before +// public void setUp() { +// AbstractMultiTenantConnectionProvider multiTenantConnectionProvider = buildMultiTenantConnectionProvider(); +// Configuration cfg = buildConfiguration(); +// +// serviceRegistry = (ServiceRegistryImplementor) new StandardServiceRegistryBuilder() +// .applySettings( cfg.getProperties() ) +// .addService( MultiTenantConnectionProvider.class, multiTenantConnectionProvider ) +// .build(); +// +// sessionFactory = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry ); +// } +// +// protected Configuration buildConfiguration() { +// Configuration cfg = new Configuration(); +// cfg.getProperties().put( Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA ); +// cfg.setProperty( Environment.CACHE_REGION_FACTORY, CachingRegionFactory.class.getName() ); +// cfg.setProperty( Environment.GENERATE_STATISTICS, "true" ); +// cfg.addAnnotatedClass( Customer.class ); +// cfg.addAnnotatedClass( Invoice.class ); +// +// cfg.buildMappings(); +// RootClass meta = (RootClass) cfg.getClassMapping( Customer.class.getName() ); +// meta.setCacheConcurrencyStrategy( "read-write" ); +// +// // do the acme export +// new SchemaExport( +// new ConnectionHelper() { +// private Connection connection; +// @Override +// public void prepare(boolean needsAutoCommit) throws SQLException { +// connection = acmeProvider.getConnection(); +// } +// +// @Override +// public Connection getConnection() throws SQLException { +// return connection; +// } +// +// @Override +// public void release() throws SQLException { +// acmeProvider.closeConnection( connection ); +// } +// }, +// cfg.generateDropSchemaScript( ConnectionProviderBuilder.getCorrespondingDialect() ), +// cfg.generateSchemaCreationScript( ConnectionProviderBuilder.getCorrespondingDialect() ) +// ).execute( // so stupid... +// false, // do not script the export (write it to file) +// true, // do run it against the database +// false, // do not *just* perform the drop +// false // do not *just* perform the create +// ); +// +// // do the jboss export +// new SchemaExport( +// new ConnectionHelper() { +// private Connection connection; +// @Override +// public void prepare(boolean needsAutoCommit) throws SQLException { +// connection = jbossProvider.getConnection(); +// } +// +// @Override +// public Connection getConnection() throws SQLException { +// return connection; +// } +// +// @Override +// public void release() throws SQLException { +// jbossProvider.closeConnection( connection ); +// } +// }, +// cfg.generateDropSchemaScript( ConnectionProviderBuilder.getCorrespondingDialect() ), +// cfg.generateSchemaCreationScript( ConnectionProviderBuilder.getCorrespondingDialect() ) +// ).execute( // so stupid... +// false, // do not script the export (write it to file) +// true, // do run it against the database +// false, // do not *just* perform the drop +// false // do not *just* perform the create +// ); +// return cfg; +// } +// +// private AbstractMultiTenantConnectionProvider buildMultiTenantConnectionProvider() { +// acmeProvider = ConnectionProviderBuilder.buildConnectionProvider( "acme" ); +// jbossProvider = ConnectionProviderBuilder.buildConnectionProvider( "jboss" ); +// return new AbstractMultiTenantConnectionProvider() { +// @Override +// protected ConnectionProvider getAnyConnectionProvider() { +// return acmeProvider; +// } +// +// @Override +// protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) { +// if ( "acme".equals( tenantIdentifier ) ) { +// return acmeProvider; +// } +// else if ( "jboss".equals( tenantIdentifier ) ) { +// return jbossProvider; +// } +// throw new HibernateException( "Unknown tenant identifier" ); +// } +// }; +// } +// +// @After +// public void tearDown() { +// if ( sessionFactory != null ) { +// sessionFactory.close(); +// } +// if ( serviceRegistry != null ) { +// serviceRegistry.destroy(); +// } +// if ( jbossProvider != null ) { +// jbossProvider.stop(); +// } +// if ( acmeProvider != null ) { +// acmeProvider.stop(); +// } +// } @Test + @FailureExpectedWithNewMetamodel public void testBasicExpectedBehavior() { Session session = getNewSession("jboss"); session.beginTransaction(); @@ -212,6 +215,7 @@ public void testBasicExpectedBehavior() { } @Test + @FailureExpectedWithNewMetamodel public void testSameIdentifiers() { // create a customer 'steve' in jboss Session session = getNewSession("jboss"); @@ -297,6 +301,7 @@ public void testSameIdentifiers() { } @Test + @FailureExpectedWithNewMetamodel public void testTableIdentifiers() { Session session = getNewSession( "jboss" ); session.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java index 2b6354566641..e344efe2270c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/namingstrategy/NamingStrategyTest.java @@ -23,15 +23,21 @@ */ package org.hibernate.test.namingstrategy; -import org.junit.Test; - import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * @author Emmanuel Bernard @@ -59,19 +65,44 @@ public String[] getMappings() { } @Test + @FailureExpectedWithNewMetamodel public void testDatabaseColumnNames() { - PersistentClass classMapping = configuration().getClassMapping( Customers.class.getName() ); - Column stateColumn = (Column) classMapping.getProperty( "specified_column" ).getColumnIterator().next(); - assertEquals( "CN_specified_column", stateColumn.getName() ); + EntityBinding entityBinding = metadata().getEntityBinding( Customers.class.getName() ); + assertNotNull( entityBinding ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( "specified_column" ); + assertNotNull( attributeBinding ); + assertTrue( SingularAttributeBinding.class.isInstance( attributeBinding ) ); + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + assertEquals( 1, singularAttributeBinding.getRelationalValueBindings().size() ); + RelationalValueBinding valueBinding = singularAttributeBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) valueBinding + .getValue(); + assertEquals( "CN_specified_column", column.getColumnName().getText() ); } @Test @TestForIssue(jiraKey = "HHH-5848") + @FailureExpectedWithNewMetamodel public void testDatabaseTableNames() { - PersistentClass classMapping = configuration().getClassMapping( Item.class.getName() ); - Column secTabColumn = (Column) classMapping.getProperty( "specialPrice" ).getColumnIterator().next(); - assertEquals( "TAB_ITEMS_SEC", secTabColumn.getValue().getTable().getName() ); - Column tabColumn = (Column) classMapping.getProperty( "price" ).getColumnIterator().next(); - assertEquals( "TAB_ITEMS", tabColumn.getValue().getTable().getName() ); + EntityBinding entityBinding = metadata().getEntityBinding( Item.class.getName() ); + assertNotNull( entityBinding ); + AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( "specialPrice" ); + assertNotNull( attributeBinding ); + assertTrue( SingularAttributeBinding.class.isInstance( attributeBinding ) ); + SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + assertEquals( 1, singularAttributeBinding.getRelationalValueBindings().size() ); + RelationalValueBinding valueBinding = singularAttributeBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + Table table = (Table)valueBinding.getTable(); + + assertEquals( "TAB_ITEMS_SEC", table.getPhysicalName().getText() ); + + singularAttributeBinding = (SingularAttributeBinding)entityBinding.locateAttributeBinding( "price" ); + assertEquals( 1, singularAttributeBinding.getRelationalValueBindings().size() ); + valueBinding = singularAttributeBinding.getRelationalValueBindings().get( 0 ); + assertFalse( valueBinding.isDerived() ); + table = (Table)valueBinding.getTable(); + assertEquals( "TAB_ITEMS", table.getPhysicalName().getText()); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java b/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java index 6dfcd164e5a0..acc68d32305b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/nationalized/SimpleNationalizedTest.java @@ -23,9 +23,6 @@ */ package org.hibernate.test.nationalized; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; - import java.sql.NClob; import javax.persistence.Entity; @@ -34,20 +31,15 @@ import org.hibernate.annotations.Nationalized; import org.hibernate.annotations.Type; -import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.type.CharacterNCharType; -import org.hibernate.type.MaterializedNClobType; -import org.hibernate.type.NClobType; -import org.hibernate.type.NTextType; -import org.hibernate.type.StringNVarcharType; import org.junit.Test; /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class SimpleNationalizedTest extends BaseUnitTestCase { @Entity( name="NationalizedEntity") @@ -78,40 +70,41 @@ public static class NationalizedEntity { @Test public void simpleNationalizedTest() { - Configuration cfg = new Configuration(); - cfg.addAnnotatedClass( NationalizedEntity.class ); - cfg.buildMappings(); - PersistentClass pc = cfg.getClassMapping( NationalizedEntity.class.getName() ); - assertNotNull( pc ); - - { - Property prop = pc.getProperty( "nvarcharAtt" ); - assertSame( StringNVarcharType.INSTANCE, prop.getType() ); - } - - { - Property prop = pc.getProperty( "materializedNclobAtt" ); - assertSame( MaterializedNClobType.INSTANCE, prop.getType() ); - } - - { - Property prop = pc.getProperty( "nclobAtt" ); - assertSame( NClobType.INSTANCE, prop.getType() ); - } - - { - Property prop = pc.getProperty( "nlongvarcharcharAtt" ); - assertSame( NTextType.INSTANCE, prop.getType() ); - } - - { - Property prop = pc.getProperty( "ncharArrAtt" ); - assertSame( StringNVarcharType.INSTANCE, prop.getType() ); - } - - { - Property prop = pc.getProperty( "ncharacterAtt" ); - assertSame( CharacterNCharType.INSTANCE, prop.getType() ); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAnnotatedClass( NationalizedEntity.class ); +// cfg.buildMappings(); +// PersistentClass pc = cfg.getClassMapping( NationalizedEntity.class.getName() ); +// assertNotNull( pc ); +// +// { +// Property prop = pc.getProperty( "nvarcharAtt" ); +// assertSame( StringNVarcharType.INSTANCE, prop.getType() ); +// } +// +// { +// Property prop = pc.getProperty( "materializedNclobAtt" ); +// assertSame( MaterializedNClobType.INSTANCE, prop.getType() ); +// } +// +// { +// Property prop = pc.getProperty( "nclobAtt" ); +// assertSame( NClobType.INSTANCE, prop.getType() ); +// } +// +// { +// Property prop = pc.getProperty( "nlongvarcharcharAtt" ); +// assertSame( NTextType.INSTANCE, prop.getType() ); +// } +// +// { +// Property prop = pc.getProperty( "ncharArrAtt" ); +// assertSame( StringNVarcharType.INSTANCE, prop.getType() ); +// } +// +// { +// Property prop = pc.getProperty( "ncharacterAtt" ); +// assertSame( CharacterNCharType.INSTANCE, prop.getType() ); +// } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java index 86b591c28a5d..b21b14900860 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/naturalid/inheritance/spread/SpreadNaturalIdTest.java @@ -23,19 +23,20 @@ */ package org.hibernate.test.naturalid.inheritance.spread; -import org.junit.Test; +import static org.junit.Assert.fail; import org.hibernate.AnnotationException; import org.hibernate.cfg.Configuration; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; - -import static org.junit.Assert.fail; +import org.junit.Test; /** * @author Steve Ebersole */ @TestForIssue( jiraKey = "HHH-7129" ) +@FailureExpectedWithNewMetamodel public class SpreadNaturalIdTest extends BaseUnitTestCase { @Test public void testSpreadNaturalIdDeclarationGivesMappingException() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/basic/OneToOneSchemaTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/basic/OneToOneSchemaTest.java index 569d3e2d9804..6a07faba304b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/basic/OneToOneSchemaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/basic/OneToOneSchemaTest.java @@ -23,13 +23,12 @@ */ package org.hibernate.test.onetoone.basic; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Table; - -import org.junit.Test; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertFalse; @@ -40,18 +39,16 @@ public class OneToOneSchemaTest extends BaseUnitTestCase { @Test public void testUniqueKeyNotGeneratedViaAnnotations() throws Exception { - Configuration cfg = new Configuration() + MetadataImplementor metadata = (MetadataImplementor) new MetadataSources() .addAnnotatedClass( Parent.class ) .addAnnotatedClass( Child.class ) - .setProperty( Environment.HBM2DDL_AUTO, "create" ); + .buildMetadata(); - probeForUniqueKey( cfg ); + probeForUniqueKey( metadata ); } - private void probeForUniqueKey(Configuration cfg) { - cfg.buildMappings(); - - Table childTable = cfg.createMappings().getTable( null, null, "CHILD" ); - assertFalse( "UniqueKey was generated when it should not", childTable.getUniqueKeyIterator().hasNext() ); + private void probeForUniqueKey(MetadataImplementor metadata) { + org.hibernate.metamodel.spi.relational.TableSpecification table = SchemaUtil.getTable( "CHILD", metadata ); + assertFalse( "UniqueKey was generated when it should not", table.getUniqueKeys().iterator().hasNext() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java index d4f97be72efb..c7925a0cee2d 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/formula/OneToOneFormulaTest.java @@ -33,6 +33,7 @@ import org.hibernate.cfg.Environment; import org.hibernate.criterion.Property; import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.type.AbstractSingleColumnStandardBasicType; import org.hibernate.type.TextType; @@ -149,6 +150,7 @@ public void testOneToOneFormula() { } @Test + @FailureExpectedWithNewMetamodel public void testOneToOneEmbeddedCompositeKey() { Person p = new Person(); p.setName("Gavin King"); diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java index 215c0886c1e6..751c584027c1 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/nopojo/DynamicMapOneToOneTest.java @@ -11,6 +11,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.stat.EntityStatistics; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java index 51523353c209..44a829e05ceb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java @@ -39,7 +39,14 @@ public void configure(Configuration cfg) { } public String[] getMappings() { - return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml", "ops/OptLockEntity.hbm.xml", "ops/OneToOne.hbm.xml", "ops/Competition.hbm.xml" }; + return new String[] { + "ops/Node.hbm.xml", + "ops/Employer.hbm.xml", + "ops/OptLockEntity.hbm.xml", + "ops/OneToOne.hbm.xml", + "ops/Competition.hbm.xml", + "ops/Hoarder.hbm.xml" + }; } public String getCacheConcurrencyStrategy() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Category.java b/hibernate-core/src/test/java/org/hibernate/test/ops/Category.java new file mode 100644 index 000000000000..adee4d797187 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/Category.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.ops; + +/** + * @author Gail Badner + */ +public class Category { + private Long id; + private String name; + private Item exampleItem; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Item getExampleItem() { + return exampleItem; + } + + public void setExampleItem(Item exampleItem) { + this.exampleItem = exampleItem; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.hbm.xml new file mode 100644 index 000000000000..79f4dd6bcfcb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.hbm.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.java b/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.java new file mode 100644 index 000000000000..4c03ae76c999 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.ops; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Gail Badner + */ +public class Hoarder { + private Long id; + private String name; + private Item favoriteItem; + private Set items = new HashSet(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Item getFavoriteItem() { + return favoriteItem; + } + + public void setFavoriteItem(Item favoriteItem) { + this.favoriteItem = favoriteItem; + } + + public Set getItems() { + return items; + } + + public void setItems(Set items) { + this.items = items; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Item.java b/hibernate-core/src/test/java/org/hibernate/test/ops/Item.java new file mode 100644 index 000000000000..184b86b6c9c3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/Item.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.ops; + +/** + * @author Gail Badner + */ +public class Item { + private Long id; + private String name; + private String description; + private Category category; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + Item item = (Item) o; + + if ( !name.equals( item.name ) ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java index 00b5dba4fb61..b06fcfba2ba2 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java @@ -35,6 +35,7 @@ import org.hibernate.StaleObjectStateException; import org.hibernate.Transaction; import org.hibernate.criterion.Projections; +import org.hibernate.testing.FailureExpected; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -493,7 +494,7 @@ public void testMergeDeepTreeWithGeneratedId() { child = (NumberedNode) root.getChildren().iterator().next(); grandchild = (NumberedNode) child.getChildren().iterator().next(); - grandchild.setDescription("the grand child"); + grandchild.setDescription( "the grand child" ); NumberedNode grandchild2 = new NumberedNode("grandchild2"); child.addChild( grandchild2 ); @@ -503,7 +504,7 @@ public void testMergeDeepTreeWithGeneratedId() { tx.commit(); s.close(); - assertInsertCount(1); + assertInsertCount( 1 ); assertUpdateCount(1); clearCounts(); @@ -512,7 +513,7 @@ public void testMergeDeepTreeWithGeneratedId() { NumberedNode child2 = new NumberedNode("child2"); NumberedNode grandchild3 = new NumberedNode("grandchild3"); child2.addChild( grandchild3 ); - root.addChild(child2); + root.addChild( child2 ); s = openSession(); tx = s.beginTransaction(); @@ -615,19 +616,19 @@ public void testMergeManaged() { tx = s.beginTransaction(); NumberedNode child = new NumberedNode("child"); - root.addChild(child); - assertSame( root, s.merge(root) ); + root.addChild( child ); + assertSame( root, s.merge( root ) ); Object mergedChild = root.getChildren().iterator().next(); assertNotSame( mergedChild, child ); - assertTrue( s.contains(mergedChild) ); + assertTrue( s.contains( mergedChild ) ); assertFalse( s.contains(child) ); assertEquals( root.getChildren().size(), 1 ); assertTrue( root.getChildren().contains(mergedChild) ); //assertNotSame( mergedChild, s.merge(child) ); //yucky :( tx.commit(); - assertInsertCount(1); - assertUpdateCount(0); + assertInsertCount( 1 ); + assertUpdateCount( 0 ); assertEquals( root.getChildren().size(), 1 ); assertTrue( root.getChildren().contains(mergedChild) ); @@ -651,7 +652,7 @@ public void testMergeManagedUninitializedCollection() { Transaction tx = s.beginTransaction(); NumberedNode root = new NumberedNode( "root" ); root.addChild( new NumberedNode( "child" ) ); - s.persist(root); + s.persist( root ); tx.commit(); s.close(); @@ -671,14 +672,14 @@ public void testMergeManagedUninitializedCollection() { assertFalse( Hibernate.isInitialized( managedChildren ) ); tx.commit(); - assertInsertCount(0); - assertUpdateCount(0); - assertDeleteCount(0); + assertInsertCount( 0 ); + assertUpdateCount( 0 ); + assertDeleteCount( 0 ); tx = s.beginTransaction(); assertEquals( Long.valueOf( 2 ), - s.createCriteria(NumberedNode.class) + s.createCriteria( NumberedNode.class ) .setProjection( Projections.rowCount() ) .uniqueResult() ); @@ -825,6 +826,97 @@ public void testMergeManyToManyWithCollectionDeference() throws Exception { cleanup(); } + @Test + @FailureExpected( jiraKey = "HHH-9106") + public void testMergeTransientWithMultipleDetachedRepresentationOfSameEntity() { + + Item item1 = new Item(); + item1.setName( "item1" ); + item1.setDescription( "item1 description" ); + + Session s = openSession(); + Transaction tx = session.beginTransaction(); + s.persist( item1 ); + tx.commit(); + s.close(); + + // Get 2 representations of the same Item from 3 different sessions. + + s = openSession(); + Item item1_1 = (Item) s.get( Item.class, item1.getId() ); + s.close(); + + s = openSession(); + Item item1_2 = (Item) s.get( Item.class, item1.getId() ); + s.close(); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertFalse( item1_1 == item1_2 ); + assertTrue( item1_1.equals( item1_2 ) ); + + // Create a transient entity that references both representations. + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + hoarder.getItems().add( item1_1 ); + hoarder.setFavoriteItem( item1_2 ); + + s = openSession(); + tx = s.beginTransaction(); + hoarder = (Hoarder) s.merge( hoarder ); + assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); + assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); + assertEquals( item1.getDescription(), hoarder.getFavoriteItem().getDescription() ); + assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); + tx.commit(); + s.close(); + } + + @Test + @FailureExpected( jiraKey = "HHH-9106") + public void testMergeDetachedWithDetachedRepresentationOfSameEntity() { + Item item1 = new Item(); + item1.setName( "item1" ); + item1.setDescription( "item1 description" ); + + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + + Session s = openSession(); + Transaction tx = session.beginTransaction(); + s.persist( item1 ); + s.persist( hoarder ); + tx.commit(); + s.close(); + + // Get 2 representations of the same Item from 3 different sessions. + + s = openSession(); + Item item1_1 = (Item) s.get( Item.class, item1.getId() ); + s.close(); + + s = openSession(); + Item item1_2 = (Item) s.get( Item.class, item1.getId() ); + s.close(); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertFalse( item1_1 == item1_2 ); + assertTrue( item1_1.equals( item1_2 ) ); + + // Update hoarder (detached) to references both representations. + hoarder.getItems().add( item1_1 ); + hoarder.setFavoriteItem( item1_2 ); + + s = openSession(); + tx = s.beginTransaction(); + hoarder = (Hoarder) s.merge( hoarder ); + assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); + assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); + assertEquals( item1.getDescription(), hoarder.getFavoriteItem().getDescription() ); + assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); + tx.commit(); + s.close(); + } + @SuppressWarnings( {"unchecked"}) private void cleanup() { Session s = openSession(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java index 8bd1ffd0fe22..fd9426475505 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java @@ -33,6 +33,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Projections; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java index 61c73d8a1112..7f15c2265c2c 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java @@ -29,6 +29,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; +import org.hibernate.metamodel.MetadataSources; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -38,11 +39,6 @@ * @author Gail Badner */ public class SimpleOpsTest extends AbstractOperationTestCase { - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true"); - } - public String[] getMappings() { return new String[] { "ops/SimpleEntity.hbm.xml" }; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWork.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWork.java index 60aa29b906fe..403b23b3404d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWork.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWork.java @@ -23,20 +23,19 @@ */ package org.hibernate.test.propertyref; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.OrderColumn; import javax.persistence.Table; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import org.hibernate.annotations.IndexColumn; import org.hibernate.annotations.ListIndexBase; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java index 9a31f474e622..05cb9f6f30a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java @@ -29,6 +29,8 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.H2Dialect; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -37,10 +39,13 @@ * @author Steve Ebersole */ @RequiresDialect(H2Dialect.class) +@FailureExpectedWithNewMetamodel( + message = "Thing is.. how does this not fail all the time? That Session.get call should always return null, leading to NPE." +) public class DoesNotWorkTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {DoesNotWork.class}; + return new Class[] { DoesNotWork.class, DoesNotWorkPk.class }; } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java index 4e973472f9c1..3303c4b4ee20 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkWithHbmTest.java @@ -32,6 +32,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.H2Dialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -39,6 +40,7 @@ /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel @RequiresDialect(H2Dialect.class) public class DoesNotWorkWithHbmTest extends BaseCoreFunctionalTestCase { diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/BasicPropertiesTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/BasicPropertiesTest.java index 8b5f5454ec4d..e4d242082950 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/BasicPropertiesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/BasicPropertiesTest.java @@ -28,6 +28,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -46,6 +47,7 @@ public String[] getMappings() { */ @Test @TestForIssue(jiraKey = "HHH-8689") + @FailureExpectedWithNewMetamodel public void testProperties() { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java index 35750de714af..00b3ed42d8f9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/basic/PropertyRefTest.java @@ -26,18 +26,19 @@ import java.util.Iterator; import java.util.List; -import org.junit.Test; - import org.hibernate.FetchMode; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.ForeignKey; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.test.util.SchemaUtil; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -67,6 +68,7 @@ public String getCacheConcurrencyStrategy() { } @Test + @FailureExpectedWithNewMetamodel public void testNonLazyBagKeyPropertyRef() { Session s = openSession(); Transaction t = s.beginTransaction(); @@ -101,6 +103,7 @@ public void testNonLazyBagKeyPropertyRef() { } @Test + @FailureExpectedWithNewMetamodel public void testManyToManyPropertyRef() { // prepare some test data relating to the Group->Person many-to-many association Session s = openSession(); @@ -141,6 +144,7 @@ public void testManyToManyPropertyRef() { } @Test + @FailureExpectedWithNewMetamodel public void testOneToOnePropertyRef() { Session s = openSession(); Transaction t = s.beginTransaction(); @@ -224,6 +228,7 @@ public void testOneToOnePropertyRef() { } @Test + @FailureExpectedWithNewMetamodel public void testJoinFetchPropertyRef() { Session s = openSession(); Transaction t = s.beginTransaction(); @@ -271,24 +276,18 @@ public void testJoinFetchPropertyRef() { @Test public void testForeignKeyCreation() { - PersistentClass classMapping = configuration().getClassMapping("org.hibernate.test.propertyref.basic.Account"); - - Iterator foreignKeyIterator = classMapping.getTable().getForeignKeyIterator(); boolean found = false; - while ( foreignKeyIterator.hasNext() ) { - ForeignKey element = (ForeignKey) foreignKeyIterator.next(); - if(element.getReferencedEntityName().equals(Person.class.getName() ) ) { - - if(!element.isReferenceToPrimaryKey() ) { - List referencedColumns = element.getReferencedColumns(); - Column column = (Column) referencedColumns.get(0); - if(column.getName().equals("person_userid") ) { - found = true; // extend test to include the columns - } + TableSpecification table = SchemaUtil.getTable( Account.class, metadata() ); + EntityBinding personEntityBinding = metadata().getEntityBinding( Person.class.getName() ); + for ( org.hibernate.metamodel.spi.relational.ForeignKey element : table.getForeignKeys() ) { + if ( element.getTargetTable().equals( personEntityBinding.getPrimaryTable() ) ) { + for ( org.hibernate.metamodel.spi.relational.Column column : element.getTargetColumns() ) { + if ( column.getColumnName().getText( getDialect() ).equals( "person_userid" ) ) { + found = true; + } } } } - assertTrue("Property ref foreign key not found",found); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/complete/CompleteComponentPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/complete/CompleteComponentPropertyRefTest.java index b6831a207bd1..10e345652a21 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/complete/CompleteComponentPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/complete/CompleteComponentPropertyRefTest.java @@ -28,6 +28,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/partial/PartialComponentPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/partial/PartialComponentPropertyRefTest.java index 0cc13332cf2d..71f74463d7fd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/partial/PartialComponentPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/component/partial/PartialComponentPropertyRefTest.java @@ -27,6 +27,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/discrim/SubclassPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/discrim/SubclassPropertyRefTest.java index 91a7c9d79c31..fa768438dc18 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/discrim/SubclassPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/discrim/SubclassPropertyRefTest.java @@ -28,6 +28,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNotNull; @@ -37,6 +38,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class SubclassPropertyRefTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java index 1b717c1e0c4e..af377116cd84 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/joined/JoinedSubclassPropertyRefTest.java @@ -29,6 +29,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNotNull; @@ -37,6 +38,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class JoinedSubclassPropertyRefTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "propertyref/inheritence/joined/Person.hbm.xml" }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/union/UnionSubclassPropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/union/UnionSubclassPropertyRefTest.java index d899e96dc12f..77a5ab8a4b98 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/union/UnionSubclassPropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/inheritence/union/UnionSubclassPropertyRefTest.java @@ -28,6 +28,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertNotNull; @@ -44,6 +45,7 @@ public String[] getMappings() { } @Test + @FailureExpectedWithNewMetamodel public void testOneToOnePropertyRef() { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java new file mode 100644 index 000000000000..8f764ed249a1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/AbstractEntity.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +@Entity +public abstract class AbstractEntity { + + @Id + @GeneratedValue + private Integer id; + + public AbstractEntity() { + super(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java new file mode 100644 index 000000000000..4cbee7e7f6c3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ConcreteEntity.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import javax.persistence.Entity; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +@Entity +public class ConcreteEntity extends AbstractEntity { + + private String content = "text"; + + public ConcreteEntity() { + super(); + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java new file mode 100644 index 000000000000..b97c70cb43ec --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/LazyAbstractEntityReference.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +@Entity +public class LazyAbstractEntityReference { + + @Id + @GeneratedValue + private Integer id; + + @ManyToOne(fetch = FetchType.LAZY) + private AbstractEntity entity; + + protected LazyAbstractEntityReference() { + } + + public LazyAbstractEntityReference(AbstractEntity entity) { + super(); + setEntity( entity ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public AbstractEntity getEntity() { + return entity; + } + + public void setEntity(AbstractEntity entity) { + this.entity = entity; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java new file mode 100644 index 000000000000..7d3f6a236928 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.proxy.narrow; + +import static org.junit.Assert.assertTrue; + +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.proxy.HibernateProxy; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +/** + * @author Yoann Rodière + * @author Guillaume Smet + */ +public class ProxyNarrowingTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { AbstractEntity.class, ConcreteEntity.class, LazyAbstractEntityReference.class }; + } + + @Test + public void testNarrowedProxyIsInitializedIfOriginalProxyIsInitialized() { + Session session = openSession(); + + Integer entityReferenceId = null; + + // Populate the database + try { + Transaction t = session.beginTransaction(); + + ConcreteEntity entity = new ConcreteEntity(); + session.save( entity ); + + LazyAbstractEntityReference reference = new LazyAbstractEntityReference( entity ); + session.save( reference ); + entityReferenceId = reference.getId(); + + session.flush(); + t.commit(); + } + finally { + session.close(); + } + + session = openSession(); + + try { + // load a proxified version of the entity into the session: the proxy is based on the AbstractEntity class + // as the reference class property is of type AbstractEntity. + LazyAbstractEntityReference reference = (LazyAbstractEntityReference) session.get( LazyAbstractEntityReference.class, entityReferenceId ); + AbstractEntity abstractEntityProxy = reference.getEntity(); + + assertTrue( ( abstractEntityProxy instanceof HibernateProxy ) && !Hibernate.isInitialized( abstractEntityProxy ) ); + Hibernate.initialize( abstractEntityProxy ); + assertTrue( Hibernate.isInitialized( abstractEntityProxy ) ); + + // load the concrete class via session.load to trigger the StatefulPersistenceContext.narrowProxy code + ConcreteEntity concreteEntityProxy = (ConcreteEntity) session.load( ConcreteEntity.class, abstractEntityProxy.getId() ); + + // the new proxy created should be initialized + assertTrue( Hibernate.isInitialized( concreteEntityProxy ) ); + assertTrue( session.contains( concreteEntityProxy ) ); + } + finally { + session.close(); + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java b/hibernate-core/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java index 04b87537d4f6..ea15ad9ae31f 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java @@ -24,6 +24,7 @@ package org.hibernate.test.querycache; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; @@ -33,6 +34,7 @@ import org.hibernate.Criteria; import org.hibernate.Hibernate; import org.hibernate.Query; +import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; @@ -41,6 +43,7 @@ import org.hibernate.stat.EntityStatistics; import org.hibernate.stat.QueryStatistics; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -487,6 +490,50 @@ public void testGetByCompositeId() { s.close(); } + @Test + @TestForIssue( jiraKey = "HHH-3051" ) + public void testScalarSQLQuery() { + sessionFactory().getCache().evictQueryRegions(); + sessionFactory().getStatistics().clear(); + + Session s = openSession(); + s.beginTransaction(); + Item item = new Item(); + item.setName("fooName"); + item.setDescription("fooDescription"); + s.persist(item); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + + // Note: StandardQueryCache#put handles single results and multiple results differently. So, test both + // 1 and 2+ scalars. + + String sqlQuery = "select name, description from Items"; + SQLQuery query = s.createSQLQuery(sqlQuery); + query.setCacheable(true); + query.addScalar("name"); + query.addScalar("description"); + Object[] result1 = (Object[]) query.uniqueResult(); + assertNotNull( result1 ); + assertEquals( result1.length, 2 ); + assertEquals( result1[0], "fooName" ); + assertEquals( result1[1], "fooDescription" ); + + sqlQuery = "select name from Items"; + query = s.createSQLQuery(sqlQuery); + query.setCacheable(true); + query.addScalar("name"); + String result2 = (String) query.uniqueResult(); + assertNotNull( result2 ); + assertEquals( result2, "fooName" ); + + s.getTransaction().commit(); + s.close(); + } + // @Test // public void testGetByCompositeIdNoCache() { // Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e.pk = :pk"); diff --git a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java index 3c31ecd11122..91afd4b1b6ea 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteGlobalTest.java @@ -23,31 +23,26 @@ */ package org.hibernate.test.quote; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Iterator; - import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; -import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.UniqueKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; + import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.tool.hbm2ddl.SchemaExport; -import org.hibernate.tool.hbm2ddl.SchemaValidator; +import org.hibernate.test.util.SchemaUtil; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * @author Emmanuel Bernard * @author Brett Meyer @@ -57,12 +52,11 @@ public class QuoteGlobalTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue(jiraKey = "HHH-7890") public void testQuotedUniqueConstraint() { - Iterator itr = configuration().getClassMapping( Person.class.getName() ) - .getTable().getUniqueKeyIterator(); - while ( itr.hasNext() ) { - UniqueKey uk = itr.next(); + Iterable uniqueKeys = + SchemaUtil.getTable( Person.class, metadata() ).getUniqueKeys(); + for ( org.hibernate.metamodel.spi.relational.UniqueKey uk : uniqueKeys ) { assertEquals( uk.getColumns().size(), 1 ); - assertEquals( uk.getColumn( 0 ).getName(), "name"); + assertEquals( uk.getColumns().get( 0 ).getColumnName().getText(), "name"); return; } fail( "GLOBALLY_QUOTED_IDENTIFIERS caused the unique key creation to fail." ); @@ -83,7 +77,7 @@ public void testQuoteManytoMany() { assertEquals( 1, u.getRoles().size() ); tx.rollback(); String role = User.class.getName() + ".roles"; - assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); + assertEquals( "User_Role", SchemaUtil.getCollectionTable( User.class, "roles", metadata() ).getLogicalName().getText() ); s.close(); } @@ -94,27 +88,28 @@ public void testHbmQuoting() { doTestHbmQuoting( AssociatedDataPoint.class ); } - @Test - @TestForIssue(jiraKey = "HHH-7927") - public void testTableGeneratorQuoting() { - Configuration configuration = constructAndConfigureConfiguration(); - configuration.addAnnotatedClass(TestEntity.class); - new SchemaExport(configuration).execute( false, true, false, true ); - try { - new SchemaValidator(configuration).validate(); - } - catch (HibernateException e) { - fail( "The identifier generator table should have validated. " + e.getMessage() ); - } - } +// @Test +// @TestForIssue(jiraKey = "HHH-7927") +// public void testTableGeneratorQuoting() { +// Configuration configuration = constructAndConfigureConfiguration(); +// configuration.addAnnotatedClass(TestEntity.class); +// new SchemaExport(configuration).execute( false, true, false, true ); +// try { +// new SchemaValidator(configuration).validate(); +// } +// catch (HibernateException e) { +// fail( "The identifier generator table should have validated. " + e.getMessage() ); +// } +// } private void doTestHbmQuoting(Class clazz) { - Table table = configuration().getClassMapping( clazz.getName() ).getTable(); - assertTrue( table.isQuoted() ); - Iterator itr = table.getColumnIterator(); - while(itr.hasNext()) { - Column column = (Column) itr.next(); - assertTrue( column.isQuoted() ); + final TableSpecification tableSpecification = SchemaUtil.getTable( clazz, metadata() ); + assertTrue( tableSpecification.getLogicalName().isQuoted() ); + for ( org.hibernate.metamodel.spi.relational.Value value : tableSpecification.values() ) { + assertTrue( org.hibernate.metamodel.spi.relational.Column.class.isInstance( value ) ); + org.hibernate.metamodel.spi.relational.Column column = + (org.hibernate.metamodel.spi.relational.Column) value; + assertTrue( column.getColumnName().isQuoted() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java index 12ad902f8ab3..5e540a116dec 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/quote/QuoteTest.java @@ -26,14 +26,33 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; /** * @author Emmanuel Bernard + * @author Brett Meyer */ public class QuoteTest extends BaseCoreFunctionalTestCase { @@ -52,7 +71,13 @@ public void testQuoteManytoMany() { assertEquals( 1, u.getRoles().size() ); tx.rollback(); String role = User.class.getName() + ".roles"; - assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); + AttributeBinding attributeBinding = metadata().getEntityBinding( User.class.getName() ).locateAttributeBinding( "roles" ); + PluralAttributeKeyBinding keyBinding = ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeKeyBinding(); + assertEquals( + "User_Role", + ( (org.hibernate.metamodel.spi.relational.Table) keyBinding.getCollectionTable() ) + .getPhysicalName().getText() + ); s.close(); } @@ -80,6 +105,32 @@ public void testDoubleQuoteJoinColumn() { s.getTransaction().commit(); s.close(); } + + @Test + @TestForIssue(jiraKey = "HHH-2988") + public void testUnionSubclassEntityQuoting() { + Session s = openSession(); + s.beginTransaction(); + Container container1 = new Container(); + Container container2 = new Container(); + SimpleItem simpleItem = new SimpleItem(); + + container1.items.add( container2 ); + container1.items.add( simpleItem ); + container2.parent = container1; + simpleItem.parent = container1; + + s.persist( simpleItem ); + s.persist( container2 ); + s.persist( container1 ); + s.getTransaction().commit(); + s.clear(); + + Container result = (Container) s.get( Container.class, container1.id ); + assertNotNull( result ); + assertNotNull( result.items ); + assertEquals( 2, result.items.size() ); + } @Override protected Class[] getAnnotatedClasses() { @@ -87,7 +138,35 @@ protected Class[] getAnnotatedClasses() { User.class, Role.class, Phone.class, - House.class + House.class, + Container.class, + SimpleItem.class }; } + + @Entity + @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) + private static abstract class Item { + + @Id @GeneratedValue + @Column(name = "`ID`") + protected long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "`ParentID`") + protected Container parent; + } + + @Entity + @Table(name = "`CoNTaiNeR`") + private static class Container extends Item { + + @OneToMany(mappedBy = "parent", targetEntity = Item.class) + private Set items = new HashSet( 0 ); + } + + @Entity + @Table(name = "`SimpleItem`") + private static class SimpleItem extends Item { + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/quote/User.java b/hibernate-core/src/test/java/org/hibernate/test/quote/User.java index 022ea3bd4487..0d53572b037b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/quote/User.java +++ b/hibernate-core/src/test/java/org/hibernate/test/quote/User.java @@ -5,6 +5,7 @@ import java.util.HashSet; import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -14,12 +15,13 @@ import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.Table; +import javax.persistence.UniqueConstraint; /** * @author Emmanuel Bernard */ @Entity -@Table(name = "`User`") +@Table(name = "`User`", uniqueConstraints = @UniqueConstraint(columnNames = { "house3" })) public class User implements Serializable { @Id @@ -39,6 +41,12 @@ public class User implements Serializable { private Long house1; @Column(name = "`house`", insertable = false, updatable = false ) private Long house2; + + // test UK on FK w/ global quoting -- see HHH-8638 + // This MUST be initialized. Several DBs do not allow multiple null values in a unique column. + @ManyToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "house3") + private House house3 = new House(); public long getId() { return id; @@ -79,4 +87,12 @@ public Long getHouse2() { public void setHouse2(Long house2) { this.house2 = house2; } + + public House getHouse3() { + return house; + } + + public void setHouse3(House house3) { + this.house3 = house3; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/reattachment/ProxyReattachmentTest.java b/hibernate-core/src/test/java/org/hibernate/test/reattachment/ProxyReattachmentTest.java index 27c520629c60..9390bd0adb80 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/reattachment/ProxyReattachmentTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/reattachment/ProxyReattachmentTest.java @@ -23,16 +23,16 @@ */ package org.hibernate.test.reattachment; +import static org.junit.Assert.assertEquals; + import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import org.junit.Test; - import org.hibernate.Session; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * Test of proxy reattachment semantics @@ -250,4 +250,24 @@ public void testIterateWithEvictBottomOfLoop() { s.getTransaction().commit(); s.close(); } + + @Test + @TestForIssue(jiraKey = "HHH-8374") + public void testRemoveAndReattachProxyEntity() { + Session s = openSession(); + s.beginTransaction(); + Parent p = new Parent("foo"); + s.persist( p ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + p = (Parent) s.load( Parent.class, p.getName() ); + s.delete( p ); + // re-attach + s.persist( p ); + s.getTransaction().commit(); + s.close(); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/MigrationTest.java b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/MigrationTest.java index e7be2085759c..f91b19c28b04 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/MigrationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/MigrationTest.java @@ -23,21 +23,7 @@ */ package org.hibernate.test.schemaupdate; -import static org.junit.Assert.assertEquals; - -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy; -import org.hibernate.tool.hbm2ddl.SchemaExport; -import org.hibernate.tool.hbm2ddl.SchemaUpdate; -import org.junit.After; -import org.junit.Before; import org.junit.Test; /** @@ -45,90 +31,94 @@ * @author Brett Meyer */ public class MigrationTest extends BaseUnitTestCase { - private ServiceRegistry serviceRegistry; - - @Before - public void setUp() { - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() ); - } - - @After - public void tearDown() { - ServiceRegistryBuilder.destroy( serviceRegistry ); - serviceRegistry = null; - } - - protected JdbcServices getJdbcServices() { - return serviceRegistry.getService( JdbcServices.class ); - } - - @Test - public void testSimpleColumnAddition() { - String resource1 = "org/hibernate/test/schemaupdate/1_Version.hbm.xml"; - String resource2 = "org/hibernate/test/schemaupdate/2_Version.hbm.xml"; - - Configuration v1cfg = new Configuration(); - v1cfg.addResource( resource1 ); - new SchemaExport( v1cfg ).execute( false, true, true, false ); - - SchemaUpdate v1schemaUpdate = new SchemaUpdate( serviceRegistry, v1cfg ); - v1schemaUpdate.execute( true, true ); - - assertEquals( 0, v1schemaUpdate.getExceptions().size() ); - - Configuration v2cfg = new Configuration(); - v2cfg.addResource( resource2 ); - - SchemaUpdate v2schemaUpdate = new SchemaUpdate( serviceRegistry, v2cfg ); - v2schemaUpdate.execute( true, true ); - assertEquals( 0, v2schemaUpdate.getExceptions().size() ); - - new SchemaExport( serviceRegistry, v2cfg ).drop( false, true ); - - } - - /** - * 3_Version.hbm.xml contains a named unique constraint and an un-named - * unique constraint (will receive a randomly-generated name). Create - * the original schema with 2_Version.hbm.xml. Then, run SchemaUpdate - * TWICE using 3_Version.hbm.xml. Neither RECREATE_QUIETLY nor SKIP should - * generate any exceptions. - */ @Test - @TestForIssue( jiraKey = "HHH-8162" ) - public void testConstraintUpdate() { - doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.DROP_RECREATE_QUIETLY); - doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.RECREATE_QUIETLY); - doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.SKIP); + public void dummy() { } - - private void doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy strategy) { - // original - String resource1 = "org/hibernate/test/schemaupdate/2_Version.hbm.xml"; - // adds unique constraint - String resource2 = "org/hibernate/test/schemaupdate/3_Version.hbm.xml"; - - Configuration v1cfg = new Configuration(); - v1cfg.addResource( resource1 ); - new SchemaExport( v1cfg ).execute( false, true, true, false ); - // adds unique constraint - Configuration v2cfg = new Configuration(); - v2cfg.getProperties().put( AvailableSettings.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY, strategy ); - v2cfg.addResource( resource2 ); - SchemaUpdate v2schemaUpdate = new SchemaUpdate( serviceRegistry, v2cfg ); - v2schemaUpdate.execute( true, true ); - assertEquals( 0, v2schemaUpdate.getExceptions().size() ); - - Configuration v3cfg = new Configuration(); - v3cfg.getProperties().put( AvailableSettings.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY, strategy ); - v3cfg.addResource( resource2 ); - SchemaUpdate v3schemaUpdate = new SchemaUpdate( serviceRegistry, v3cfg ); - v3schemaUpdate.execute( true, true ); - assertEquals( 0, v3schemaUpdate.getExceptions().size() ); - - new SchemaExport( serviceRegistry, v3cfg ).drop( false, true ); - } +// private ServiceRegistry serviceRegistry; +// +// @Before +// public void setUp() { +// serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() ); +// } +// +// @After +// public void tearDown() { +// ServiceRegistryBuilder.destroy( serviceRegistry ); +// serviceRegistry = null; +// } +// +// protected JdbcServices getJdbcServices() { +// return serviceRegistry.getService( JdbcServices.class ); +// } +// +// @Test +// public void testSimpleColumnAddition() { +// String resource1 = "org/hibernate/test/schemaupdate/1_Version.hbm.xml"; +// String resource2 = "org/hibernate/test/schemaupdate/2_Version.hbm.xml"; +// +// Configuration v1cfg = new Configuration(); +// v1cfg.addResource( resource1 ); +// new SchemaExport( v1cfg ).execute( false, true, true, false ); +// +// SchemaUpdate v1schemaUpdate = new SchemaUpdate( serviceRegistry, v1cfg ); +// v1schemaUpdate.execute( true, true ); +// +// assertEquals( 0, v1schemaUpdate.getExceptions().size() ); +// +// Configuration v2cfg = new Configuration(); +// v2cfg.addResource( resource2 ); +// +// SchemaUpdate v2schemaUpdate = new SchemaUpdate( serviceRegistry, v2cfg ); +// v2schemaUpdate.execute( true, true ); +// assertEquals( 0, v2schemaUpdate.getExceptions().size() ); +// +// new SchemaExport( serviceRegistry, v2cfg ).drop( false, true ); +// +// } +// +// /** +// * 3_Version.hbm.xml contains a named unique constraint and an un-named +// * unique constraint (will receive a randomly-generated name). Create +// * the original schema with 2_Version.hbm.xml. Then, run SchemaUpdate +// * TWICE using 3_Version.hbm.xml. Neither RECREATE_QUIETLY nor SKIP should +// * generate any exceptions. +// */ +// @Test +// @TestForIssue( jiraKey = "HHH-8162" ) +// public void testConstraintUpdate() { +// doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.DROP_RECREATE_QUIETLY); +// doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.RECREATE_QUIETLY); +// doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy.SKIP); +// } +// +// private void doConstraintUpdate(UniqueConstraintSchemaUpdateStrategy strategy) { +// // original +// String resource1 = "org/hibernate/test/schemaupdate/2_Version.hbm.xml"; +// // adds unique constraint +// String resource2 = "org/hibernate/test/schemaupdate/3_Version.hbm.xml"; +// +// Configuration v1cfg = new Configuration(); +// v1cfg.addResource( resource1 ); +// new SchemaExport( v1cfg ).execute( false, true, true, false ); +// +// // adds unique constraint +// Configuration v2cfg = new Configuration(); +// v2cfg.getProperties().put( AvailableSettings.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY, strategy ); +// v2cfg.addResource( resource2 ); +// SchemaUpdate v2schemaUpdate = new SchemaUpdate( serviceRegistry, v2cfg ); +// v2schemaUpdate.execute( true, true ); +// assertEquals( 0, v2schemaUpdate.getExceptions().size() ); +// +// Configuration v3cfg = new Configuration(); +// v3cfg.getProperties().put( AvailableSettings.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY, strategy ); +// v3cfg.addResource( resource2 ); +// SchemaUpdate v3schemaUpdate = new SchemaUpdate( serviceRegistry, v3cfg ); +// v3schemaUpdate.execute( true, true ); +// assertEquals( 0, v3schemaUpdate.getExceptions().size() ); +// +// new SchemaExport( serviceRegistry, v3cfg ).drop( false, true ); +// } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportManagedConnectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportManagedConnectionTest.java index 5ec0f4e4f656..7253925610e8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportManagedConnectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportManagedConnectionTest.java @@ -23,7 +23,7 @@ */ package org.hibernate.test.schemaupdate; -import org.hibernate.cfg.Configuration; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.tool.hbm2ddl.SchemaExport; /** @@ -31,7 +31,7 @@ */ public class SchemaExportManagedConnectionTest extends SchemaExportTest { @Override - protected SchemaExport createSchemaExport(Configuration cfg) { - return new SchemaExport( cfg ); + protected SchemaExport createSchemaExport(MetadataImplementor metadata) { + return new SchemaExport( metadata ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportSuppliedConnectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportSuppliedConnectionTest.java index 451f66be4223..c2915f86941f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportSuppliedConnectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportSuppliedConnectionTest.java @@ -23,13 +23,7 @@ */ package org.hibernate.test.schemaupdate; -import org.junit.After; -import org.junit.Before; - -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.tool.hbm2ddl.SchemaExport; /** @@ -38,7 +32,7 @@ public class SchemaExportSuppliedConnectionTest extends SchemaExportTest { @Override - protected SchemaExport createSchemaExport(Configuration cfg) { - return new SchemaExport( serviceRegistry, cfg ); + protected SchemaExport createSchemaExport(MetadataImplementor metadata) { + return new SchemaExport( metadata ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportTest.java b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportTest.java index 8c31fdbc7f5d..4752f6d0a527 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/schemaupdate/SchemaExportTest.java @@ -23,18 +23,16 @@ */ package org.hibernate.test.schemaupdate; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Before; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -44,34 +42,28 @@ public abstract class SchemaExportTest extends BaseUnitTestCase { private final String MAPPING = "org/hibernate/test/schemaupdate/mapping.hbm.xml"; - protected abstract SchemaExport createSchemaExport(Configuration cfg); + protected abstract SchemaExport createSchemaExport(MetadataImplementor metadata); private boolean doesDialectSupportDropTableIfExist() { return Dialect.getDialect().supportsIfExistsAfterTableName() || Dialect.getDialect() .supportsIfExistsBeforeTableName(); } - protected ServiceRegistry serviceRegistry; - @Before public void setUp() { - serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() ); - Configuration cfg = new Configuration(); - cfg.addResource( MAPPING ); - SchemaExport schemaExport = createSchemaExport( cfg ); + MetadataImplementor metadata = buildMetadata(); + SchemaExport schemaExport = createSchemaExport( metadata ); schemaExport.drop( true, true ); } - @After - public void tearDown() { - ServiceRegistryBuilder.destroy( serviceRegistry ); - serviceRegistry = null; + private MetadataImplementor buildMetadata() { + return (MetadataImplementor) new MetadataSources().addResource( MAPPING ).buildMetadata(); } - @Test + + @Test + @FailureExpectedWithNewMetamodel public void testCreateAndDropOnlyType() { - Configuration cfg = new Configuration(); - cfg.addResource( MAPPING ); - SchemaExport schemaExport = createSchemaExport( cfg ); + SchemaExport schemaExport = createSchemaExport( buildMetadata() ); // create w/o dropping first; (OK because tables don't exist yet schemaExport.execute( false, true, false, true ); // if ( doesDialectSupportDropTableIfExist() ) { @@ -84,6 +76,7 @@ public void testCreateAndDropOnlyType() { // (2 total) because the tables exist already // assertEquals( 0, schemaExport.getExceptions().size() ); schemaExport.execute( false, true, false, true ); + // metamodel : fails here. assertEquals( 2, schemaExport.getExceptions().size() ); // drop tables only schemaExport.execute( false, true, true, false ); @@ -92,9 +85,7 @@ public void testCreateAndDropOnlyType() { @Test public void testBothType() { - Configuration cfg = new Configuration(); - cfg.addResource( MAPPING ); - SchemaExport schemaExport = createSchemaExport( cfg ); + SchemaExport schemaExport = createSchemaExport( buildMetadata() ); // drop before create (nothing to drop yeT) schemaExport.execute( false, true, false, false ); if ( doesDialectSupportDropTableIfExist() ) { @@ -113,9 +104,7 @@ public void testBothType() { @Test public void testGenerateDdlToFile() { - Configuration cfg = new Configuration(); - cfg.addResource( MAPPING ); - SchemaExport schemaExport = createSchemaExport( cfg ); + SchemaExport schemaExport = createSchemaExport( buildMetadata() ); java.io.File outFile = new java.io.File("schema.ddl"); schemaExport.setOutputFile(outFile.getPath()); // do not script to console or export to database @@ -132,9 +121,7 @@ public void testGenerateDdlToFile() { @Test public void testCreateAndDrop() { - Configuration cfg = new Configuration(); - cfg.addResource( MAPPING ); - SchemaExport schemaExport = createSchemaExport( cfg ); + SchemaExport schemaExport = createSchemaExport( buildMetadata() ); // should drop before creating, but tables don't exist yet schemaExport.create( true, true ); if ( doesDialectSupportDropTableIfExist() ) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/schemavalidation/SynonymValidationTest.java b/hibernate-core/src/test/java/org/hibernate/test/schemavalidation/SynonymValidationTest.java index b388d1396aa2..157fbb1d396e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/schemavalidation/SynonymValidationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/schemavalidation/SynonymValidationTest.java @@ -26,15 +26,15 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.hibernate.Session; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Oracle9iDialect; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.tool.hbm2ddl.SchemaValidator; import org.junit.Test; +import static org.junit.Assert.fail; + /** * Allows the BaseCoreFunctionalTestCase to create the schema using TestEntity. The test method validates against an * identical entity, but using the synonym name. @@ -48,27 +48,30 @@ public class SynonymValidationTest extends BaseCoreFunctionalTestCase { protected Class[] getAnnotatedClasses() { return new Class[] { TestEntity.class }; } - + @Test + @FailureExpectedWithNewMetamodel public void testSynonymValidation() { - Session s = openSession(); - s.getTransaction().begin(); - s.createSQLQuery( "CREATE SYNONYM test_synonym FOR test_entity" ).executeUpdate(); - s.getTransaction().commit(); - s.close(); - - Configuration cfg = new Configuration(); - cfg.addAnnotatedClass( TestEntityWithSynonym.class ); - cfg.setProperty( AvailableSettings.ENABLE_SYNONYMS, "true" ); - - SchemaValidator schemaValidator = new SchemaValidator( cfg ); - schemaValidator.validate(); - - s = openSession(); - s.getTransaction().begin(); - s.createSQLQuery( "DROP SYNONYM test_synonym FORCE" ).executeUpdate(); - s.getTransaction().commit(); - s.close(); + fail( "Needs to be implemented for new SchemaValidator" ); +// +// Session s = openSession(); +// s.getTransaction().begin(); +// s.createSQLQuery( "CREATE SYNONYM test_synonym FOR test_entity" ).executeUpdate(); +// s.getTransaction().commit(); +// s.close(); +// +// Configuration cfg = new Configuration(); +// cfg.addAnnotatedClass( TestEntityWithSynonym.class ); +// cfg.setProperty( AvailableSettings.ENABLE_SYNONYMS, "true" ); +// +// SchemaValidator schemaValidator = new SchemaValidator( cfg ); +// schemaValidator.validate(); +// +// s = openSession(); +// s.getTransaction().begin(); +// s.createSQLQuery( "DROP SYNONYM test_synonym FORCE" ).executeUpdate(); +// s.getTransaction().commit(); +// s.close(); } @Entity diff --git a/hibernate-core/src/test/java/org/hibernate/test/serialization/TypedValueSerializationTest.java b/hibernate-core/src/test/java/org/hibernate/test/serialization/TypedValueSerializationTest.java new file mode 100644 index 000000000000..3518ef238255 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/serialization/TypedValueSerializationTest.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.serialization; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.hibernate.engine.spi.TypedValue; +import org.hibernate.testing.TestForIssue; +import org.hibernate.type.Type; +import org.junit.Test; + +/** + * @author Brett Meyer + */ +public class TypedValueSerializationTest { + + @Test + @TestForIssue(jiraKey = "HHH-9024") + public void testTypedValueSerialization() throws Exception { + final Type mockType = mock(Type.class); + final String value = "foo"; + final TypedValue typedValue = new TypedValue(mockType, value); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(typedValue); + + final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); + final TypedValue typedValueClone = (TypedValue) ois.readObject(); + + assertEquals(typedValue.hashCode(), typedValueClone.hashCode()); + assertEquals(typedValue.toString(), typedValueClone.toString()); + assertEquals(typedValue.getValue(), typedValueClone.getValue()); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java b/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java index 1ff447eafb23..8aeb183f208d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java +++ b/hibernate-core/src/test/java/org/hibernate/test/service/TestIntegrator.java @@ -23,7 +23,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/sorted/SortTest.java b/hibernate-core/src/test/java/org/hibernate/test/sorted/SortTest.java index c78277ccb390..b63695cc2f21 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/sorted/SortTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/sorted/SortTest.java @@ -23,27 +23,46 @@ */ package org.hibernate.test.sorted; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; -import org.junit.Test; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import org.hibernate.FetchMode; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.annotations.SortNatural; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Gavin King + * @author Brett Meyer */ public class SortTest extends BaseCoreFunctionalTestCase { - public String[] getMappings() { + + @Override + protected String[] getMappings() { return new String[] { "sorted/Search.hbm.xml" }; } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Owner.class, Cat.class }; + } @Test @SuppressWarnings( {"unchecked"}) @@ -92,6 +111,68 @@ public void testOrderBy() { tx.commit(); sess.close(); } + + @Test + @TestForIssue(jiraKey = "HHH-8827") + public void testSortNatural() { + Session s = openSession(); + s.beginTransaction(); + + Owner owner = new Owner(); + Cat cat1 = new Cat(); + Cat cat2 = new Cat(); + cat1.owner = owner; + cat1.name = "B"; + cat2.owner = owner; + cat2.name = "A"; + owner.cats.add( cat1 ); + owner.cats.add( cat2 ); + s.persist( owner ); + + s.getTransaction().commit(); + s.clear(); + + s.beginTransaction(); + + owner = (Owner) s.get( Owner.class, owner.id ); + assertNotNull(owner.cats); + assertEquals(owner.cats.size(), 2); + assertEquals(owner.cats.first().name, "A"); + assertEquals(owner.cats.last().name, "B"); + + s.getTransaction().commit(); + s.close(); + } + + @Entity + private static class Owner { + + @Id + @GeneratedValue + private long id; + + @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL) + @SortNatural + private SortedSet cats = new TreeSet(); + } + + @Entity + private static class Cat implements Comparable { + + @Id + @GeneratedValue + private long id; + + @ManyToOne + private Owner owner; + + private String name; + + @Override + public int compareTo(Cat cat) { + return this.name.compareTo( cat.name ); + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java b/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java index d8346297f96e..84377f790cda 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/sql/hand/query/NativeSQLQueriesTest.java @@ -9,7 +9,6 @@ import java.util.Map; import org.junit.Test; - import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Query; @@ -22,6 +21,8 @@ import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.MySQL5Dialect; +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.test.sql.hand.Dimension; import org.hibernate.test.sql.hand.Employment; @@ -35,6 +36,7 @@ import org.hibernate.test.sql.hand.Speech; import org.hibernate.test.sql.hand.TextHolder; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -58,6 +60,7 @@ * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel public class NativeSQLQueriesTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "sql/hand/query/NativeSQLQueries.hbm.xml" }; @@ -141,6 +144,28 @@ public void testFailOnNoAddEntityOrScalar() { s.close(); } } + + @Test + public void testRegisteredNamedSQLQueryWithScalar() + { + final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder(); + builder.setName("namedQuery"); + builder.setQuery("select count(*) AS count from organization"); + builder.setQueryReturns(new NativeSQLQueryReturn[1]); + + sessionFactory().registerNamedSQLQueryDefinition("namedQuery", builder.createNamedQueryDefinition()); + + final Session s = openSession(); + s.beginTransaction(); + final SQLQuery query = (SQLQuery) s.getNamedQuery("namedQuery"); + query.addScalar("count"); + final Object result = query.uniqueResult(); + s.getTransaction().commit(); + s.close(); + + assertNotNull(result); + assertEquals(BigInteger.valueOf(0), result); + } @Test public void testManualSynchronization() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureResultSetMappingTest.java b/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureResultSetMappingTest.java index 5904e8b48a96..fd7cc3f35655 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureResultSetMappingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureResultSetMappingTest.java @@ -48,6 +48,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -131,7 +132,10 @@ public String sqlDropString(Dialect dialect, String defaultCatalog, String defau } @Test + @FailureExpectedWithNewMetamodel public void testPartialResults() { + // metamodel : seems AuxiliaryDatabaseObjects are not exported + Configuration cfg = new Configuration() .addAnnotatedClass( Employee.class ) .setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java b/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java index 493879b6d4b5..a3084e617f6c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java @@ -40,6 +40,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -182,6 +183,7 @@ public void baseTest() { } @Test + @FailureExpectedWithNewMetamodel public void testGetSingleResultTuple() { Session session = openSession(); session.beginTransaction(); @@ -201,6 +203,7 @@ public void testGetSingleResultTuple() { } @Test + @FailureExpectedWithNewMetamodel public void testGetResultListTuple() { Session session = openSession(); session.beginTransaction(); @@ -237,6 +240,7 @@ else if ( id.equals( 3 ) ) { // A warning should be logged if database metadata indicates named parameters are not supported. @Test + @FailureExpectedWithNewMetamodel public void testInParametersByName() { Session session = openSession(); session.beginTransaction(); @@ -262,6 +266,7 @@ public void testInParametersByName() { } @Test + @FailureExpectedWithNewMetamodel public void testInParametersByPosition() { Session session = openSession(); session.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/Mappings.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/Mappings.hbm.xml new file mode 100644 index 000000000000..8a2534b4ae1a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/Mappings.hbm.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/Message.java b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/Message.java new file mode 100644 index 000000000000..3cb0bf9b791c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/Message.java @@ -0,0 +1,35 @@ +package org.hibernate.test.stateless.insert; + +/** + * @author mukhanov@gmail.com + */ +public class Message { + + private String id; + private String subject; + private String content; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/MessageRecipient.java b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/MessageRecipient.java new file mode 100644 index 000000000000..a7b8d66a5e18 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/MessageRecipient.java @@ -0,0 +1,35 @@ +package org.hibernate.test.stateless.insert; + +/** + * @author mukhanov@gmail.com + */ +public class MessageRecipient { + + private String id; + private String email; + private Message message; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Message getMessage() { + return message; + } + + public void setMessage(Message message) { + this.message = message; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/StatelessSessionInsertTest.java b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/StatelessSessionInsertTest.java new file mode 100644 index 000000000000..c1b9e62333cc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/stateless/insert/StatelessSessionInsertTest.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009-2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.stateless.insert; + +import org.hibernate.Session; +import org.hibernate.StatelessSession; +import org.hibernate.Transaction; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.jboss.logging.Logger; +import org.junit.Test; + +/** + * @author mukhanov@gmail.com + */ +public class StatelessSessionInsertTest extends BaseCoreFunctionalTestCase { + private static final Logger log = Logger.getLogger(StatelessSessionInsertTest.class); + + @Override + public String[] getMappings() { + return new String[]{"stateless/insert/Mappings.hbm.xml"}; + } + + @Test + public void testInsertWithForeignKey() { + Session session = sessionFactory().openSession(); + Transaction tx = session.beginTransaction(); + + Message msg = new Message(); + final String messageId = "message_id"; + msg.setId(messageId); + msg.setContent("message_content"); + msg.setSubject("message_subject"); + session.save(msg); + + tx.commit(); + session.close(); + + StatelessSession statelessSession = sessionFactory().openStatelessSession(); + tx = statelessSession.beginTransaction(); + + MessageRecipient signature = new MessageRecipient(); + signature.setId("recipient"); + signature.setEmail("recipient@hibernate.org"); + signature.setMessage(msg); + statelessSession.insert(signature); + + tx.commit(); + + cleanup(); + } + + private void cleanup() { + Session s = openSession(); + s.beginTransaction(); + s.createQuery("delete MessageRecipient").executeUpdate(); + s.createQuery("delete Message").executeUpdate(); + s.getTransaction().commit(); + s.close(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/stats/StatsTest.java b/hibernate-core/src/test/java/org/hibernate/test/stats/StatsTest.java index 083eeb8d12d8..e8f8ea4bfa3f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/stats/StatsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/stats/StatsTest.java @@ -26,9 +26,6 @@ import java.util.HashSet; import java.util.Iterator; -import org.junit.Test; - -import org.hibernate.FetchMode; import org.hibernate.Hibernate; import org.hibernate.ScrollableResults; import org.hibernate.Session; @@ -36,12 +33,11 @@ import org.hibernate.Transaction; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Collection; import org.hibernate.stat.QueryStatistics; -import org.hibernate.stat.Statistics; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -63,107 +59,107 @@ private Configuration buildBaseConfiguration() { .setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ); } - @Test - @SuppressWarnings( {"UnusedAssignment"}) - public void testCollectionFetchVsLoad() throws Exception { - SessionFactory sf = buildBaseConfiguration() - .setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ) - .buildSessionFactory(); - - Session s = sf.openSession(); - Transaction tx = s.beginTransaction(); - Continent europe = fillDb(s); - tx.commit(); - s.close(); - - s = sf.openSession(); - tx = s.beginTransaction(); - assertEquals(0, sf.getStatistics().getCollectionLoadCount() ); - assertEquals(0, sf.getStatistics().getCollectionFetchCount() ); - Continent europe2 = (Continent) s.get( Continent.class, europe.getId() ); - assertEquals("Lazy true: no collection should be loaded", 0, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); - europe2.getCountries().size(); - assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); - assertEquals("Explicit fetch of the collection state", 1, sf.getStatistics().getCollectionFetchCount() ); - tx.commit(); - s.close(); - - sf.getStatistics().clear(); - - s = sf.openSession(); - tx = s.beginTransaction(); - europe = fillDb(s); - tx.commit(); - s.clear(); - tx = s.beginTransaction(); - assertEquals( 0, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); - europe2 = (Continent) s.createQuery( - "from " + Continent.class.getName() + " a join fetch a.countries where a.id = " + europe.getId() - ).uniqueResult(); - assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( "collection should be loaded in the same query as its parent", 0, sf.getStatistics().getCollectionFetchCount() ); - tx.commit(); - s.close(); - - // open a new SF - sf.close(); - Configuration cfg = buildBaseConfiguration().setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); - cfg.buildMappings(); - Collection coll = cfg.getCollectionMapping(Continent.class.getName() + ".countries"); - coll.setFetchMode(FetchMode.JOIN); - coll.setLazy(false); - sf = cfg.buildSessionFactory(); - - s = sf.openSession(); - tx = s.beginTransaction(); - europe = fillDb(s); - tx.commit(); - s.close(); - - s = sf.openSession(); - tx = s.beginTransaction(); - assertEquals( 0, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); - europe2 = (Continent) s.get( Continent.class, europe.getId() ); - assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( "Should do direct load, not indirect second load when lazy false and JOIN", 0, sf.getStatistics().getCollectionFetchCount() ); - tx.commit(); - s.close(); - sf.close(); - - // open yet another SF - sf.close(); - cfg = buildBaseConfiguration().setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); - cfg.buildMappings(); - coll = cfg.getCollectionMapping( Continent.class.getName() + ".countries" ); - coll.setFetchMode(FetchMode.SELECT); - coll.setLazy(false); - sf = cfg.buildSessionFactory(); - - s = sf.openSession(); - tx = s.beginTransaction(); - europe = fillDb(s); - tx.commit(); - s.close(); - - s = sf.openSession(); - tx = s.beginTransaction(); - assertEquals( 0, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); - europe2 = (Continent) s.get( Continent.class, europe.getId() ); - assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); - assertEquals( "Should do explicit collection load, not part of the first one", 1, sf.getStatistics().getCollectionFetchCount() ); - for ( Object o : europe2.getCountries() ) { - s.delete( o ); - } - cleanDb( s ); - tx.commit(); - s.close(); - - sf.close(); - } +// @Test +// @SuppressWarnings( {"UnusedAssignment"}) +// public void testCollectionFetchVsLoad() throws Exception { +// SessionFactory sf = buildBaseConfiguration() +// .setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ) +// .buildSessionFactory(); +// +// Session s = sf.openSession(); +// Transaction tx = s.beginTransaction(); +// Continent europe = fillDb(s); +// tx.commit(); +// s.close(); +// +// s = sf.openSession(); +// tx = s.beginTransaction(); +// assertEquals(0, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals(0, sf.getStatistics().getCollectionFetchCount() ); +// Continent europe2 = (Continent) s.get( Continent.class, europe.getId() ); +// assertEquals("Lazy true: no collection should be loaded", 0, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); +// europe2.getCountries().size(); +// assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals("Explicit fetch of the collection state", 1, sf.getStatistics().getCollectionFetchCount() ); +// tx.commit(); +// s.close(); +// +// sf.getStatistics().clear(); +// +// s = sf.openSession(); +// tx = s.beginTransaction(); +// europe = fillDb(s); +// tx.commit(); +// s.clear(); +// tx = s.beginTransaction(); +// assertEquals( 0, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); +// europe2 = (Continent) s.createQuery( +// "from " + Continent.class.getName() + " a join fetch a.countries where a.id = " + europe.getId() +// ).uniqueResult(); +// assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( "collection should be loaded in the same query as its parent", 0, sf.getStatistics().getCollectionFetchCount() ); +// tx.commit(); +// s.close(); +// +// // open a new SF +// sf.close(); +// Configuration cfg = buildBaseConfiguration().setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); +// cfg.buildMappings(); +// Collection coll = cfg.getCollectionMapping(Continent.class.getName() + ".countries"); +// coll.setFetchMode(FetchMode.JOIN); +// coll.setLazy(false); +// sf = cfg.buildSessionFactory(); +// +// s = sf.openSession(); +// tx = s.beginTransaction(); +// europe = fillDb(s); +// tx.commit(); +// s.close(); +// +// s = sf.openSession(); +// tx = s.beginTransaction(); +// assertEquals( 0, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); +// europe2 = (Continent) s.get( Continent.class, europe.getId() ); +// assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( "Should do direct load, not indirect second load when lazy false and JOIN", 0, sf.getStatistics().getCollectionFetchCount() ); +// tx.commit(); +// s.close(); +// sf.close(); +// +// // open yet another SF +// sf.close(); +// cfg = buildBaseConfiguration().setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); +// cfg.buildMappings(); +// coll = cfg.getCollectionMapping( Continent.class.getName() + ".countries" ); +// coll.setFetchMode(FetchMode.SELECT); +// coll.setLazy(false); +// sf = cfg.buildSessionFactory(); +// +// s = sf.openSession(); +// tx = s.beginTransaction(); +// europe = fillDb(s); +// tx.commit(); +// s.close(); +// +// s = sf.openSession(); +// tx = s.beginTransaction(); +// assertEquals( 0, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( 0, sf.getStatistics().getCollectionFetchCount() ); +// europe2 = (Continent) s.get( Continent.class, europe.getId() ); +// assertEquals( 1, sf.getStatistics().getCollectionLoadCount() ); +// assertEquals( "Should do explicit collection load, not part of the first one", 1, sf.getStatistics().getCollectionFetchCount() ); +// for ( Object o : europe2.getCountries() ) { +// s.delete( o ); +// } +// cleanDb( s ); +// tx.commit(); +// s.close(); +// +// sf.close(); +// } @Test public void testQueryStatGathering() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/subclassfilter/UnionSubclassFilterTest.java b/hibernate-core/src/test/java/org/hibernate/test/subclassfilter/UnionSubclassFilterTest.java index d79bf7aefb3a..4d0756c0555d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/subclassfilter/UnionSubclassFilterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/subclassfilter/UnionSubclassFilterTest.java @@ -32,6 +32,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -46,6 +47,7 @@ public final String[] getMappings() { @Test @SuppressWarnings( {"unchecked"}) + @FailureExpectedWithNewMetamodel public void testFiltersWithUnionSubclass() { Session s = openSession(); s.enableFilter( "region" ).setParameter( "userRegion", "US" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/subselect/SubselectTest.java b/hibernate-core/src/test/java/org/hibernate/test/subselect/SubselectTest.java index b35ede4292ba..8f24b8f37fc4 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/subselect/SubselectTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/subselect/SubselectTest.java @@ -30,6 +30,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class SubselectTest extends BaseCoreFunctionalTestCase { public String[] getMappings() { return new String[] { "subselect/Beings.hbm.xml" }; @@ -86,6 +88,7 @@ public void testEntitySubselect() { } @Test + @FailureExpectedWithNewMetamodel public void testCustomColumnReadAndWrite() { Session s = openSession(); Transaction t = s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java b/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java index d850a4f4f7c7..210c05a87dd8 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ternary/TernaryTest.java @@ -35,6 +35,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -45,6 +46,7 @@ /** * @author Gavin King */ +@FailureExpectedWithNewMetamodel public class TernaryTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java b/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java index 436c83e07070..5c8966ebcb42 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/tm/CMTTest.java @@ -40,6 +40,7 @@ import org.hibernate.criterion.Order; import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.jta.TestingJtaBootstrap; import org.hibernate.testing.jta.TestingJtaPlatformImpl; diff --git a/hibernate-core/src/test/java/org/hibernate/test/tm/TransactionTimeoutTest.java b/hibernate-core/src/test/java/org/hibernate/test/tm/TransactionTimeoutTest.java index 4328e6b3100a..22f90f31ce0d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/tm/TransactionTimeoutTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/tm/TransactionTimeoutTest.java @@ -30,7 +30,6 @@ import org.hibernate.Transaction; import org.hibernate.TransactionException; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.test.jdbc.Person; import org.hibernate.testing.SkipForDialect; @@ -42,7 +41,7 @@ * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-6780") -@SkipForDialect( value ={ PostgreSQL81Dialect.class, PostgreSQLDialect.class}, comment = "PostgreSQL jdbc driver doesn't impl timeout method") +@SkipForDialect( value ={ PostgreSQL81Dialect.class}, comment = "PostgreSQL jdbc driver doesn't impl timeout method") public class TransactionTimeoutTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java b/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java index 2826c9775615..9bb016170e74 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/type/AttributeConverterTest.java @@ -23,15 +23,8 @@ */ package org.hibernate.test.type; -import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; - import java.io.Serializable; import java.sql.Timestamp; -import java.sql.Types; import javax.persistence.AttributeConverter; import javax.persistence.Convert; @@ -39,24 +32,10 @@ import javax.persistence.Entity; import javax.persistence.Id; -import org.hibernate.IrrelevantEntity; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.AttributeConverterDefinition; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; -import org.hibernate.internal.util.ConfigHelper; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.SimpleValue; -import org.hibernate.testing.FailureExpected; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.type.AbstractStandardBasicType; -import org.hibernate.type.BasicType; -import org.hibernate.type.Type; -import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; -import org.hibernate.type.descriptor.java.StringTypeDescriptor; import org.junit.Test; /** @@ -66,188 +45,202 @@ */ public class AttributeConverterTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel public void testBasicOperation() { - Configuration cfg = new Configuration(); - SimpleValue simpleValue = new SimpleValue( cfg.createMappings() ); - simpleValue.setJpaAttributeConverterDefinition( - new AttributeConverterDefinition( new StringClobConverter(), true ) - ); - simpleValue.setTypeUsingReflection( IrrelevantEntity.class.getName(), "name" ); - - Type type = simpleValue.getType(); - assertNotNull( type ); - if ( ! AttributeConverterTypeAdapter.class.isInstance( type ) ) { - fail( "AttributeConverter not applied" ); - } - AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); - assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); - assertEquals( Types.CLOB, basicType.getSqlTypeDescriptor().getSqlType() ); + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// SimpleValue simpleValue = new SimpleValue( cfg.createMappings() ); +// simpleValue.setJpaAttributeConverterDefinition( +// new AttributeConverterDefinition( new StringClobConverter(), true ) +// ); +// simpleValue.setTypeUsingReflection( IrrelevantEntity.class.getName(), "name" ); +// +// Type type = simpleValue.getType(); +// assertNotNull( type ); +// if ( ! AttributeConverterTypeAdapter.class.isInstance( type ) ) { +// fail( "AttributeConverter not applied" ); +// } +// AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); +// assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); +// assertEquals( Types.CLOB, basicType.getSqlTypeDescriptor().getSqlType() ); } @Test + @FailureExpectedWithNewMetamodel public void testNonAutoApplyHandling() { - Configuration cfg = new Configuration(); - cfg.addAttributeConverter( NotAutoAppliedConverter.class, false ); - cfg.addAnnotatedClass( Tester.class ); - cfg.buildMappings(); - - PersistentClass tester = cfg.getClassMapping( Tester.class.getName() ); - Property nameProp = tester.getProperty( "name" ); - SimpleValue nameValue = (SimpleValue) nameProp.getValue(); - Type type = nameValue.getType(); - assertNotNull( type ); - if ( AttributeConverterTypeAdapter.class.isInstance( type ) ) { - fail( "AttributeConverter with autoApply=false was auto applied" ); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAttributeConverter( NotAutoAppliedConverter.class, false ); +// cfg.addAnnotatedClass( Tester.class ); +// cfg.buildMappings(); +// +// PersistentClass tester = cfg.getClassMapping( Tester.class.getName() ); +// Property nameProp = tester.getProperty( "name" ); +// SimpleValue nameValue = (SimpleValue) nameProp.getValue(); +// Type type = nameValue.getType(); +// assertNotNull( type ); +// if ( AttributeConverterTypeAdapter.class.isInstance( type ) ) { +// fail( "AttributeConverter with autoApply=false was auto applied" ); +// } } @Test + @FailureExpectedWithNewMetamodel public void testBasicConverterApplication() { - Configuration cfg = new Configuration(); - cfg.addAttributeConverter( StringClobConverter.class, true ); - cfg.addAnnotatedClass( Tester.class ); - cfg.buildMappings(); - - { - PersistentClass tester = cfg.getClassMapping( Tester.class.getName() ); - Property nameProp = tester.getProperty( "name" ); - SimpleValue nameValue = (SimpleValue) nameProp.getValue(); - Type type = nameValue.getType(); - assertNotNull( type ); - assertTyping( BasicType.class, type ); - if ( ! AttributeConverterTypeAdapter.class.isInstance( type ) ) { - fail( "AttributeConverter not applied" ); - } - AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); - assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); - assertEquals( Types.CLOB, basicType.getSqlTypeDescriptor().getSqlType() ); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAttributeConverter( StringClobConverter.class, true ); +// cfg.addAnnotatedClass( Tester.class ); +// cfg.buildMappings(); +// +// { +// PersistentClass tester = cfg.getClassMapping( Tester.class.getName() ); +// Property nameProp = tester.getProperty( "name" ); +// SimpleValue nameValue = (SimpleValue) nameProp.getValue(); +// Type type = nameValue.getType(); +// assertNotNull( type ); +// assertTyping( BasicType.class, type ); +// if ( ! AttributeConverterTypeAdapter.class.isInstance( type ) ) { +// fail( "AttributeConverter not applied" ); +// } +// AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); +// assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); +// assertEquals( Types.CLOB, basicType.getSqlTypeDescriptor().getSqlType() ); +// } } @Test @TestForIssue(jiraKey = "HHH-8462") + @FailureExpectedWithNewMetamodel public void testBasicOrmXmlConverterApplication() { - Configuration cfg = new Configuration(); - cfg.addAnnotatedClass( Tester.class ); - cfg.addURL( ConfigHelper.findAsResource( "org/hibernate/test/type/orm.xml") ); - cfg.buildMappings(); - - { - PersistentClass tester = cfg.getClassMapping( Tester.class.getName() ); - Property nameProp = tester.getProperty( "name" ); - SimpleValue nameValue = (SimpleValue) nameProp.getValue(); - Type type = nameValue.getType(); - assertNotNull( type ); - if ( ! AttributeConverterTypeAdapter.class.isInstance( type ) ) { - fail( "AttributeConverter not applied" ); - } - AttributeConverterTypeAdapter basicType = assertTyping( AttributeConverterTypeAdapter.class, type ); - assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); - assertEquals( Types.CLOB, basicType.getSqlTypeDescriptor().getSqlType() ); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAnnotatedClass( Tester.class ); +// cfg.addURL( ConfigHelper.findAsResource( "org/hibernate/test/type/orm.xml") ); +// cfg.buildMappings(); +// +// { +// PersistentClass tester = cfg.getClassMapping( Tester.class.getName() ); +// Property nameProp = tester.getProperty( "name" ); +// SimpleValue nameValue = (SimpleValue) nameProp.getValue(); +// Type type = nameValue.getType(); +// assertNotNull( type ); +// if ( ! AttributeConverterTypeAdapter.class.isInstance( type ) ) { +// fail( "AttributeConverter not applied" ); +// } +// AttributeConverterTypeAdapter basicType = assertTyping( AttributeConverterTypeAdapter.class, type ); +// assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); +// assertEquals( Types.CLOB, basicType.getSqlTypeDescriptor().getSqlType() ); +// } } @Test + @FailureExpectedWithNewMetamodel public void testBasicConverterDisableApplication() { - Configuration cfg = new Configuration(); - cfg.addAttributeConverter( StringClobConverter.class, true ); - cfg.addAnnotatedClass( Tester2.class ); - cfg.buildMappings(); - - { - PersistentClass tester = cfg.getClassMapping( Tester2.class.getName() ); - Property nameProp = tester.getProperty( "name" ); - SimpleValue nameValue = (SimpleValue) nameProp.getValue(); - Type type = nameValue.getType(); - assertNotNull( type ); - if ( AttributeConverterTypeAdapter.class.isInstance( type ) ) { - fail( "AttributeConverter applied (should not have been)" ); - } - AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); - assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); - assertEquals( Types.VARCHAR, basicType.getSqlTypeDescriptor().getSqlType() ); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAttributeConverter( StringClobConverter.class, true ); +// cfg.addAnnotatedClass( Tester2.class ); +// cfg.buildMappings(); +// +// { +// PersistentClass tester = cfg.getClassMapping( Tester2.class.getName() ); +// Property nameProp = tester.getProperty( "name" ); +// SimpleValue nameValue = (SimpleValue) nameProp.getValue(); +// Type type = nameValue.getType(); +// assertNotNull( type ); +// if ( AttributeConverterTypeAdapter.class.isInstance( type ) ) { +// fail( "AttributeConverter applied (should not have been)" ); +// } +// AbstractStandardBasicType basicType = assertTyping( AbstractStandardBasicType.class, type ); +// assertSame( StringTypeDescriptor.INSTANCE, basicType.getJavaTypeDescriptor() ); +// assertEquals( Types.VARCHAR, basicType.getSqlTypeDescriptor().getSqlType() ); +// } } @Test + @FailureExpectedWithNewMetamodel public void testBasicUsage() { - Configuration cfg = new Configuration(); - cfg.addAttributeConverter( IntegerToVarcharConverter.class, false ); - cfg.addAnnotatedClass( Tester4.class ); - cfg.setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); - cfg.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ); - - SessionFactory sf = cfg.buildSessionFactory(); - - try { - Session session = sf.openSession(); - session.beginTransaction(); - session.save( new Tester4( 1L, "steve", 200 ) ); - session.getTransaction().commit(); - session.close(); - - sf.getStatistics().clear(); - session = sf.openSession(); - session.beginTransaction(); - session.get( Tester4.class, 1L ); - session.getTransaction().commit(); - session.close(); - assertEquals( 0, sf.getStatistics().getEntityUpdateCount() ); - - session = sf.openSession(); - session.beginTransaction(); - Tester4 t4 = (Tester4) session.get( Tester4.class, 1L ); - t4.code = 300; - session.getTransaction().commit(); - session.close(); - - session = sf.openSession(); - session.beginTransaction(); - t4 = (Tester4) session.get( Tester4.class, 1L ); - assertEquals( 300, t4.code.longValue() ); - session.delete( t4 ); - session.getTransaction().commit(); - session.close(); - } - finally { - sf.close(); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAttributeConverter( IntegerToVarcharConverter.class, false ); +// cfg.addAnnotatedClass( Tester4.class ); +// cfg.setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); +// cfg.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ); +// +// SessionFactory sf = cfg.buildSessionFactory(); +// +// try { +// Session session = sf.openSession(); +// session.beginTransaction(); +// session.save( new Tester4( 1L, "steve", 200 ) ); +// session.getTransaction().commit(); +// session.close(); +// +// sf.getStatistics().clear(); +// session = sf.openSession(); +// session.beginTransaction(); +// session.get( Tester4.class, 1L ); +// session.getTransaction().commit(); +// session.close(); +// assertEquals( 0, sf.getStatistics().getEntityUpdateCount() ); +// +// session = sf.openSession(); +// session.beginTransaction(); +// Tester4 t4 = (Tester4) session.get( Tester4.class, 1L ); +// t4.code = 300; +// session.getTransaction().commit(); +// session.close(); +// +// session = sf.openSession(); +// session.beginTransaction(); +// t4 = (Tester4) session.get( Tester4.class, 1L ); +// assertEquals( 300, t4.code.longValue() ); +// session.delete( t4 ); +// session.getTransaction().commit(); +// session.close(); +// } +// finally { +// sf.close(); +// } } @Test + @FailureExpectedWithNewMetamodel public void testBasicTimestampUsage() { - Configuration cfg = new Configuration(); - cfg.addAttributeConverter( InstantConverter.class, false ); - cfg.addAnnotatedClass( IrrelevantInstantEntity.class ); - cfg.setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); - cfg.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ); - - SessionFactory sf = cfg.buildSessionFactory(); - - try { - Session session = sf.openSession(); - session.beginTransaction(); - session.save( new IrrelevantInstantEntity( 1L ) ); - session.getTransaction().commit(); - session.close(); - - sf.getStatistics().clear(); - session = sf.openSession(); - session.beginTransaction(); - IrrelevantInstantEntity e = (IrrelevantInstantEntity) session.get( IrrelevantInstantEntity.class, 1L ); - session.getTransaction().commit(); - session.close(); - assertEquals( 0, sf.getStatistics().getEntityUpdateCount() ); - - session = sf.openSession(); - session.beginTransaction(); - session.delete( e ); - session.getTransaction().commit(); - session.close(); - } - finally { - sf.close(); - } + throw new NotYetImplementedException( "Not implemented using new metamodel." ); +// Configuration cfg = new Configuration(); +// cfg.addAttributeConverter( InstantConverter.class, false ); +// cfg.addAnnotatedClass( IrrelevantInstantEntity.class ); +// cfg.setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); +// cfg.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ); +// +// SessionFactory sf = cfg.buildSessionFactory(); +// +// try { +// Session session = sf.openSession(); +// session.beginTransaction(); +// session.save( new IrrelevantInstantEntity( 1L ) ); +// session.getTransaction().commit(); +// session.close(); +// +// sf.getStatistics().clear(); +// session = sf.openSession(); +// session.beginTransaction(); +// IrrelevantInstantEntity e = (IrrelevantInstantEntity) session.get( IrrelevantInstantEntity.class, 1L ); +// session.getTransaction().commit(); +// session.close(); +// assertEquals( 0, sf.getStatistics().getEntityUpdateCount() ); +// +// session = sf.openSession(); +// session.beginTransaction(); +// session.delete( e ); +// session.getTransaction().commit(); +// session.close(); +// } +// finally { +// sf.close(); +// } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java index 8ecd2d3ab00e..7f095263ec60 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/typedmanytoone/TypedManyToOneTest.java @@ -30,6 +30,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import static org.junit.Assert.assertEquals; @@ -46,6 +47,7 @@ public String[] getMappings() { } @Test + @FailureExpectedWithNewMetamodel public void testCreateQuery() { Customer cust = new Customer(); cust.setCustomerId("abc123"); diff --git a/hibernate-core/src/test/java/org/hibernate/test/typeoverride/TypeOverrideTest.java b/hibernate-core/src/test/java/org/hibernate/test/typeoverride/TypeOverrideTest.java index dc50c6123fdf..f0b84dc5979f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/typeoverride/TypeOverrideTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/typeoverride/TypeOverrideTest.java @@ -32,7 +32,6 @@ import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SybaseASE15Dialect; import org.hibernate.dialect.SybaseDialect; import org.hibernate.testing.SkipForDialect; @@ -63,7 +62,7 @@ public void testStandardBasicSqlTypeDescriptor() { assertSame( IntegerTypeDescriptor.INSTANCE, remapSqlTypeDescriptor( IntegerTypeDescriptor.INSTANCE ) ); // A few dialects explicitly override BlobTypeDescriptor.DEFAULT - if ( PostgreSQL81Dialect.class.isInstance( getDialect() ) || PostgreSQLDialect.class.isInstance( getDialect() ) ) { + if ( PostgreSQL81Dialect.class.isInstance( getDialect() ) ) { assertSame( BlobTypeDescriptor.BLOB_BINDING, getDialect().remapSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT ) diff --git a/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java b/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java index da743cba9469..db11771289cf 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/unconstrained/UnconstrainedTest.java @@ -23,7 +23,9 @@ */ package org.hibernate.test.unconstrained; -import org.junit.Test; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import org.hibernate.FetchMode; import org.hibernate.Hibernate; @@ -31,10 +33,7 @@ import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Gavin King diff --git a/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java b/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java index 8b815b8df0c2..352fb36659dc 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java +++ b/hibernate-core/src/test/java/org/hibernate/test/util/SchemaUtil.java @@ -24,38 +24,186 @@ package org.hibernate.test.util; import java.util.Iterator; -import org.hibernate.cfg.Configuration; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.AssertionFailure; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.UniqueKey; /** * Check that the Hibernate metamodel contains some database objects * * @author Emmanuel Bernard + * @author Brett Meyer */ -public abstract class SchemaUtil { - public static boolean isColumnPresent(String tableName, String columnName, Configuration cfg) { - final Iterator
    tables = cfg.getTableMappings(); - while (tables.hasNext()) { - Table table = tables.next(); - if (tableName.equals( table.getName() ) ) { - Iterator columns = (Iterator) table.getColumnIterator(); - while ( columns.hasNext() ) { - Column column = columns.next(); - if ( columnName.equals( column.getName() ) ) { - return true; +public class SchemaUtil { + + private SchemaUtil() {} + + public static boolean isColumnPresent(String tableName, String columnName, MetadataImplementor metadata) { + try { + TableSpecification table = getTable( tableName, metadata ); + return ( table.locateColumn( columnName ) != null ); + } + catch ( AssertionFailure e ) { + return false; + } + } + + public static boolean isTablePresent(String tableName, MetadataImplementor metadata) { + try { + TableSpecification table = getTable( tableName, metadata ); + return ( table != null ); + } + catch ( AssertionFailure e ) { + return false; + } + } + + public static TableSpecification getTable(Class entityClass, MetadataImplementor metadata) + throws AssertionFailure { + return metadata.getEntityBinding( entityClass.getName() ).getPrimaryTable(); + } + + public static TableSpecification getTable(String tableName, MetadataImplementor metadata) throws AssertionFailure { + Iterable schemas = metadata.getDatabase().getSchemas(); + for ( Schema schema : schemas ) { + TableSpecification table = schema.locateTable( Identifier.toIdentifier( tableName ) ); + if ( table != null ) { + return table; + } + } + throw new AssertionFailure( "can't find table " + tableName ); + } + + public static org.hibernate.metamodel.spi.relational.Column getColumn(Class entityClass, String columnName, MetadataImplementor metadata) + throws AssertionFailure { + return getTable( entityClass, metadata ).locateColumn( columnName ); + } + + public static PrimaryKey getPrimaryKey(Class entityClass, MetadataImplementor metadata) throws AssertionFailure { + return getTable( entityClass, metadata ).getPrimaryKey(); + } + + // TODO: this is not a "schema" method; this should be in MetadataImplmentor + public static PluralAttributeBinding getCollection(Class entityClass, String fieldName, Metadata metadata) { + Iterator collectionBindings = metadata.getCollectionBindings().iterator(); + while ( collectionBindings.hasNext() ) { + PluralAttributeBinding collectionBinding = collectionBindings.next(); + if ( collectionBinding.getAttribute().getName().equals( fieldName ) ) { + final String collectionOwnerName = collectionBinding.getAttribute() + .getAttributeContainer() + .getDescriptor() + .getName() + .toString(); + if ( entityClass.getName().equals( collectionOwnerName ) ) { + return collectionBinding; + } + } + } + return null; + } + + public static TableSpecification getCollectionTable(Class entityClass, String fieldName, Metadata metadata) { + PluralAttributeBinding collection = getCollection( entityClass, fieldName, metadata ); + return collection.getPluralAttributeKeyBinding().getCollectionTable(); + } + + /** + * Do all of the given columns have associated UKs? + */ + public static boolean columnHasUniqueKey(TableSpecification table, String columnName) { + return table.hasUniqueKey( table.locateColumn( columnName ) ); + } + + public static boolean hasUniqueKey(TableSpecification table, String keyName) { + Identifier identifier = Identifier.toIdentifier( keyName ); + for ( UniqueKey uk : table.getUniqueKeys() ) { + if ( uk.getName().equals( identifier ) ) { + return true; + } + } + return false; + } + + /** + * Does a unique key exist with the given keyName containing the given columnNames *exclusively*? + * + * @param table + * @param keyName + * @param columnNames + * @return + */ + public static boolean hasUniqueKey(TableSpecification table, String keyName, String... columnNames) { + Identifier identifier = Identifier.toIdentifier( keyName ); + for ( UniqueKey uk : table.getUniqueKeys() ) { + if ( uk.getName().equals( identifier ) ) { + for (String columnName : columnNames) { + if (!uk.hasColumn( columnName )) { + return false; } + return columnNames.length == uk.getColumnSpan(); } } } return false; } - public static boolean isTablePresent(String tableName, Configuration cfg) { - final Iterator
    tables = cfg.getTableMappings(); - while (tables.hasNext()) { - Table table = tables.next(); - if (tableName.equals( table.getName() ) ) { + public static boolean hasForeignKey(TableSpecification table, String keyName) { + return table.locateForeignKey( keyName ) != null; + } + + public static boolean hasForeignKey(TableSpecification table, String keyName, String... columnNames) { + ForeignKey fk = table.locateForeignKey( keyName ); + if (fk == null) { + return false; + } + for (String columnName : columnNames) { + if (!fk.hasColumn( columnName )) { + return false; + } + } + return true; + } + + public static boolean hasIndex(TableSpecification table, String indexName) { + Identifier identifier = Identifier.toIdentifier( indexName ); + for ( Index index : table.getIndexes() ) { + if ( index.getName().equals( identifier ) ) { + return true; + } + } + return false; + } + + /** + * Does an exist with the given name containing the given columnNames *exclusively* & in order? + * + * @param table + * @param name + * @param columnNames + * @return + */ + public static boolean hasIndex(TableSpecification table, String name, String... columnNames) { + Identifier identifier = Identifier.toIdentifier( name ); + for ( Index index : table.getIndexes() ) { + if ( index.getName().equals( identifier ) ) { + if (columnNames.length != index.getColumnSpan()) { + return false; + } + + for (int i = 0; i < index.getColumnSpan(); i++) { + if (! index.getColumns().get( i ).getColumnName().getText().equals( columnNames[i] ) ) { + return false; + } + } + return true; } } diff --git a/hibernate-core/src/test/resources/log4j.properties b/hibernate-core/src/test/resources/log4j.properties index d406433daa98..3f5527f4066f 100644 --- a/hibernate-core/src/test/resources/log4j.properties +++ b/hibernate-core/src/test/resources/log4j.properties @@ -25,7 +25,6 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n -#log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L (hibernateLoadPlanWalkPath->%X{hibernateLoadPlanWalkPath}) - %m%n #log4j.appender.stdout-mdc=org.apache.log4j.ConsoleAppender #log4j.appender.stdout-mdc.Target=System.out @@ -56,4 +55,16 @@ log4j.logger.org.hibernate.loader.plan2.build.internal.LoadPlanImpl=debug log4j.logger.org.hibernate.loader.plan2.build.spi.LoadPlanTreePrinter=debug log4j.logger.org.hibernate.loader.plan2.exec.spi.EntityLoadQueryDetails=debug -log4j.logger.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=info \ No newline at end of file +log4j.logger.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=info + + + +## Used to direct certain log events (that indicate possible leaks from the test suite) to a file + +log4j.appender.leak=org.apache.log4j.FileAppender +log4j.appender.leak.File=target/logs/test-leaks.txt +log4j.appender.leak.Append=false +log4j.appender.leak.layout=org.apache.log4j.PatternLayout +log4j.appender.leak.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +log4j.logger.org.hibernate.testing.PossibleLeaksLogger=warn,leak \ No newline at end of file diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml new file mode 100644 index 000000000000..3b945f8c1ab2 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/User.hbm.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/AttributeOverride.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributeOverride.xml similarity index 78% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/AttributeOverride.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributeOverride.xml index b12d58305624..3ae71f37cff4 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/AttributeOverride.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AttributeOverride.xml @@ -1,14 +1,14 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + version="2.0"> - org.hibernate.metamodel.source.annotations.xml.mocker + org.hibernate.metamodel.internal.source.annotations.xml.mocker diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema.xml similarity index 75% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema.xml index 9a9689492faa..ff4246aa6982 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + version="2.0"> XML_SCHEMA diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema2.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema2.xml new file mode 100644 index 000000000000..c3a8da811ec9 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/default-schema2.xml @@ -0,0 +1,9 @@ + + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker + XML_SCHEMA + XML_CATALOG + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/entity-metadata-complete.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/entity-metadata-complete.xml new file mode 100644 index 000000000000..d5a507b89b21 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/entity-metadata-complete.xml @@ -0,0 +1,10 @@ + + + + org.hibernate.metamodel.internal.source.annotations.xml.mocker + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/listener.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/listener.xml similarity index 79% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/listener.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/listener.xml index 486798aef922..3a36c08035c2 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/listener.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/listener.xml @@ -8,17 +8,17 @@ FIELD - + - org.hibernate.metamodel.source.annotations.xml.mocker + org.hibernate.metamodel.internal.source.annotations.xml.mocker - + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/override-to-mappedsuperclass.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/override-to-mappedsuperclass.xml similarity index 86% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/override-to-mappedsuperclass.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/override-to-mappedsuperclass.xml index b2cc07b66420..a84268bacbc0 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/override-to-mappedsuperclass.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/override-to-mappedsuperclass.xml @@ -3,7 +3,7 @@ - org.hibernate.metamodel.source.annotations.xml.mocker + org.hibernate.metamodel.internal.source.annotations.xml.mocker diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/persistence-metadata.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/persistence-metadata.xml similarity index 93% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/persistence-metadata.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/persistence-metadata.xml index 766e7690f545..966a11114544 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/persistence-metadata.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/mocker/persistence-metadata.xml @@ -8,7 +8,7 @@ FIELD - + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-father.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml similarity index 84% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-father.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml index 04aa71fe58a7..38057ac22745 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-father.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-father.xml @@ -3,7 +3,7 @@ - org.hibernate.metamodel.source.annotations.xml + org.hibernate.metamodel.internal.source.annotations.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml similarity index 85% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml index 8709ce0741bd..0323af6cf141 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-invalid.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-invalid.xml @@ -3,7 +3,7 @@ - org.hibernate.metamodel.source.annotations.xml + org.hibernate.metamodel.internal.source.annotations.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-quote-identifier.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-quote-identifier.xml similarity index 100% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-quote-identifier.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-quote-identifier.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-star.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml similarity index 86% rename from hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-star.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml index b3ef07004995..d4eb5d63b316 100644 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/orm-star.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/internal/source/annotations/xml/orm-star.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> - org.hibernate.metamodel.source.annotations.xml + org.hibernate.metamodel.internal.source.annotations.xml diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema2.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema2.xml deleted file mode 100644 index 3d3c49d4492b..000000000000 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/default-schema2.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - org.hibernate.metamodel.source.annotations.xml.mocker - XML_SCHEMA - XML_CATALOG - diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/entity-metadata-complete.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/entity-metadata-complete.xml deleted file mode 100644 index f31ede708899..000000000000 --- a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/xml/mocker/entity-metadata-complete.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - org.hibernate.metamodel.source.annotations.xml.mocker - - - - diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml new file mode 100644 index 000000000000..328912bc3ed0 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithManyToOnes.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml new file mode 100644 index 000000000000..91498541f0ad --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/EntityWithUnidirectionalManyToManys.hbm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml new file mode 100644 index 000000000000..ee77f942d821 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntity.hbm.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml index af62001456da..48ff255aef93 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleEntityWithSimpleComponent.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleEntityWithSimpleComponent.hbm.xml @@ -3,7 +3,7 @@ xmlns="http://www.hibernate.org/xsd/hibernate-mapping" xsi:schemaLocation="http://www.hibernate.org/xsd/hibernate-mapping hibernate-mapping-4.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - package="org.hibernate.metamodel.binding"> + package="org.hibernate.metamodel.spi.binding"> diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml index 13425bf8d861..57e376c38523 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.hbm.xml @@ -22,7 +22,7 @@ ~ 51 Franklin Street, Fifth Floor ~ Boston, MA 02110-1301 USA --> - diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.xml rename to hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.xml index 24882262d18d..718c12aa7c3d 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleVersionedEntity.xml +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/SimpleVersionedEntity.xml @@ -22,7 +22,7 @@ ~ 51 Franklin Street, Fifth Floor ~ Boston, MA 02110-1301 USA --> - diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml new file mode 100644 index 000000000000..59e82776ea0a --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedDefaultValues.hbm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml new file mode 100644 index 000000000000..799d331e3147 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/UnsavedNonDefaultValues.hbm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml new file mode 100644 index 000000000000..99b330e29312 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/basiccollections/EntityWithBasicCollections.hbm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml new file mode 100644 index 000000000000..34e332a4b939 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/EntityWithUnidirectionalOneToMany.hbm.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml new file mode 100644 index 000000000000..66c44df1f065 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/binding/onetomany/ReferencedEntity.hbm.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml new file mode 100644 index 000000000000..6b7e8221c335 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/spi/relational/GeneratedIdColumn.hbm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-ehcache/hibernate-ehcache.gradle b/hibernate-ehcache/hibernate-ehcache.gradle index 492d4d6b2ba9..e18db8f2ba68 100644 --- a/hibernate-ehcache/hibernate-ehcache.gradle +++ b/hibernate-ehcache/hibernate-ehcache.gradle @@ -16,3 +16,7 @@ def pomDescription() { def osgiDescription() { return pomDescription() } + +test { + forkEvery 1 +} diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java index 0ac419141f83..1b22469c0811 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java @@ -41,7 +41,6 @@ import org.hibernate.cache.ehcache.internal.regions.EhcacheTimestampsRegion; import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory; import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactoryImpl; -import org.hibernate.cache.ehcache.internal.util.HibernateEhcacheUtils; import org.hibernate.cache.ehcache.management.impl.ProviderMBeanRegistrationHelper; import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.cache.spi.CollectionRegion; @@ -181,7 +180,6 @@ private Ehcache getCache(String name) throws CacheException { cache = manager.getEhcache( name ); LOG.debug( "started EHCache region: " + name ); } - HibernateEhcacheUtils.validateEhcache( cache ); return cache; } catch (net.sf.ehcache.CacheException e) { diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/util/HibernateEhcacheUtils.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/util/HibernateEhcacheUtils.java index 2e5ddb613bfa..0a9798023c21 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/util/HibernateEhcacheUtils.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/util/HibernateEhcacheUtils.java @@ -25,20 +25,15 @@ import java.net.URL; -import net.sf.ehcache.Ehcache; import net.sf.ehcache.config.CacheConfiguration; import net.sf.ehcache.config.Configuration; import net.sf.ehcache.config.ConfigurationFactory; import net.sf.ehcache.config.NonstopConfiguration; -import net.sf.ehcache.config.TerracottaConfiguration; -import net.sf.ehcache.config.TerracottaConfiguration.ValueMode; import net.sf.ehcache.config.TimeoutBehaviorConfiguration.TimeoutBehaviorType; +import org.jboss.logging.Logger; -import org.hibernate.cache.CacheException; import org.hibernate.cache.ehcache.EhCacheMessageLogger; -import org.jboss.logging.Logger; - /** * Copy of Ehcache utils into Hibernate code base @@ -73,16 +68,9 @@ public static Configuration loadAndCorrectConfiguration(URL url) { if ( config == null ) { return null; } - + if ( config.getDefaultCacheConfiguration() != null && config.getDefaultCacheConfiguration().isTerracottaClustered() ) { - if ( ValueMode.IDENTITY - .equals( config.getDefaultCacheConfiguration().getTerracottaConfiguration().getValueMode() ) ) { - LOG.incompatibleCacheValueMode(); - config.getDefaultCacheConfiguration() - .getTerracottaConfiguration() - .setValueMode( ValueMode.SERIALIZATION.name() ); - } setupHibernateTimeoutBehavior( config.getDefaultCacheConfiguration() .getTerracottaConfiguration() @@ -92,10 +80,6 @@ public static Configuration loadAndCorrectConfiguration(URL url) { for ( CacheConfiguration cacheConfig : config.getCacheConfigurations().values() ) { if ( cacheConfig.isTerracottaClustered() ) { - if ( ValueMode.IDENTITY.equals( cacheConfig.getTerracottaConfiguration().getValueMode() ) ) { - LOG.incompatibleCacheValueModePerCache( cacheConfig.getName() ); - cacheConfig.getTerracottaConfiguration().setValueMode( ValueMode.SERIALIZATION.name() ); - } setupHibernateTimeoutBehavior( cacheConfig.getTerracottaConfiguration().getNonstopConfiguration() ); } } @@ -105,32 +89,4 @@ public static Configuration loadAndCorrectConfiguration(URL url) { private static void setupHibernateTimeoutBehavior(NonstopConfiguration nonstopConfig) { nonstopConfig.getTimeoutBehavior().setType( TimeoutBehaviorType.EXCEPTION.getTypeName() ); } - - /** - * Validates that the supplied Ehcache instance is valid for use as a Hibernate cache. - * - * @param cache The cache instance - * - * @throws CacheException If any explicit settings on the cache are not validate - */ - public static void validateEhcache(Ehcache cache) throws CacheException { - final CacheConfiguration cacheConfig = cache.getCacheConfiguration(); - - if ( cacheConfig.isTerracottaClustered() ) { - final TerracottaConfiguration tcConfig = cacheConfig.getTerracottaConfiguration(); - switch ( tcConfig.getValueMode() ) { - case IDENTITY: { - throw new CacheException( - "The clustered Hibernate cache " + cache.getName() + " is using IDENTITY value mode.\n" - + "Identity value mode cannot be used with Hibernate cache regions." - ); - } - case SERIALIZATION: - default: { - // this is the recommended valueMode - break; - } - } - } - } } diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheHibernate.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheHibernate.java index 009e7035c15c..b9ecfb00448c 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheHibernate.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheHibernate.java @@ -97,11 +97,9 @@ public boolean isHibernateStatisticsSupported() { @Override public void setStatisticsEnabled(boolean flag) { if ( flag ) { - ehcacheStats.enableStats(); hibernateStats.enableStats(); } else { - ehcacheStats.disableStats(); hibernateStats.disableStats(); } statsEnabled.set( flag ); @@ -121,7 +119,6 @@ public boolean isStatisticsEnabled() { */ @Override public void clearStats() { - ehcacheStats.clearStats(); hibernateStats.clearStats(); } diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheStatsImpl.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheStatsImpl.java index 4fc433bad3b2..26ed40fecf5a 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheStatsImpl.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/management/impl/EhcacheStatsImpl.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.management.MBeanNotificationInfo; import javax.management.NotCompliantMBeanException; import javax.management.Notification; @@ -33,7 +34,6 @@ import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.hibernate.management.api.EhcacheStats; -import net.sf.ehcache.management.sampled.SampledCacheManager; /** * Implementation of {@link EhcacheStats} @@ -46,7 +46,6 @@ public class EhcacheStatsImpl extends AbstractEmitterBean implements EhcacheStat private static final long MILLIS_PER_SECOND = 1000; private static final MBeanNotificationInfo NOTIFICATION_INFO; - private final SampledCacheManager sampledCacheManager; private final CacheManager cacheManager; private long statsSince = System.currentTimeMillis(); @@ -64,35 +63,14 @@ public class EhcacheStatsImpl extends AbstractEmitterBean implements EhcacheStat * Constructor accepting the backing {@link CacheManager} * * @param manager The {@link CacheManager} to expose stats for + * * @throws javax.management.NotCompliantMBeanException should registering the MBean fail */ public EhcacheStatsImpl(CacheManager manager) throws NotCompliantMBeanException { super( EhcacheStats.class ); - this.sampledCacheManager = new SampledCacheManager( manager ); this.cacheManager = manager; } - @Override - public boolean isStatisticsEnabled() { - return false; - } - - @Override - public void clearStats() { - sampledCacheManager.clearStatistics(); - statsSince = System.currentTimeMillis(); - } - - @Override - public void disableStats() { - setStatisticsEnabled( false ); - } - - @Override - public void enableStats() { - setStatisticsEnabled( true ); - } - @Override public void flushRegionCache(String region) { final Cache cache = this.cacheManager.getCache( region ); @@ -127,7 +105,7 @@ public long getCacheHitCount() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { - count += cache.getLiveCacheStatistics().getCacheHitCount(); + count += cache.getStatistics().cacheHitCount(); } } return count; @@ -136,7 +114,7 @@ public long getCacheHitCount() { @Override public double getCacheHitRate() { final long now = System.currentTimeMillis(); - final double deltaSecs = (double) (now - statsSince) / MILLIS_PER_SECOND; + final double deltaSecs = (double) ( now - statsSince ) / MILLIS_PER_SECOND; return getCacheHitCount() / deltaSecs; } @@ -146,7 +124,7 @@ public long getCacheHitSample() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { - count += cache.getSampledCacheStatistics().getCacheHitMostRecentSample(); + count += cache.getStatistics().cacheHitOperation().rate().value().longValue(); } } return count; @@ -158,7 +136,7 @@ public long getCacheMissCount() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { - count += cache.getLiveCacheStatistics().getCacheMissCount(); + count += cache.getStatistics().cacheMissCount(); } } return count; @@ -167,7 +145,7 @@ public long getCacheMissCount() { @Override public double getCacheMissRate() { final long now = System.currentTimeMillis(); - final double deltaSecs = (double) (now - statsSince) / MILLIS_PER_SECOND; + final double deltaSecs = (double) ( now - statsSince ) / MILLIS_PER_SECOND; return getCacheMissCount() / deltaSecs; } @@ -177,7 +155,7 @@ public long getCacheMissSample() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { - count += cache.getSampledCacheStatistics().getCacheMissMostRecentSample(); + count += cache.getStatistics().cacheMissOperation().rate().value().longValue(); } } return count; @@ -189,7 +167,7 @@ public long getCachePutCount() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { - count += cache.getLiveCacheStatistics().getPutCount(); + count += cache.getStatistics().cachePutCount(); } } return count; @@ -198,7 +176,7 @@ public long getCachePutCount() { @Override public double getCachePutRate() { final long now = System.currentTimeMillis(); - final double deltaSecs = (double) (now - statsSince) / MILLIS_PER_SECOND; + final double deltaSecs = (double) ( now - statsSince ) / MILLIS_PER_SECOND; return getCachePutCount() / deltaSecs; } @@ -208,7 +186,7 @@ public long getCachePutSample() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { - count += cache.getSampledCacheStatistics().getCacheElementPutMostRecentSample(); + count += cache.getStatistics().cachePutOperation().rate().value().longValue(); } } return count; @@ -286,12 +264,16 @@ public Map getRegionCacheSamples() { for ( String name : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( name ); if ( cache != null ) { + final Double hits = cache.getStatistics().cacheHitOperation().rate().value(); + final Double misses = cache.getStatistics().cacheMissNotFoundOperation().rate().value(); + final Double expired = cache.getStatistics().cacheMissExpiredOperation().rate().value(); + final Double puts = cache.getStatistics().cachePutOperation().rate().value(); rv.put( name, new int[] { - (int) cache.getSampledCacheStatistics().getCacheHitMostRecentSample(), - (int) (cache.getSampledCacheStatistics().getCacheMissNotFoundMostRecentSample() - + cache.getSampledCacheStatistics().getCacheMissExpiredMostRecentSample()), - (int) cache.getSampledCacheStatistics().getCacheElementPutMostRecentSample(), + hits.intValue(), + misses.intValue(), + expired.intValue(), + puts.intValue() } ); } @@ -332,7 +314,7 @@ public String[] getTerracottaHibernateCacheRegionNames() { } } } - return rv.toArray( new String[ rv.size() ] ); + return rv.toArray( new String[rv.size()] ); } @Override @@ -472,27 +454,22 @@ public int getNumberOfElementsOnDisk(String region) { } } - @Override - public void setStatisticsEnabled(boolean flag) { - for ( String cacheName : cacheManager.getCacheNames() ) { - final Cache cache = cacheManager.getCache( cacheName ); - if ( cache != null ) { - cache.setStatisticsEnabled( flag ); - } - } - if ( flag ) { - clearStats(); - } - sendNotification( CACHE_STATISTICS_ENABLED, flag ); - } - @Override public long getMaxGetTimeMillis() { long rv = 0; for ( String cacheName : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( cacheName ); if ( cache != null ) { - rv = Math.max( rv, cache.getLiveCacheStatistics().getMaxGetTimeMillis() ); + final Long maximum = cache.getStatistics() + .cacheGetOperation().latency().maximum().value(); + if ( maximum != null ) { + rv = Math.max( + rv, TimeUnit.MILLISECONDS.convert( + maximum, + TimeUnit.NANOSECONDS + ) + ); + } } } return rv; @@ -500,21 +477,39 @@ public long getMaxGetTimeMillis() { @Override public long getMinGetTimeMillis() { - long rv = 0; + long rv = Long.MAX_VALUE; for ( String cacheName : cacheManager.getCacheNames() ) { final Cache cache = cacheManager.getCache( cacheName ); if ( cache != null ) { - rv = Math.max( rv, cache.getLiveCacheStatistics().getMinGetTimeMillis() ); + final Long minimum = cache.getStatistics() + .cacheGetOperation() + .latency() + .minimum().value(); + if ( minimum != null ) { + rv = Math.min( + rv, TimeUnit.MILLISECONDS.convert( + minimum, + TimeUnit.NANOSECONDS + ) + ); + } } } - return rv; + return rv == Long.MAX_VALUE ? 0 : rv; } @Override public long getMaxGetTimeMillis(String cacheName) { final Cache cache = cacheManager.getCache( cacheName ); if ( cache != null ) { - return cache.getLiveCacheStatistics().getMaxGetTimeMillis(); + final Long maximum = cache.getStatistics() + .cacheGetOperation() + .latency() + .maximum().value(); + return maximum == null ? 0 : TimeUnit.MILLISECONDS.convert( + maximum, + TimeUnit.NANOSECONDS + ); } else { return 0; @@ -525,7 +520,14 @@ public long getMaxGetTimeMillis(String cacheName) { public long getMinGetTimeMillis(String cacheName) { final Cache cache = cacheManager.getCache( cacheName ); if ( cache != null ) { - return cache.getLiveCacheStatistics().getMinGetTimeMillis(); + final Long minimum = cache.getStatistics() + .cacheGetOperation() + .latency() + .minimum().value(); + return minimum == null ? 0 : TimeUnit.MILLISECONDS.convert( + minimum, + TimeUnit.NANOSECONDS + ); } else { return 0; @@ -536,7 +538,14 @@ public long getMinGetTimeMillis(String cacheName) { public float getAverageGetTimeMillis(String region) { final Cache cache = this.cacheManager.getCache( region ); if ( cache != null ) { - return cache.getLiveCacheStatistics().getAverageGetTimeMillis(); + final Double avg = cache.getStatistics() + .cacheGetOperation() + .latency() + .average().value(); + return TimeUnit.MILLISECONDS.convert( + avg.longValue(), + TimeUnit.NANOSECONDS + ); } else { return -1f; @@ -550,6 +559,6 @@ protected void doDispose() { @Override public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[] {NOTIFICATION_INFO}; + return new MBeanNotificationInfo[] { NOTIFICATION_INFO }; } } diff --git a/hibernate-ehcache/src/test/java/org/hibernate/test/cache/EhcacheStatsImplTest.java b/hibernate-ehcache/src/test/java/org/hibernate/test/cache/EhcacheStatsImplTest.java index be342b548186..a5c6f0cf3479 100644 --- a/hibernate-ehcache/src/test/java/org/hibernate/test/cache/EhcacheStatsImplTest.java +++ b/hibernate-ehcache/src/test/java/org/hibernate/test/cache/EhcacheStatsImplTest.java @@ -1,11 +1,13 @@ package org.hibernate.test.cache; import net.sf.ehcache.CacheManager; -import org.junit.BeforeClass; -import org.junit.Test; import org.hibernate.cache.ehcache.management.impl.EhcacheStatsImpl; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -13,13 +15,19 @@ * @author Alex Snaps */ public class EhcacheStatsImplTest { - + private static CacheManager manager; private static EhcacheStatsImpl stats; @BeforeClass public static void createCache() throws Exception { - CacheManager manager = CacheManager.getInstance(); + manager = CacheManager.getInstance(); stats = new EhcacheStatsImpl( manager ); + + } + + @AfterClass + public static void stopCache() { + manager.shutdown(); } @Test diff --git a/hibernate-ehcache/src/test/java/org/hibernate/test/cache/HibernateCacheTest.java b/hibernate-ehcache/src/test/java/org/hibernate/test/cache/HibernateCacheTest.java index a8244b3ef1b0..d8fe3e320968 100644 --- a/hibernate-ehcache/src/test/java/org/hibernate/test/cache/HibernateCacheTest.java +++ b/hibernate-ehcache/src/test/java/org/hibernate/test/cache/HibernateCacheTest.java @@ -1,50 +1,72 @@ package org.hibernate.test.cache; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - import java.util.Date; import java.util.List; import java.util.Map; -import org.hamcrest.CoreMatchers; import org.hibernate.Session; +import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cache.ehcache.internal.strategy.ItemValueExtractor; import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.stat.QueryStatistics; import org.hibernate.stat.SecondLevelCacheStatistics; import org.hibernate.stat.Statistics; + +import org.hibernate.testing.AfterClassOnce; +import org.hibernate.testing.BeforeClassOnce; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.OnExpectedFailure; +import org.hibernate.testing.OnFailure; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.test.domain.Event; import org.hibernate.test.domain.EventManager; import org.hibernate.test.domain.Item; import org.hibernate.test.domain.Person; import org.hibernate.test.domain.PhoneNumber; import org.hibernate.test.domain.VersionedItem; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + /** * @author Chris Dennis * @author Brett Meyer */ -public class HibernateCacheTest extends BaseCoreFunctionalTestCase { +public class HibernateCacheTest extends BaseUnitTestCase { + private SessionFactory sessionFactory; - private static final String REGION_PREFIX = "hibernate.test."; - - @Override - protected void configure(Configuration config) { + @BeforeClassOnce + public void before() { System.setProperty( "derby.system.home", "target/derby" ); - config.configure( "hibernate-config/hibernate.cfg.xml" ); + sessionFactory = new Configuration() + .configure( "hibernate-config/hibernate.cfg.xml" ) + .setProperty( AvailableSettings.GENERATE_STATISTICS, "true" ) + .setProperty( AvailableSettings.HBM2DDL_AUTO, "create-drop" ) + .buildSessionFactory(); } - - @Override - protected void afterSessionFactoryBuilt() { - sessionFactory().getStatistics().setStatisticsEnabled( true ); + + @AfterClassOnce + public void after() { + if ( sessionFactory != null ) { + sessionFactory.close(); + } + } + + @OnFailure + @OnExpectedFailure + public void handleFailure() { + after(); + before(); } + private static final String REGION_PREFIX = "hibernate.test."; + @Test public void testQueryCacheInvalidation() throws Exception { Session s = sessionFactory().openSession(); @@ -97,6 +119,10 @@ public void testQueryCacheInvalidation() throws Exception { s.close(); } + private SessionFactory sessionFactory() { + return sessionFactory; + } + @Test public void testEmptySecondLevelCacheEntry() throws Exception { sessionFactory().evictEntity( Item.class.getName() ); @@ -154,7 +180,7 @@ public void testStaleWritesLeaveCacheConsistent() { // check the version value in the cache... SecondLevelCacheStatistics slcs = sessionFactory().getStatistics() .getSecondLevelCacheStatistics( REGION_PREFIX + VersionedItem.class.getName() ); - assertThat( slcs, CoreMatchers.notNullValue() ); + assertNotNull( slcs ); final Map entries = slcs.getEntries(); Object entry = entries.get( item.getId() ); Long cachedVersionValue; @@ -179,6 +205,10 @@ public void testStaleWritesLeaveCacheConsistent() { } @Test + @FailureExpectedWithNewMetamodel( + message="Attempts to bind too many jdbc parameters during insert of PhoneNumber; the issue " + + "is the mishandling of virtual attributes such as _identifierMapper and backrefs" + ) public void testGeneralUsage() { EventManager mgr = new EventManager( sessionFactory() ); Statistics stats = sessionFactory().getStatistics(); diff --git a/hibernate-entitymanager/hibernate-entitymanager.gradle b/hibernate-entitymanager/hibernate-entitymanager.gradle index 989291e4db4c..86ab4c52c949 100644 --- a/hibernate-entitymanager/hibernate-entitymanager.gradle +++ b/hibernate-entitymanager/hibernate-entitymanager.gradle @@ -32,6 +32,8 @@ dependencies { // for testing stored procedure support testCompile( libraries.derby ) + testCompile( 'joda-time:joda-time:2.3' ) + hibernateJpaModelGenTool( project( ':hibernate-jpamodelgen' ) ) } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java index 4c299a7adcd1..389ea5f6ec6a 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/HibernatePersistence.java @@ -81,7 +81,6 @@ public boolean generateSchema(String persistenceUnitName, Map map) { @Override public ProviderUtil getProviderUtil() { - logDeprecation(); return super.getProviderUtil(); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/HibernatePersistenceProvider.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/HibernatePersistenceProvider.java index 3df0fba8bc07..321eb41811ef 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/HibernatePersistenceProvider.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/HibernatePersistenceProvider.java @@ -34,9 +34,11 @@ import javax.persistence.spi.ProviderUtil; import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; +import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor; import org.hibernate.jpa.boot.internal.PersistenceXmlParser; import org.hibernate.jpa.boot.spi.Bootstrap; import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; +import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; import org.hibernate.jpa.boot.spi.ProviderChecker; import org.hibernate.jpa.internal.util.PersistenceUtilHelper; @@ -126,7 +128,7 @@ protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(Strin continue; } - return Bootstrap.getEntityManagerFactoryBuilder( persistenceUnit, integration, providedClassLoader ); + return getEntityManagerFactoryBuilder( persistenceUnit, integration, providedClassLoader ); } log.debug( "Found no matching persistence units" ); @@ -134,7 +136,7 @@ protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(Strin } @SuppressWarnings("unchecked") - private static Map wrap(Map properties) { + protected static Map wrap(Map properties) { return properties == null ? Collections.emptyMap() : Collections.unmodifiableMap( properties ); } @@ -147,14 +149,14 @@ private static Map wrap(Map properties) { public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) { log.tracef( "Starting createContainerEntityManagerFactory : %s", info.getPersistenceUnitName() ); - return Bootstrap.getEntityManagerFactoryBuilder( info, properties ).build(); + return getEntityManagerFactoryBuilder( info, properties ).build(); } @Override public void generateSchema(PersistenceUnitInfo info, Map map) { log.tracef( "Starting generateSchema : PUI.name=%s", info.getPersistenceUnitName() ); - final EntityManagerFactoryBuilder builder = Bootstrap.getEntityManagerFactoryBuilder( info, map ); + final EntityManagerFactoryBuilder builder = getEntityManagerFactoryBuilder( info, map ); builder.generateSchema(); } @@ -171,6 +173,15 @@ public boolean generateSchema(String persistenceUnitName, Map map) { return true; } + private EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitInfo info, Map integration) { + return getEntityManagerFactoryBuilder( new PersistenceUnitInfoDescriptor( info ), integration, null ); + } + + protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitDescriptor persistenceUnitDescriptor, + Map integration, ClassLoader providedClassLoader) { + return Bootstrap.getEntityManagerFactoryBuilder( persistenceUnitDescriptor, integration, providedClassLoader ); + } + private final ProviderUtil providerUtil = new ProviderUtil() { @Override public LoadState isLoadedWithoutReference(Object proxy, String property) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenAction.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenAction.java index 3590f9cf7462..7f8cf9e24f0b 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenAction.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenAction.java @@ -93,6 +93,14 @@ else if ( BOTH.externalName.equals( value ) ) { ); } + public static SchemaGenAction interpret(Object value) { + if ( SchemaGenAction.class.isInstance( value ) ) { + return (SchemaGenAction) value; + } + + return interpret( value == null ? null : value.toString() ); + } + /** * Does this action include creations? * diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenSource.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenSource.java index 78dfc2e75beb..2b7f3095a78d 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenSource.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/SchemaGenSource.java @@ -102,4 +102,12 @@ else if ( SCRIPT_THEN_METADATA.externalName.equals( value ) ) { throw new IllegalArgumentException( "Unrecognized schema generation source value : " + value ); } + + public static SchemaGenSource interpret(Object value) { + if ( SchemaGenSource.class.isInstance( value ) ) { + return (SchemaGenSource) value; + } + + return interpret( value == null ? null : value.toString() ); + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java index 5694e206a0a9..1870ebd05a39 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/archive/spi/AbstractArchiveDescriptor.java @@ -74,7 +74,7 @@ protected String getEntryBasePrefix() { protected String extractRelativeName(ZipEntry zipEntry) { final String entryName = extractName( zipEntry ); - return entryBasePrefix == null ? entryName : entryName.substring( entryBasePrefix.length() ); + return entryBasePrefix != null && entryName.contains( entryBasePrefix ) ? entryName.substring( entryBasePrefix.length() ) : entryName; } protected String extractName(ZipEntry zipEntry) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java index fd30a8b06246..3049b9976221 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java @@ -23,44 +23,35 @@ */ package org.hibernate.jpa.boot.internal; -import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.Serializable; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; import javax.persistence.AttributeConverter; import javax.persistence.EntityManagerFactory; -import javax.persistence.EntityNotFoundException; import javax.persistence.PersistenceException; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; import org.hibernate.Interceptor; -import org.hibernate.InvalidMappingException; -import org.hibernate.MappingException; -import org.hibernate.MappingNotFoundException; import org.hibernate.SessionFactory; import org.hibernate.SessionFactoryObserver; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.selector.StrategyRegistrationProvider; import org.hibernate.boot.registry.selector.spi.StrategySelector; -import org.hibernate.cfg.Configuration; +import org.hibernate.boot.spi.CacheRegionDefinition; import org.hibernate.cfg.Environment; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator; @@ -69,9 +60,9 @@ import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.ValueHolder; +import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.boot.scan.internal.StandardScanOptions; import org.hibernate.jpa.boot.scan.internal.StandardScanner; @@ -80,10 +71,8 @@ import org.hibernate.jpa.boot.scan.spi.Scanner; import org.hibernate.jpa.boot.spi.ClassDescriptor; import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; -import org.hibernate.jpa.boot.spi.InputStreamAccess; import org.hibernate.jpa.boot.spi.IntegratorProvider; import org.hibernate.jpa.boot.spi.MappingFileDescriptor; -import org.hibernate.jpa.boot.spi.NamedInputStream; import org.hibernate.jpa.boot.spi.PackageDescriptor; import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; import org.hibernate.jpa.boot.spi.StrategyRegistrationProviderList; @@ -95,24 +84,38 @@ import org.hibernate.jpa.internal.util.LogHelper; import org.hibernate.jpa.internal.util.PersistenceUnitTransactionTypeHelper; import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider; -import org.hibernate.metamodel.source.annotations.JPADotNames; -import org.hibernate.metamodel.source.annotations.JandexHelper; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.metamodel.spi.TypeContributor; -import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.secure.spi.GrantedPermission; +import org.hibernate.secure.spi.JaccPermissionDeclarations; import org.hibernate.secure.spi.JaccService; import org.hibernate.service.ConfigLoader; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.ServiceRegistryImplementor; -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.jboss.jandex.IndexView; -import org.jboss.jandex.Indexer; import org.jboss.logging.Logger; +import static org.hibernate.cfg.AvailableSettings.JACC_CONTEXT_ID; +import static org.hibernate.cfg.AvailableSettings.JACC_PREFIX; +import static org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME; +import static org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration.JaxbSecurity.JaxbGrant; +import static org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache; +import static org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache; +import static org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping; +import static org.hibernate.jpa.AvailableSettings.CFG_FILE; +import static org.hibernate.jpa.AvailableSettings.CLASS_CACHE_PREFIX; +import static org.hibernate.jpa.AvailableSettings.COLLECTION_CACHE_PREFIX; +import static org.hibernate.jpa.AvailableSettings.DISCARD_PC_ON_CLOSE; +import static org.hibernate.jpa.AvailableSettings.PERSISTENCE_UNIT_NAME; +import static org.hibernate.jpa.AvailableSettings.SHARED_CACHE_MODE; +import static org.hibernate.jpa.AvailableSettings.VALIDATION_MODE; + /** * @author Steve Ebersole */ @@ -122,8 +125,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil EntityManagerFactoryBuilderImpl.class.getName() ); - private static final String META_INF_ORM_XML = "META-INF/orm.xml"; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // New settings @@ -153,34 +154,19 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil // Explicit "injectables" // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private Object validatorFactory; + private Object cdiBeanManager; private DataSource dataSource; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private final PersistenceUnitDescriptor persistenceUnit; - private final SettingsImpl settings = new SettingsImpl(); - private final StandardServiceRegistryBuilder serviceRegistryBuilder; - private final Map configurationValues; - - private final List grantedJaccPermissions = new ArrayList(); - private final List cacheRegionDefinitions = new ArrayList(); - // todo : would much prefer this as a local variable... - private final List cfgXmlNamedMappings = new ArrayList(); - private Interceptor sessionFactoryInterceptor; - private NamingStrategy namingStrategy; - private SessionFactoryObserver suppliedSessionFactoryObserver; - private MetadataSources metadataSources; - private Configuration hibernateConfiguration; - - private static EntityNotFoundDelegate jpaEntityNotFoundDelegate = new JpaEntityNotFoundDelegate(); - - private ClassLoader providedClassLoader; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // things built in first phase, needed for second phase.. + private final Map configurationValues; + private final StandardServiceRegistry standardServiceRegistry; + private final MetadataImplementor metadata; + private final SettingsImpl settings; - private static class JpaEntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable { - public void handleEntityNotFound(String entityName, Serializable id) { - throw new EntityNotFoundException( "Unable to find " + entityName + " with id " + id ); - } - } public EntityManagerFactoryBuilderImpl(PersistenceUnitDescriptor persistenceUnit, Map integrationSettings) { this( persistenceUnit, integrationSettings, null ); @@ -190,429 +176,394 @@ public EntityManagerFactoryBuilderImpl( PersistenceUnitDescriptor persistenceUnit, Map integrationSettings, ClassLoader providedClassLoader ) { - LogHelper.logPersistenceUnitInformation( persistenceUnit ); - this.persistenceUnit = persistenceUnit; if ( integrationSettings == null ) { - integrationSettings = Collections.emptyMap(); - } - - this.providedClassLoader = providedClassLoader; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // First we build the boot-strap service registry, which mainly handles class loader interactions - final BootstrapServiceRegistry bootstrapServiceRegistry = buildBootstrapServiceRegistry( integrationSettings ); - // And the main service registry. This is needed to start adding configuration values, etc - this.serviceRegistryBuilder = new StandardServiceRegistryBuilder( bootstrapServiceRegistry ); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Next we build a merged map of all the configuration values - this.configurationValues = mergePropertySources( persistenceUnit, integrationSettings, bootstrapServiceRegistry ); - // add all merged configuration values into the service registry builder - this.serviceRegistryBuilder.applySettings( configurationValues ); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Next we do a preliminary pass at metadata processing, which involves: - // 1) scanning - final ScanResult scanResult = scan( bootstrapServiceRegistry ); - final DeploymentResources deploymentResources = buildDeploymentResources( scanResult, bootstrapServiceRegistry ); - // 2) building a Jandex index - final IndexView jandexIndex = locateOrBuildJandexIndex( deploymentResources ); - // 3) building "metadata sources" to keep for later to use in building the SessionFactory - metadataSources = prepareMetadataSources( jandexIndex, deploymentResources, bootstrapServiceRegistry ); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - withValidatorFactory( configurationValues.get( AvailableSettings.VALIDATION_FACTORY ) ); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // push back class transformation to the environment; for the time being this only has any effect in EE - // container situations, calling back into PersistenceUnitInfo#addClassTransformer - final boolean useClassTransformer = "true".equals( configurationValues.remove( AvailableSettings.USE_CLASS_ENHANCER ) ); - if ( useClassTransformer ) { - persistenceUnit.pushClassTransformer( metadataSources.collectMappingClassNames() ); + integrationSettings = new HashMap(); } - } - - private static interface DeploymentResources { - public Iterable getClassDescriptors(); - public Iterable getPackageDescriptors(); - public Iterable getMappingFileDescriptors(); - } - - private DeploymentResources buildDeploymentResources( - ScanResult scanResult, - BootstrapServiceRegistry bootstrapServiceRegistry) { - // mapping files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - final ArrayList mappingFileDescriptors = new ArrayList(); - - final Set nonLocatedMappingFileNames = new HashSet(); - final List explicitMappingFileNames = persistenceUnit.getMappingFileNames(); - if ( explicitMappingFileNames != null ) { - nonLocatedMappingFileNames.addAll( explicitMappingFileNames ); + try { + // Build the boot-strap service registry, which mainly handles class loader interactions + final BootstrapServiceRegistry bsr = buildBootstrapServiceRegistry( integrationSettings, providedClassLoader ); + + // merge configuration sources + final MergedSettings mergedSettings = mergeSettings( persistenceUnit, integrationSettings, bsr ); + this.configurationValues = mergedSettings.getConfigurationValues(); + + // Build the "standard" service registry + final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr ); + ssrBuilder.applySettings( configurationValues ); + this.settings = configure( ssrBuilder ); + this.standardServiceRegistry = ssrBuilder.build(); + configure( standardServiceRegistry, mergedSettings ); + + + // Perform deployment scanning + final ScanResult scanResult = scanDeployment( bsr ); + + // Build the Metadata object + final MetadataSources metadataSources = new MetadataSources( bsr ); + populate( metadataSources, scanResult, mergedSettings, standardServiceRegistry ); + final MetadataBuilder metamodelBuilder = metadataSources.getMetadataBuilder( standardServiceRegistry ); + populate( metamodelBuilder, mergedSettings, standardServiceRegistry ); + this.metadata = (MetadataImplementor) metamodelBuilder.build(); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // push back class transformation to the environment; for the time being this only has any effect in EE + // container situations, calling back into PersistenceUnitInfo#addClassTransformer + final boolean useClassTransformer = "true".equals( configurationValues.remove( AvailableSettings.USE_CLASS_ENHANCER ) ); + if ( useClassTransformer ) { + persistenceUnit.pushClassTransformer( collectNamesOfClassesToEnhance( metadata ) ); + } } - - for ( MappingFileDescriptor mappingFileDescriptor : scanResult.getLocatedMappingFiles() ) { - mappingFileDescriptors.add( mappingFileDescriptor ); - nonLocatedMappingFileNames.remove( mappingFileDescriptor.getName() ); + catch (PersistenceException pe) { + throw pe; } - - for ( String name : nonLocatedMappingFileNames ) { - MappingFileDescriptor descriptor = buildMappingFileDescriptor( name, bootstrapServiceRegistry ); - mappingFileDescriptors.add( descriptor ); + catch (Exception e) { + throw persistenceException( "Unable to build Hibernate SessionFactory", e ); } + } + /** + * Gets the metadata. + * @return the metadata. + * @deprecated This should only be needed for testing and should ultimately be removed. + */ + public MetadataImplementor getMetadata() { + return metadata; + } - // classes and packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + private SettingsImpl configure(StandardServiceRegistryBuilder ssrBuilder) { + final SettingsImpl settings = new SettingsImpl(); - final HashMap classDescriptorMap = new HashMap(); - final HashMap packageDescriptorMap = new HashMap(); + applyJdbcConnectionProperties( ssrBuilder ); + applyTransactionProperties( ssrBuilder, settings ); - for ( ClassDescriptor classDescriptor : scanResult.getLocatedClasses() ) { - classDescriptorMap.put( classDescriptor.getName(), classDescriptor ); + // flush before completion validation + if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) { + ssrBuilder.applySetting( Environment.FLUSH_BEFORE_COMPLETION, "false" ); + LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION ); } - for ( PackageDescriptor packageDescriptor : scanResult.getLocatedPackages() ) { - packageDescriptorMap.put( packageDescriptor.getName(), packageDescriptor ); + final Object value = configurationValues.get( DISCARD_PC_ON_CLOSE ); + if ( value != null ) { + settings.setReleaseResourcesOnCloseEnabled( "true".equals( value ) ); } - final List explicitClassNames = persistenceUnit.getManagedClassNames(); - if ( explicitClassNames != null ) { - for ( String explicitClassName : explicitClassNames ) { - // IMPL NOTE : explicitClassNames can contain class or package names!!! - if ( classDescriptorMap.containsKey( explicitClassName ) ) { - continue; - } - if ( packageDescriptorMap.containsKey( explicitClassName ) ) { - continue; - } - - // try it as a class name first... - final String classFileName = explicitClassName.replace( '.', '/' ) + ".class"; - final URL classFileUrl = bootstrapServiceRegistry.getService( ClassLoaderService.class ) - .locateResource( classFileName ); - if ( classFileUrl != null ) { - classDescriptorMap.put( - explicitClassName, - new ClassDescriptorImpl( explicitClassName, new UrlInputStreamAccess( classFileUrl ) ) - ); - continue; - } - - // otherwise, try it as a package name - final String packageInfoFileName = explicitClassName.replace( '.', '/' ) + "/package-info.class"; - final URL packageInfoFileUrl = bootstrapServiceRegistry.getService( ClassLoaderService.class ) - .locateResource( packageInfoFileName ); - if ( packageInfoFileUrl != null ) { - packageDescriptorMap.put( - explicitClassName, - new PackageDescriptorImpl( explicitClassName, new UrlInputStreamAccess( packageInfoFileUrl ) ) - ); - continue; - } - - LOG.debugf( - "Unable to resolve class [%s] named in persistence unit [%s]", - explicitClassName, - persistenceUnit.getName() - ); - } + final StrategySelector strategySelector = ssrBuilder.getBootstrapServiceRegistry().getService( StrategySelector.class ); + final Object interceptorSetting = configurationValues.remove( AvailableSettings.SESSION_INTERCEPTOR ); + if ( interceptorSetting != null ) { + settings.setSessionInterceptorClass( + loadSessionInterceptorClass( interceptorSetting, strategySelector ) + ); } - return new DeploymentResources() { - @Override - public Iterable getClassDescriptors() { - return classDescriptorMap.values(); - } + return settings; + } - @Override - public Iterable getPackageDescriptors() { - return packageDescriptorMap.values(); + private void applyJdbcConnectionProperties(StandardServiceRegistryBuilder ssrBuilder) { + if ( dataSource != null ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, dataSource ); + } + else if ( persistenceUnit.getJtaDataSource() != null ) { + if ( ! ssrBuilder.getSettings().containsKey( org.hibernate.cfg.AvailableSettings.DATASOURCE ) ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, persistenceUnit.getJtaDataSource() ); + // HHH-8121 : make the PU-defined value available to EMF.getProperties() + configurationValues.put( AvailableSettings.JTA_DATASOURCE, persistenceUnit.getJtaDataSource() ); } - - @Override - public Iterable getMappingFileDescriptors() { - return mappingFileDescriptors; + } + else if ( persistenceUnit.getNonJtaDataSource() != null ) { + if ( ! ssrBuilder.getSettings().containsKey( org.hibernate.cfg.AvailableSettings.DATASOURCE ) ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, persistenceUnit.getNonJtaDataSource() ); + // HHH-8121 : make the PU-defined value available to EMF.getProperties() + configurationValues.put( AvailableSettings.NON_JTA_DATASOURCE, persistenceUnit.getNonJtaDataSource() ); } - }; - } - - private MappingFileDescriptor buildMappingFileDescriptor( - String name, - BootstrapServiceRegistry bootstrapServiceRegistry) { - final URL url = bootstrapServiceRegistry.getService( ClassLoaderService.class ).locateResource( name ); - if ( url == null ) { - throw persistenceException( "Unable to resolve named mapping-file [" + name + "]" ); } - - return new MappingFileDescriptorImpl( name, new UrlInputStreamAccess( url ) ); - } - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // temporary! - @SuppressWarnings("unchecked") - public Map getConfigurationValues() { - return Collections.unmodifiableMap( configurationValues ); - } - - public Configuration getHibernateConfiguration() { - return hibernateConfiguration; - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - @SuppressWarnings("unchecked") - private MetadataSources prepareMetadataSources( - IndexView jandexIndex, - DeploymentResources deploymentResources, - BootstrapServiceRegistry bootstrapServiceRegistry) { - // todo : this needs to tie into the metamodel branch... - MetadataSources metadataSources = new MetadataSources(); - - for ( ClassDescriptor classDescriptor : deploymentResources.getClassDescriptors() ) { - final String className = classDescriptor.getName(); - final ClassInfo classInfo = jandexIndex.getClassByName( DotName.createSimple( className ) ); - if ( classInfo == null ) { - // Not really sure what this means. Most likely it is explicitly listed in the persistence unit, - // but mapped via mapping file. Anyway assume its a mapping class... - metadataSources.annotatedMappingClassNames.add( className ); - continue; + else { + final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER ); + if ( StringHelper.isNotEmpty( driver ) ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DRIVER, driver ); } - - // logic here assumes an entity is not also a converter... - AnnotationInstance converterAnnotation = JandexHelper.getSingleAnnotation( - classInfo.annotations(), - JPADotNames.CONVERTER - ); - if ( converterAnnotation != null ) { - metadataSources.converterDescriptors.add( - new MetadataSources.ConverterDescriptor( - className, - JandexHelper.getValue( converterAnnotation, "autoApply", boolean.class, - bootstrapServiceRegistry.getService( ClassLoaderService.class ) ) - ) - ); + final String url = (String) configurationValues.get( AvailableSettings.JDBC_URL ); + if ( StringHelper.isNotEmpty( url ) ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.URL, url ); } - else { - metadataSources.annotatedMappingClassNames.add( className ); + final String user = (String) configurationValues.get( AvailableSettings.JDBC_USER ); + if ( StringHelper.isNotEmpty( user ) ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.USER, user ); + } + final String pass = (String) configurationValues.get( AvailableSettings.JDBC_PASSWORD ); + if ( StringHelper.isNotEmpty( pass ) ) { + ssrBuilder.applySetting( org.hibernate.cfg.AvailableSettings.PASS, pass ); } } + } - for ( PackageDescriptor packageDescriptor : deploymentResources.getPackageDescriptors() ) { - metadataSources.packageNames.add( packageDescriptor.getName() ); - } - - for ( MappingFileDescriptor mappingFileDescriptor : deploymentResources.getMappingFileDescriptors() ) { - metadataSources.namedMappingFileInputStreams.add( mappingFileDescriptor.getStreamAccess().asNamedInputStream() ); + private void applyTransactionProperties(StandardServiceRegistryBuilder ssrBuilder, SettingsImpl settings) { + PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( + configurationValues.get( AvailableSettings.TRANSACTION_TYPE ) + ); + if ( txnType == null ) { + txnType = persistenceUnit.getTransactionType(); } - - final String explicitHbmXmls = (String) configurationValues.remove( AvailableSettings.HBXML_FILES ); - if ( explicitHbmXmls != null ) { - metadataSources.mappingFileResources.addAll( Arrays.asList( StringHelper.split( ", ", explicitHbmXmls ) ) ); + if ( txnType == null ) { + // is it more appropriate to have this be based on bootstrap entry point (EE vs SE)? + txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL; } - - final List explicitOrmXml = (List) configurationValues.remove( AvailableSettings.XML_FILE_NAMES ); - if ( explicitOrmXml != null ) { - metadataSources.mappingFileResources.addAll( explicitOrmXml ); + settings.setTransactionType( txnType ); + boolean hasTxStrategy = configurationValues.containsKey( Environment.TRANSACTION_STRATEGY ); + if ( hasTxStrategy ) { + LOG.overridingTransactionStrategyDangerous( Environment.TRANSACTION_STRATEGY ); } - - return metadataSources; - } - - private IndexView locateOrBuildJandexIndex(DeploymentResources deploymentResources) { - // for now create a whole new Index to work with, eventually we need to: - // 1) accept an Index as an incoming config value - // 2) pass that Index along to the metamodel code... - IndexView jandexIndex = (IndexView) configurationValues.get( JANDEX_INDEX ); - if ( jandexIndex == null ) { - jandexIndex = buildJandexIndex( deploymentResources ); + else { + if ( txnType == PersistenceUnitTransactionType.JTA ) { + ssrBuilder.applySetting( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class ); + } + else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) { + ssrBuilder.applySetting( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class ); + } } - return jandexIndex; } - private IndexView buildJandexIndex(DeploymentResources deploymentResources) { - Indexer indexer = new Indexer(); - - for ( ClassDescriptor classDescriptor : deploymentResources.getClassDescriptors() ) { - indexStream( indexer, classDescriptor.getStreamAccess() ); - } - - for ( PackageDescriptor packageDescriptor : deploymentResources.getPackageDescriptors() ) { - indexStream( indexer, packageDescriptor.getStreamAccess() ); + @SuppressWarnings("unchecked") + private Class loadSessionInterceptorClass(Object value, StrategySelector strategySelector) { + if ( value == null ) { + return null; } - // for now we just skip entities defined in (1) orm.xml files and (2) hbm.xml files. this part really needs - // metamodel branch... - - // for now, we also need to wrap this in a CompositeIndex until Jandex is updated to use a common interface - // between the 2... - return indexer.complete(); + return Class.class.isInstance( value ) + ? (Class) value + : strategySelector.selectStrategyImplementor( Interceptor.class, value.toString() ); } - private void indexStream(Indexer indexer, InputStreamAccess streamAccess) { - try { - InputStream stream = streamAccess.accessInputStream(); - try { - indexer.index( stream ); - } - finally { - try { - stream.close(); - } - catch (Exception ignore) { - } - } - } - catch ( IOException e ) { - throw persistenceException( "Unable to index from stream " + streamAccess.getStreamName(), e ); + private List collectNamesOfClassesToEnhance(MetadataImplementor metadata) { + final List entityClassNames = new ArrayList(); + for ( EntityBinding eb : metadata.getEntityBindings() ) { + entityClassNames.add( eb.getEntity().getDescriptor().getName().toString() ); } + return entityClassNames; } /** * Builds the {@link BootstrapServiceRegistry} used to eventually build the {@link org.hibernate.boot.registry.StandardServiceRegistryBuilder}; mainly * used here during instantiation to define class-loading behavior. * + * * @param integrationSettings Any integration settings passed by the EE container or SE application + * @param providedClassLoader Typically (if non-null) a osgi bundle classloader. * * @return The built BootstrapServiceRegistry */ - private BootstrapServiceRegistry buildBootstrapServiceRegistry(Map integrationSettings) { - final BootstrapServiceRegistryBuilder bootstrapServiceRegistryBuilder = new BootstrapServiceRegistryBuilder(); - bootstrapServiceRegistryBuilder.with( new JpaIntegrator() ); + private BootstrapServiceRegistry buildBootstrapServiceRegistry( + Map integrationSettings, + ClassLoader providedClassLoader) { + final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder(); + bsrBuilder.with( new JpaIntegrator() ); final IntegratorProvider integratorProvider = (IntegratorProvider) integrationSettings.get( INTEGRATOR_PROVIDER ); if ( integratorProvider != null ) { for ( Integrator integrator : integratorProvider.getIntegrators() ) { - bootstrapServiceRegistryBuilder.with( integrator ); + bsrBuilder.with( integrator ); } } - + final StrategyRegistrationProviderList strategyRegistrationProviderList = (StrategyRegistrationProviderList) integrationSettings.get( STRATEGY_REGISTRATION_PROVIDERS ); if ( strategyRegistrationProviderList != null ) { for ( StrategyRegistrationProvider strategyRegistrationProvider : strategyRegistrationProviderList .getStrategyRegistrationProviders() ) { - bootstrapServiceRegistryBuilder.withStrategySelectors( strategyRegistrationProvider ); + bsrBuilder.withStrategySelectors( strategyRegistrationProvider ); } } - // TODO: If providedClassLoader is present (OSGi, etc.) *and* - // an APP_CLASSLOADER is provided, should throw an exception or - // warn? - ClassLoader classLoader; - ClassLoader appClassLoader = (ClassLoader) integrationSettings.get( org.hibernate.cfg.AvailableSettings.APP_CLASSLOADER ); + + // ClassLoaders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if ( persistenceUnit.getClassLoader() != null ) { + bsrBuilder.with( persistenceUnit.getClassLoader() ); + } + if ( providedClassLoader != null ) { - classLoader = providedClassLoader; + bsrBuilder.with( providedClassLoader ); } - else if ( appClassLoader != null ) { - classLoader = appClassLoader; + + final ClassLoader appClassLoader = (ClassLoader) integrationSettings.get( org.hibernate.cfg.AvailableSettings.APP_CLASSLOADER ); + if ( appClassLoader != null ) { + LOG.debugf( + "Found use of deprecated `%s` setting; use `%s` instead.", + org.hibernate.cfg.AvailableSettings.APP_CLASSLOADER, + org.hibernate.cfg.AvailableSettings.CLASSLOADERS + ); } - else { - classLoader = persistenceUnit.getClassLoader(); + final Object classLoadersSetting = integrationSettings.get( org.hibernate.cfg.AvailableSettings.CLASSLOADERS ); + if ( classLoadersSetting != null ) { + if ( java.util.Collection.class.isInstance( classLoadersSetting ) ) { + for ( ClassLoader classLoader : (java.util.Collection) classLoadersSetting ) { + bsrBuilder.with( classLoader ); + } + } + else if ( classLoadersSetting.getClass().isArray() ) { + for ( ClassLoader classLoader : (ClassLoader[]) classLoadersSetting ) { + bsrBuilder.with( classLoader ); + } + } + else if ( ClassLoader.class.isInstance( classLoadersSetting ) ) { + bsrBuilder.with( (ClassLoader) classLoadersSetting ); + } } - bootstrapServiceRegistryBuilder.with( classLoader ); - return bootstrapServiceRegistryBuilder.build(); + return bsrBuilder.build(); } @SuppressWarnings("unchecked") - private Map mergePropertySources( + private MergedSettings mergeSettings( PersistenceUnitDescriptor persistenceUnit, - Map integrationSettings, - final BootstrapServiceRegistry bootstrapServiceRegistry) { - final Map merged = new HashMap(); + Map integrationSettings, + final BootstrapServiceRegistry bsr) { + final MergedSettings mergedSettings = new MergedSettings( + determineJaccContext( integrationSettings, persistenceUnit.getProperties() ) + ); + // first, apply persistence.xml-defined settings if ( persistenceUnit.getProperties() != null ) { - merged.putAll( persistenceUnit.getProperties() ); + mergedSettings.configurationValues.putAll( persistenceUnit.getProperties() ); } - merged.put( AvailableSettings.PERSISTENCE_UNIT_NAME, persistenceUnit.getName() ); + mergedSettings.configurationValues.put( PERSISTENCE_UNIT_NAME, persistenceUnit.getName() ); - // see if the persistence.xml settings named a Hibernate config file.... final ValueHolder configLoaderHolder = new ValueHolder( new ValueHolder.DeferredInitializer() { @Override public ConfigLoader initialize() { - return new ConfigLoader( bootstrapServiceRegistry ); + return new ConfigLoader( bsr ); } } ); - final String cfgXmlResourceName1 = (String) merged.remove( AvailableSettings.CFG_FILE ); + // see if the persistence.xml settings named a Hibernate config file.... + final String cfgXmlResourceName1 = (String) mergedSettings.configurationValues.remove( CFG_FILE ); if ( StringHelper.isNotEmpty( cfgXmlResourceName1 ) ) { - // it does, so load those properties - JaxbHibernateConfiguration configurationElement = configLoaderHolder.getValue() - .loadConfigXmlResource( cfgXmlResourceName1 ); - processHibernateConfigurationElement( configurationElement, merged ); + processConfigXml( configLoaderHolder.getValue(), cfgXmlResourceName1, mergedSettings ); } // see if integration settings named a Hibernate config file.... - final String cfgXmlResourceName2 = (String) integrationSettings.get( AvailableSettings.CFG_FILE ); + final String cfgXmlResourceName2 = (String) integrationSettings.get( CFG_FILE ); if ( StringHelper.isNotEmpty( cfgXmlResourceName2 ) ) { - integrationSettings.remove( AvailableSettings.CFG_FILE ); - // it does, so load those properties - JaxbHibernateConfiguration configurationElement = configLoaderHolder.getValue().loadConfigXmlResource( - cfgXmlResourceName2 - ); - processHibernateConfigurationElement( configurationElement, merged ); + integrationSettings.remove( CFG_FILE ); + processConfigXml( configLoaderHolder.getValue(), cfgXmlResourceName2, mergedSettings ); } // finally, apply integration-supplied settings (per JPA spec, integration settings should override other sources) - merged.putAll( integrationSettings ); + for ( Map.Entry entry : integrationSettings.entrySet() ) { + if ( entry.getKey() == null ) { + continue; + } - if ( !merged.containsKey( AvailableSettings.VALIDATION_MODE ) ) { + if ( entry.getValue() == null ) { + mergedSettings.configurationValues.remove( entry.getKey() ); + } + else { + mergedSettings.configurationValues.put( entry.getKey(), entry.getValue() ); + } + } + + if ( !mergedSettings.configurationValues.containsKey( VALIDATION_MODE ) ) { if ( persistenceUnit.getValidationMode() != null ) { - merged.put( AvailableSettings.VALIDATION_MODE, persistenceUnit.getValidationMode() ); + mergedSettings.configurationValues.put( VALIDATION_MODE, persistenceUnit.getValidationMode() ); } } - if ( !merged.containsKey( AvailableSettings.SHARED_CACHE_MODE ) ) { + if ( !mergedSettings.configurationValues.containsKey( SHARED_CACHE_MODE ) ) { if ( persistenceUnit.getSharedCacheMode() != null ) { - merged.put( AvailableSettings.SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() ); + mergedSettings.configurationValues.put( SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() ); } } - // was getting NPE exceptions from the underlying map when just using #putAll, so going this safer route... - Iterator itr = merged.entrySet().iterator(); + // here we are going to iterate the merged config settings looking for: + // 1) additional JACC permissions + // 2) additional cache region declarations + // + // we will also clean up an references with null entries + Iterator itr = mergedSettings.configurationValues.entrySet().iterator(); while ( itr.hasNext() ) { final Map.Entry entry = (Map.Entry) itr.next(); if ( entry.getValue() == null ) { + // remove entries with null values itr.remove(); + break; } + + if ( String.class.isInstance( entry.getKey() ) && String.class.isInstance( entry.getValue() ) ) { + final String keyString = (String) entry.getKey(); + final String valueString = (String) entry.getValue(); + + if ( keyString.startsWith( JACC_PREFIX ) ) { + mergedSettings.getJaccPermissions().addPermissionDeclaration( + parseJaccConfigEntry( keyString, valueString ) + ); + } + else if ( keyString.startsWith( CLASS_CACHE_PREFIX ) ) { + mergedSettings.add( + parseCacheRegionDefinitionEntry( + keyString.substring( CLASS_CACHE_PREFIX.length() + 1 ), + valueString, + CacheRegionDefinition.CacheRegionType.ENTITY + ) + ); + } + else if ( keyString.startsWith( COLLECTION_CACHE_PREFIX ) ) { + mergedSettings.add( + parseCacheRegionDefinitionEntry( + keyString.substring( COLLECTION_CACHE_PREFIX.length() + 1 ), + (String) entry.getValue(), + CacheRegionDefinition.CacheRegionType.COLLECTION + ) + ); + } + } + } - return merged; + return mergedSettings; + } + + private JaccPermissionDeclarations determineJaccContext(Map integrationSettings, Properties properties) { + String jaccContextId = (String) integrationSettings.get( JACC_CONTEXT_ID ); + if ( jaccContextId == null && properties != null ) { + jaccContextId = properties.getProperty( JACC_CONTEXT_ID ); + } + + return new JaccPermissionDeclarations( jaccContextId ); } @SuppressWarnings("unchecked") - private void processHibernateConfigurationElement( - JaxbHibernateConfiguration configurationElement, - Map mergeMap) { - if ( ! mergeMap.containsKey( org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME ) ) { - String cfgName = configurationElement.getSessionFactory().getName(); - if ( cfgName != null ) { - mergeMap.put( org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME, cfgName ); + private void processConfigXml(ConfigLoader configLoader, String cfgXmlResourceName, MergedSettings mergedSettings) { + JaxbHibernateConfiguration configurationElement = configLoader.loadConfigXmlResource( cfgXmlResourceName ); + + if ( ! mergedSettings.configurationValues.containsKey( SESSION_FACTORY_NAME ) ) { + // there is not already a SF-name in the merged settings + final String sfName = configurationElement.getSessionFactory().getName(); + if ( sfName != null ) { + // but the cfg.xml file we are processing named one.. + mergedSettings.configurationValues.put( SESSION_FACTORY_NAME, sfName ); } } for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbProperty jaxbProperty : configurationElement.getSessionFactory().getProperty() ) { - mergeMap.put( jaxbProperty.getName(), jaxbProperty.getValue() ); + mergedSettings.configurationValues.put( jaxbProperty.getName(), jaxbProperty.getValue() ); } - for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping jaxbMapping : configurationElement.getSessionFactory().getMapping() ) { - cfgXmlNamedMappings.add( jaxbMapping ); + for ( JaxbMapping jaxbMapping : configurationElement.getSessionFactory().getMapping() ) { + mergedSettings.add( jaxbMapping ); } for ( Object cacheDeclaration : configurationElement.getSessionFactory().getClassCacheOrCollectionCache() ) { - if ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache.class.isInstance( cacheDeclaration ) ) { - final JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache jaxbClassCache - = (JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache) cacheDeclaration; - cacheRegionDefinitions.add( + if ( JaxbClassCache.class.isInstance( cacheDeclaration ) ) { + final JaxbClassCache jaxbClassCache = (JaxbClassCache) cacheDeclaration; + mergedSettings.add( new CacheRegionDefinition( - CacheRegionDefinition.CacheType.ENTITY, + CacheRegionDefinition.CacheRegionType.ENTITY, jaxbClassCache.getClazz(), jaxbClassCache.getUsage().value(), jaxbClassCache.getRegion(), @@ -621,11 +572,10 @@ private void processHibernateConfigurationElement( ); } else { - final JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache jaxbCollectionCache - = (JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache) cacheDeclaration; - cacheRegionDefinitions.add( + final JaxbCollectionCache jaxbCollectionCache = (JaxbCollectionCache) cacheDeclaration; + mergedSettings.add( new CacheRegionDefinition( - CacheRegionDefinition.CacheType.COLLECTION, + CacheRegionDefinition.CacheRegionType.COLLECTION, jaxbCollectionCache.getCollection(), jaxbCollectionCache.getUsage().value(), jaxbCollectionCache.getRegion(), @@ -636,8 +586,8 @@ private void processHibernateConfigurationElement( } if ( configurationElement.getSecurity() != null ) { - for ( JaxbHibernateConfiguration.JaxbSecurity.JaxbGrant grant : configurationElement.getSecurity().getGrant() ) { - grantedJaccPermissions.add( + for ( JaxbGrant grant : configurationElement.getSecurity().getGrant() ) { + mergedSettings.getJaccPermissions().addPermissionDeclaration( new GrantedPermission( grant.getRole(), grant.getEntityName(), @@ -648,51 +598,38 @@ private void processHibernateConfigurationElement( } } - private String jaccContextId; - - private void addJaccDefinition(String key, Object value) { - if ( jaccContextId == null ) { - jaccContextId = (String) configurationValues.get( AvailableSettings.JACC_CONTEXT_ID ); - if ( jaccContextId == null ) { - throw persistenceException( - "Entities have been configured for JACC, but " - + AvailableSettings.JACC_CONTEXT_ID + " has not been set" - ); - } - } - + private GrantedPermission parseJaccConfigEntry(String keyString, String valueString) { try { - final int roleStart = AvailableSettings.JACC_PREFIX.length() + 1; - final String role = key.substring( roleStart, key.indexOf( '.', roleStart ) ); + final int roleStart = JACC_PREFIX.length() + 1; + final String role = keyString.substring( roleStart, keyString.indexOf( '.', roleStart ) ); final int classStart = roleStart + role.length() + 1; - final String clazz = key.substring( classStart, key.length() ); - - grantedJaccPermissions.add( new GrantedPermission( role, clazz, (String) value ) ); + final String clazz = keyString.substring( classStart, keyString.length() ); + return new GrantedPermission( role, clazz, valueString ); } catch ( IndexOutOfBoundsException e ) { - throw persistenceException( "Illegal usage of " + AvailableSettings.JACC_PREFIX + ": " + key ); + throw persistenceException( "Illegal usage of " + JACC_PREFIX + ": " + keyString ); } } - private void addCacheRegionDefinition(String role, String value, CacheRegionDefinition.CacheType cacheType) { + private CacheRegionDefinition parseCacheRegionDefinitionEntry(String role, String value, CacheRegionDefinition.CacheRegionType cacheType) { final StringTokenizer params = new StringTokenizer( value, ";, " ); if ( !params.hasMoreTokens() ) { StringBuilder error = new StringBuilder( "Illegal usage of " ); - if ( cacheType == CacheRegionDefinition.CacheType.ENTITY ) { - error.append( AvailableSettings.CLASS_CACHE_PREFIX ) + if ( cacheType == CacheRegionDefinition.CacheRegionType.ENTITY ) { + error.append( CLASS_CACHE_PREFIX ) .append( ": " ) - .append( AvailableSettings.CLASS_CACHE_PREFIX ); + .append( CLASS_CACHE_PREFIX ); } else { - error.append( AvailableSettings.COLLECTION_CACHE_PREFIX ) + error.append( COLLECTION_CACHE_PREFIX ) .append( ": " ) - .append( AvailableSettings.COLLECTION_CACHE_PREFIX ); + .append( COLLECTION_CACHE_PREFIX ); } error.append( '.' ) .append( role ) .append( ' ' ) .append( value ) - .append( ". Was expecting configuration, but found none" ); + .append( ". Was expecting configuration (usage[,region[,lazy]]), but found none" ); throw persistenceException( error.toString() ); } @@ -702,7 +639,7 @@ private void addCacheRegionDefinition(String role, String value, CacheRegionDefi region = params.nextToken(); } boolean lazyProperty = true; - if ( cacheType == CacheRegionDefinition.CacheType.ENTITY ) { + if ( cacheType == CacheRegionDefinition.CacheRegionType.ENTITY ) { if ( params.hasMoreTokens() ) { lazyProperty = "all".equalsIgnoreCase( params.nextToken() ); } @@ -711,25 +648,53 @@ private void addCacheRegionDefinition(String role, String value, CacheRegionDefi lazyProperty = false; } - final CacheRegionDefinition def = new CacheRegionDefinition( cacheType, role, usage, region, lazyProperty ); - cacheRegionDefinitions.add( def ); + return new CacheRegionDefinition( cacheType, role, usage, region, lazyProperty ); + } + + private void configure(StandardServiceRegistry ssr, MergedSettings mergedSettings) { + final StrategySelector strategySelector = ssr.getService( StrategySelector.class ); + + // apply any JACC permissions + final JaccService jaccService = ssr.getService( JaccService.class ); + if ( jaccService == null ) { + // JACC not enabled + if ( !mergedSettings.getJaccPermissions().getPermissionDeclarations().isEmpty() ) { + LOG.debug( "JACC Service not enabled, but JACC permissions specified" ); + } + } + else { + for ( GrantedPermission grantedPermission : mergedSettings.getJaccPermissions().getPermissionDeclarations() ) { + jaccService.addPermission( grantedPermission ); + } + } + + + // apply id generators + final Object idGeneratorStrategyProviderSetting = configurationValues.remove( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER ); + if ( idGeneratorStrategyProviderSetting != null ) { + final IdentifierGeneratorStrategyProvider idGeneratorStrategyProvider = + strategySelector.resolveStrategy( IdentifierGeneratorStrategyProvider.class, idGeneratorStrategyProviderSetting ); + final MutableIdentifierGeneratorFactory identifierGeneratorFactory = ssr.getService( MutableIdentifierGeneratorFactory.class ); + if ( identifierGeneratorFactory == null ) { + throw persistenceException( + "Application requested custom identifier generator strategies, " + + "but the MutableIdentifierGeneratorFactory could not be found" + ); + } + for ( Map.Entry> entry : idGeneratorStrategyProvider.getStrategies().entrySet() ) { + identifierGeneratorFactory.register( entry.getKey(), entry.getValue() ); + } + } } @SuppressWarnings("unchecked") - private ScanResult scan(BootstrapServiceRegistry bootstrapServiceRegistry) { + private ScanResult scanDeployment(BootstrapServiceRegistry bootstrapServiceRegistry) { final Scanner scanner = locateOrBuildScanner( bootstrapServiceRegistry ); final ScanOptions scanOptions = determineScanOptions(); return scanner.scan( persistenceUnit, scanOptions ); } - private ScanOptions determineScanOptions() { - return new StandardScanOptions( - (String) configurationValues.get( AvailableSettings.AUTODETECTION ), - persistenceUnit.isExcludeUnlistedClasses() - ); - } - @SuppressWarnings("unchecked") private Scanner locateOrBuildScanner(BootstrapServiceRegistry bootstrapServiceRegistry) { final Object value = configurationValues.remove( AvailableSettings.SCANNER ); @@ -768,452 +733,268 @@ private Scanner locateOrBuildScanner(BootstrapServiceRegistry bootstrapServiceRe } } - @Override - public EntityManagerFactoryBuilder withValidatorFactory(Object validatorFactory) { - this.validatorFactory = validatorFactory; - - if ( validatorFactory != null ) { - BeanValidationIntegrator.validateFactory( validatorFactory ); - } - return this; - } - - @Override - public EntityManagerFactoryBuilder withDataSource(DataSource dataSource) { - this.dataSource = dataSource; - - return this; - } - - @Override - public void cancel() { - // todo : close the bootstrap registry (not critical, but nice to do) - - } - - @Override - public void generateSchema() { - processProperties(); - - final ServiceRegistry serviceRegistry = buildServiceRegistry(); - final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - - // IMPL NOTE : TCCL handling here is temporary. - // It is needed because this code still uses Hibernate Configuration and Hibernate commons-annotations - // in turn which relies on TCCL being set. - - ( (ClassLoaderServiceImpl) classLoaderService ).withTccl( - new ClassLoaderServiceImpl.Work() { - @Override - public Object perform() { - final Configuration hibernateConfiguration = buildHibernateConfiguration( serviceRegistry ); - - // This seems overkill, but building the SF is necessary to get the Integrators to kick in. - // Metamodel will clean this up... - try { - hibernateConfiguration.buildSessionFactory( serviceRegistry ); - } - catch (MappingException e) { - throw persistenceException( "Unable to build Hibernate SessionFactory", e ); - } - - JpaSchemaGenerator.performGeneration( hibernateConfiguration, serviceRegistry ); - - return null; - } - } + private ScanOptions determineScanOptions() { + return new StandardScanOptions( + (String) configurationValues.get( AvailableSettings.AUTODETECTION ), + persistenceUnit.isExcludeUnlistedClasses() ); - - // release this builder - cancel(); } @SuppressWarnings("unchecked") - public EntityManagerFactory build() { - processProperties(); + private void populate( + MetadataSources metadataSources, + ScanResult scanResult, + MergedSettings mergedSettings, + StandardServiceRegistry ssr) { + final ClassLoaderService classLoaderService = ssr.getService( ClassLoaderService.class ); - final ServiceRegistry serviceRegistry = buildServiceRegistry(); - final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + // todo : make MetadataSources/Metadata capable of handling duplicates - // IMPL NOTE : TCCL handling here is temporary. - // It is needed because this code still uses Hibernate Configuration and Hibernate commons-annotations - // in turn which relies on TCCL being set. + // explicit persistence unit mapping files listings + if ( persistenceUnit.getMappingFileNames() != null ) { + for ( String name : persistenceUnit.getMappingFileNames() ) { + metadataSources.addResource( name ); + } + } - return ( (ClassLoaderServiceImpl) classLoaderService ).withTccl( - new ClassLoaderServiceImpl.Work() { - @Override - public EntityManagerFactoryImpl perform() { - hibernateConfiguration = buildHibernateConfiguration( serviceRegistry ); - - SessionFactoryImplementor sessionFactory; - try { - sessionFactory = (SessionFactoryImplementor) hibernateConfiguration.buildSessionFactory( serviceRegistry ); - } - catch (MappingException e) { - throw persistenceException( "Unable to build Hibernate SessionFactory", e ); - } - - // must do after buildSessionFactory to let the Integrators kick in - JpaSchemaGenerator.performGeneration( hibernateConfiguration, serviceRegistry ); - - if ( suppliedSessionFactoryObserver != null ) { - sessionFactory.addObserver( suppliedSessionFactoryObserver ); - } - sessionFactory.addObserver( new ServiceRegistryCloser() ); - - // NOTE : passing cfg is temporary until - return new EntityManagerFactoryImpl( - persistenceUnit.getName(), - sessionFactory, - settings, - configurationValues, - hibernateConfiguration - ); - } + // explicit persistence unit managed class listings + // IMPL NOTE : managed-classes can contain class or package names!!! + if ( persistenceUnit.getManagedClassNames() != null ) { + for ( String managedClassName : persistenceUnit.getManagedClassNames() ) { + // try it as a class name first... + final String classFileName = managedClassName.replace( '.', '/' ) + ".class"; + final URL classFileUrl = classLoaderService.locateResource( classFileName ); + if ( classFileUrl != null ) { + // it is a class + metadataSources.addAnnotatedClassName( managedClassName ); + continue; } - ); - } - - private void processProperties() { - applyJdbcConnectionProperties(); - applyTransactionProperties(); - Object validationFactory = this.validatorFactory; - if ( validationFactory == null ) { - validationFactory = configurationValues.get( AvailableSettings.VALIDATION_FACTORY ); - } - if ( validationFactory != null ) { - BeanValidationIntegrator.validateFactory( validationFactory ); - serviceRegistryBuilder.applySetting( AvailableSettings.VALIDATION_FACTORY, validationFactory ); - configurationValues.put( AvailableSettings.VALIDATION_FACTORY, this.validatorFactory ); - } + // otherwise, try it as a package name + final String packageInfoFileName = managedClassName.replace( '.', '/' ) + "/package-info.class"; + final URL packageInfoFileUrl = classLoaderService.locateResource( packageInfoFileName ); + if ( packageInfoFileUrl != null ) { + // it is a package + metadataSources.addPackage( managedClassName ); + continue; + } - // flush before completion validation - if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) { - serviceRegistryBuilder.applySetting( Environment.FLUSH_BEFORE_COMPLETION, "false" ); - LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION ); + LOG.debugf( + "Unable to resolve class [%s] named in persistence unit [%s]", + managedClassName, + persistenceUnit.getName() + ); + } } - final StrategySelector strategySelector = serviceRegistryBuilder.getBootstrapServiceRegistry().getService( StrategySelector.class ); - - for ( Object oEntry : configurationValues.entrySet() ) { - Map.Entry entry = (Map.Entry) oEntry; - if ( entry.getKey() instanceof String ) { - final String keyString = (String) entry.getKey(); - - if ( AvailableSettings.INTERCEPTOR.equals( keyString ) ) { - sessionFactoryInterceptor = strategySelector.resolveStrategy( Interceptor.class, entry.getValue() ); + // add metadata sources explicitly listed in a cfg.xml file referenced by the application + if ( mergedSettings.cfgXmlNamedMappings != null ) { + for ( JaxbMapping jaxbMapping : mergedSettings.cfgXmlNamedMappings ) { + if ( jaxbMapping.getClazz() != null ) { + metadataSources.addAnnotatedClassName( jaxbMapping.getClazz() ); } - else if ( AvailableSettings.SESSION_INTERCEPTOR.equals( keyString ) ) { - settings.setSessionInterceptorClass( - loadSessionInterceptorClass( entry.getValue(), strategySelector ) - ); - } - else if ( AvailableSettings.NAMING_STRATEGY.equals( keyString ) ) { - namingStrategy = strategySelector.resolveStrategy( NamingStrategy.class, entry.getValue() ); + else if ( jaxbMapping.getResource() != null ) { + metadataSources.addResource( jaxbMapping.getResource() ); } - else if ( AvailableSettings.SESSION_FACTORY_OBSERVER.equals( keyString ) ) { - suppliedSessionFactoryObserver = strategySelector.resolveStrategy( SessionFactoryObserver.class, entry.getValue() ); + else if ( jaxbMapping.getJar() != null ) { + metadataSources.addJar( new File( jaxbMapping.getJar() ) ); } - else if ( AvailableSettings.DISCARD_PC_ON_CLOSE.equals( keyString ) ) { - settings.setReleaseResourcesOnCloseEnabled( "true".equals( entry.getValue() ) ); - } - else if ( keyString.startsWith( AvailableSettings.CLASS_CACHE_PREFIX ) ) { - addCacheRegionDefinition( - keyString.substring( AvailableSettings.CLASS_CACHE_PREFIX.length() + 1 ), - (String) entry.getValue(), - CacheRegionDefinition.CacheType.ENTITY - ); + else if ( jaxbMapping.getPackage() != null ) { + metadataSources.addPackage( jaxbMapping.getPackage() ); } - else if ( keyString.startsWith( AvailableSettings.COLLECTION_CACHE_PREFIX ) ) { - addCacheRegionDefinition( - keyString.substring( AvailableSettings.COLLECTION_CACHE_PREFIX.length() + 1 ), - (String) entry.getValue(), - CacheRegionDefinition.CacheType.COLLECTION - ); + } + } + + // add any explicit Class references passed in + final List loadedAnnotatedClasses = (List) configurationValues.remove( AvailableSettings.LOADED_CLASSES ); + if ( loadedAnnotatedClasses != null ) { + for ( Class cls : loadedAnnotatedClasses ) { + if ( AttributeConverter.class.isAssignableFrom( cls ) ) { + metadataSources.addAttributeConverter( (Class) cls ); } - else if ( keyString.startsWith( AvailableSettings.JACC_PREFIX ) - && ! ( keyString.equals( AvailableSettings.JACC_CONTEXT_ID ) - || keyString.equals( AvailableSettings.JACC_ENABLED ) ) ) { - addJaccDefinition( (String) entry.getKey(), entry.getValue() ); + else { + metadataSources.addAnnotatedClass( cls ); } } } - } - private void applyJdbcConnectionProperties() { - if ( dataSource != null ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, dataSource ); - } - else if ( persistenceUnit.getJtaDataSource() != null ) { - if ( ! serviceRegistryBuilder.getSettings().containsKey( org.hibernate.cfg.AvailableSettings.DATASOURCE ) ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, persistenceUnit.getJtaDataSource() ); - // HHH-8121 : make the PU-defined value available to EMF.getProperties() - configurationValues.put( AvailableSettings.JTA_DATASOURCE, persistenceUnit.getJtaDataSource() ); + // add any explicit hbm.xml references passed in + final String explicitHbmXmls = (String) configurationValues.remove( AvailableSettings.HBXML_FILES ); + if ( explicitHbmXmls != null ) { + for ( String hbmXml : StringHelper.split( ", ", explicitHbmXmls ) ) { + metadataSources.addResource( hbmXml ); } } - else if ( persistenceUnit.getNonJtaDataSource() != null ) { - if ( ! serviceRegistryBuilder.getSettings().containsKey( org.hibernate.cfg.AvailableSettings.DATASOURCE ) ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, persistenceUnit.getNonJtaDataSource() ); - // HHH-8121 : make the PU-defined value available to EMF.getProperties() - configurationValues.put( AvailableSettings.NON_JTA_DATASOURCE, persistenceUnit.getNonJtaDataSource() ); + + // add any explicit orm.xml references passed in + final List explicitOrmXmlList = (List) configurationValues.remove( AvailableSettings.XML_FILE_NAMES ); + if ( explicitOrmXmlList != null ) { + for ( String ormXml : explicitOrmXmlList ) { + metadataSources.addResource( ormXml ); } } - else { - final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER ); - if ( StringHelper.isNotEmpty( driver ) ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DRIVER, driver ); - } - final String url = (String) configurationValues.get( AvailableSettings.JDBC_URL ); - if ( StringHelper.isNotEmpty( url ) ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.URL, url ); - } - final String user = (String) configurationValues.get( AvailableSettings.JDBC_USER ); - if ( StringHelper.isNotEmpty( user ) ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.USER, user ); + + // Add mapping files found as a result of scanning + for ( MappingFileDescriptor mappingFileDescriptor : scanResult.getLocatedMappingFiles() ) { + final InputStream stream = mappingFileDescriptor.getStreamAccess().accessInputStream(); + try { + metadataSources.addInputStream( stream ); } - final String pass = (String) configurationValues.get( AvailableSettings.JDBC_PASSWORD ); - if ( StringHelper.isNotEmpty( pass ) ) { - serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.PASS, pass ); + finally { + try { + stream.close(); + } + catch ( IOException ignore ) { + LOG.trace( "Was unable to close input stream" ); + } } } - } - private void applyTransactionProperties() { - PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( - configurationValues.get( AvailableSettings.TRANSACTION_TYPE ) - ); - if ( txnType == null ) { - txnType = persistenceUnit.getTransactionType(); - } - if ( txnType == null ) { - // is it more appropriate to have this be based on bootstrap entry point (EE vs SE)? - txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL; + // Add packages found as a result of scanning + for ( PackageDescriptor packageDescriptor : scanResult.getLocatedPackages() ) { + metadataSources.addPackage( packageDescriptor.getName() ); } - settings.setTransactionType( txnType ); - boolean hasTxStrategy = configurationValues.containsKey( Environment.TRANSACTION_STRATEGY ); - if ( hasTxStrategy ) { - LOG.overridingTransactionStrategyDangerous( Environment.TRANSACTION_STRATEGY ); + + // Add classes found as a result of scanning + for ( ClassDescriptor classDescriptor : scanResult.getLocatedClasses() ) { + metadataSources.addAnnotatedClassName( classDescriptor.getName() ); } - else { - if ( txnType == PersistenceUnitTransactionType.JTA ) { - serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class ); - } - else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) { - serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class ); + } + + private void populate(MetadataBuilder metamodelBuilder, MergedSettings mergedSettings, StandardServiceRegistry ssr) { + if ( mergedSettings.cacheRegionDefinitions != null ) { + for ( CacheRegionDefinition localCacheRegionDefinition : mergedSettings.cacheRegionDefinitions ) { + metamodelBuilder.with( localCacheRegionDefinition ); } } - } - @SuppressWarnings("unchecked") - private Class loadSessionInterceptorClass(Object value, StrategySelector strategySelector) { - if ( value == null ) { - return null; + final Object namingStrategySetting = configurationValues.remove( AvailableSettings.NAMING_STRATEGY ); + if ( namingStrategySetting != null ) { + final StrategySelector strategySelector = ssr.getService( StrategySelector.class ); + metamodelBuilder.with( strategySelector.resolveStrategy( NamingStrategy.class, namingStrategySetting ) ); } - return Class.class.isInstance( value ) - ? (Class) value - : strategySelector.selectStrategyImplementor( Interceptor.class, value.toString() ); + final TypeContributorList typeContributorList = (TypeContributorList) configurationValues.remove( + TYPE_CONTRIBUTORS + ); + if ( typeContributorList != null ) { + for ( TypeContributor typeContributor : typeContributorList.getTypeContributors() ) { + metamodelBuilder.with( typeContributor ); + } + } + + IndexView jandexIndex = (IndexView) configurationValues.remove( JANDEX_INDEX ); + if ( jandexIndex != null ) { + metamodelBuilder.with( jandexIndex ); + } } - public ServiceRegistry buildServiceRegistry() { - return serviceRegistryBuilder.build(); + /** + * Completely and utterly not supported :) Here for use by tests + */ + public Map getConfigurationValues() { + return configurationValues; } - public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry) { - Properties props = new Properties(); - props.putAll( configurationValues ); - Configuration cfg = new Configuration(); - cfg.getProperties().putAll( props ); - cfg.setEntityNotFoundDelegate( jpaEntityNotFoundDelegate ); - if ( namingStrategy != null ) { - cfg.setNamingStrategy( namingStrategy ); - } + // Phase 2 concerns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ( sessionFactoryInterceptor != null ) { - cfg.setInterceptor( sessionFactoryInterceptor ); - } - - final Object strategyProviderValue = props.get( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER ); - final IdentifierGeneratorStrategyProvider strategyProvider = strategyProviderValue == null - ? null - : serviceRegistry.getService( StrategySelector.class ) - .resolveStrategy( IdentifierGeneratorStrategyProvider.class, strategyProviderValue ); + @Override + public EntityManagerFactoryBuilder withValidatorFactory(Object validatorFactory) { + this.validatorFactory = validatorFactory; - if ( strategyProvider != null ) { - final MutableIdentifierGeneratorFactory identifierGeneratorFactory = cfg.getIdentifierGeneratorFactory(); - for ( Map.Entry> entry : strategyProvider.getStrategies().entrySet() ) { - identifierGeneratorFactory.register( entry.getKey(), entry.getValue() ); - } + if ( validatorFactory != null ) { + BeanValidationIntegrator.validateFactory( validatorFactory ); } + return this; + } - if ( grantedJaccPermissions != null ) { - final JaccService jaccService = serviceRegistry.getService( JaccService.class ); - for ( GrantedPermission grantedPermission : grantedJaccPermissions ) { - jaccService.addPermission( grantedPermission ); - } - } + @Override + public EntityManagerFactoryBuilder withDataSource(DataSource dataSource) { + this.dataSource = dataSource; - if ( cacheRegionDefinitions != null ) { - for ( CacheRegionDefinition cacheRegionDefinition : cacheRegionDefinitions ) { - if ( cacheRegionDefinition.cacheType == CacheRegionDefinition.CacheType.ENTITY ) { - cfg.setCacheConcurrencyStrategy( - cacheRegionDefinition.role, - cacheRegionDefinition.usage, - cacheRegionDefinition.region, - cacheRegionDefinition.cacheLazy - ); - } - else { - cfg.setCollectionCacheConcurrencyStrategy( - cacheRegionDefinition.role, - cacheRegionDefinition.usage, - cacheRegionDefinition.region - ); - } - } + return this; + } + + @Override + public void cancel() { + if ( standardServiceRegistry != null ) { + StandardServiceRegistryBuilder.destroy( standardServiceRegistry ); } + } - // todo : need to have this use the metamodel codebase eventually... + @Override + public void generateSchema() { + // This seems overkill, but building the SF is necessary to get the Integrators to kick in. + // Metamodel will clean this up... + try { + SessionFactoryBuilder sfBuilder = metadata.getSessionFactoryBuilder(); + populate( sfBuilder, standardServiceRegistry ); + sfBuilder.build(); - for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping jaxbMapping : cfgXmlNamedMappings ) { - if ( jaxbMapping.getClazz() != null ) { - cfg.addAnnotatedClass( - serviceRegistry.getService( ClassLoaderService.class ).classForName( jaxbMapping.getClazz() ) - ); - } - else if ( jaxbMapping.getResource() != null ) { - cfg.addResource( jaxbMapping.getResource() ); - } - else if ( jaxbMapping.getJar() != null ) { - cfg.addJar( new File( jaxbMapping.getJar() ) ); - } - else if ( jaxbMapping.getPackage() != null ) { - cfg.addPackage( jaxbMapping.getPackage() ); - } + JpaSchemaGenerator.performGeneration( metadata, configurationValues, standardServiceRegistry ); } - - List loadedAnnotatedClasses = (List) configurationValues.remove( AvailableSettings.LOADED_CLASSES ); - if ( loadedAnnotatedClasses != null ) { - for ( Class cls : loadedAnnotatedClasses ) { - if ( AttributeConverter.class.isAssignableFrom( cls ) ) { - cfg.addAttributeConverter( (Class) cls ); - } - else { - cfg.addAnnotatedClass( cls ); - } - } + catch (Exception e) { + throw persistenceException( "Unable to build Hibernate SessionFactory", e ); } - for ( String className : metadataSources.getAnnotatedMappingClassNames() ) { - cfg.addAnnotatedClass( serviceRegistry.getService( ClassLoaderService.class ).classForName( className ) ); - } - for ( MetadataSources.ConverterDescriptor converterDescriptor : metadataSources.getConverterDescriptors() ) { - final Class converterClass; - try { - Class theClass = serviceRegistry.getService( ClassLoaderService.class ).classForName( converterDescriptor.converterClassName ); - converterClass = (Class) theClass; - } - catch (ClassCastException e) { - throw persistenceException( - String.format( - "AttributeConverter implementation [%s] does not implement AttributeConverter interface", - converterDescriptor.converterClassName - ) - ); - } - cfg.addAttributeConverter( converterClass, converterDescriptor.autoApply ); - } + // release this builder + cancel(); + } - for ( String resourceName : metadataSources.mappingFileResources ) { - Boolean useMetaInf = null; - try { - if ( resourceName.endsWith( META_INF_ORM_XML ) ) { - useMetaInf = true; - } - cfg.addResource( resourceName ); - } - catch( MappingNotFoundException e ) { - if ( ! resourceName.endsWith( META_INF_ORM_XML ) ) { - throw persistenceException( "Unable to find XML mapping file in classpath: " + resourceName ); - } - else { - useMetaInf = false; - //swallow it, the META-INF/orm.xml is optional - } - } - catch( MappingException me ) { - throw persistenceException( "Error while reading JPA XML file: " + resourceName, me ); - } + @SuppressWarnings("unchecked") + public EntityManagerFactory build() { + SessionFactoryBuilder sfBuilder = metadata.getSessionFactoryBuilder(); + populate( sfBuilder, standardServiceRegistry ); - if ( Boolean.TRUE.equals( useMetaInf ) ) { - LOG.exceptionHeaderFound( getExceptionHeader(), META_INF_ORM_XML ); - } - else if (Boolean.FALSE.equals(useMetaInf)) { - LOG.exceptionHeaderNotFound( getExceptionHeader(), META_INF_ORM_XML ); - } - } - for ( NamedInputStream namedInputStream : metadataSources.namedMappingFileInputStreams ) { - try { - //addInputStream has the responsibility to close the stream - cfg.addInputStream( new BufferedInputStream( namedInputStream.getStream() ) ); - } - catch ( InvalidMappingException e ) { - // try our best to give the file name - if ( StringHelper.isNotEmpty( namedInputStream.getName() ) ) { - throw new InvalidMappingException( - "Error while parsing file: " + namedInputStream.getName(), - e.getType(), - e.getPath(), - e - ); - } - else { - throw e; - } - } - catch (MappingException me) { - // try our best to give the file name - if ( StringHelper.isNotEmpty( namedInputStream.getName() ) ) { - throw new MappingException("Error while parsing file: " + namedInputStream.getName(), me ); - } - else { - throw me; - } - } - } - for ( String packageName : metadataSources.packageNames ) { - cfg.addPackage( packageName ); + SessionFactoryImplementor sessionFactory; + try { + sessionFactory = (SessionFactoryImplementor) sfBuilder.build(); } - - final TypeContributorList typeContributorList - = (TypeContributorList) configurationValues.get( TYPE_CONTRIBUTORS ); - if ( typeContributorList != null ) { - configurationValues.remove( TYPE_CONTRIBUTORS ); - for ( TypeContributor typeContributor : typeContributorList.getTypeContributors() ) { - cfg.registerTypeContributor( typeContributor ); - } + catch (Exception e) { + throw persistenceException( "Unable to build Hibernate SessionFactory", e ); } - - return cfg; + + return new EntityManagerFactoryImpl( + persistenceUnit.getName(), + sessionFactory, + metadata, + settings, + configurationValues + ); } - public static class ServiceRegistryCloser implements SessionFactoryObserver { - @Override - public void sessionFactoryCreated(SessionFactory sessionFactory) { - // nothing to do + private void populate(SessionFactoryBuilder sfBuilder, StandardServiceRegistry ssr) { + final StrategySelector strategySelector = ssr.getService( StrategySelector.class ); + + // Locate and apply the requested SessionFactory-level interceptor (if one) + final Object sessionFactoryInterceptorSetting = configurationValues.remove( AvailableSettings.INTERCEPTOR ); + if ( sessionFactoryInterceptorSetting != null ) { + final Interceptor sessionFactoryInterceptor = + strategySelector.resolveStrategy( Interceptor.class, sessionFactoryInterceptorSetting ); + sfBuilder.with( sessionFactoryInterceptor ); } - @Override - public void sessionFactoryClosed(SessionFactory sessionFactory) { - SessionFactoryImplementor sfi = ( (SessionFactoryImplementor) sessionFactory ); - sfi.getServiceRegistry().destroy(); - ServiceRegistry basicRegistry = sfi.getServiceRegistry().getParentServiceRegistry(); - ( (ServiceRegistryImplementor) basicRegistry ).destroy(); + // Locate and apply any requested SessionFactoryObserver + final Object sessionFactoryObserverSetting = configurationValues.remove( AvailableSettings.SESSION_FACTORY_OBSERVER ); + if ( sessionFactoryObserverSetting != null ) { + final SessionFactoryObserver suppliedSessionFactoryObserver = + strategySelector.resolveStrategy( SessionFactoryObserver.class, sessionFactoryObserverSetting ); + sfBuilder.add( suppliedSessionFactoryObserver ); + } + + sfBuilder.add( new ServiceRegistryCloser() ); + + sfBuilder.with( JpaEntityNotFoundDelegate.INSTANCE ); + + if ( this.validatorFactory != null ) { + sfBuilder.withValidatorFactory( validatorFactory ); + } + if ( this.cdiBeanManager != null ) { + sfBuilder.withBeanManager( cdiBeanManager ); } } @@ -1232,79 +1013,56 @@ private String getExceptionHeader() { return "[PersistenceUnit: " + persistenceUnit.getName() + "] "; } - public static class CacheRegionDefinition { - public static enum CacheType { ENTITY, COLLECTION } - - public final CacheType cacheType; - public final String role; - public final String usage; - public final String region; - public final boolean cacheLazy; - - public CacheRegionDefinition( - CacheType cacheType, - String role, - String usage, - String region, boolean cacheLazy) { - this.cacheType = cacheType; - this.role = role; - this.usage = usage; - this.region = region; - this.cacheLazy = cacheLazy; - } - } - public static class JaccDefinition { - public final String contextId; - public final String role; - public final String clazz; - public final String actions; - public JaccDefinition(String contextId, String role, String clazz, String actions) { - this.contextId = contextId; - this.role = role; - this.clazz = clazz; - this.actions = actions; + public static class ServiceRegistryCloser implements SessionFactoryObserver { + @Override + public void sessionFactoryCreated(SessionFactory sessionFactory) { + // nothing to do + } + + @Override + public void sessionFactoryClosed(SessionFactory sessionFactory) { + SessionFactoryImplementor sfi = ( (SessionFactoryImplementor) sessionFactory ); + sfi.getServiceRegistry().destroy(); + ServiceRegistry basicRegistry = sfi.getServiceRegistry().getParentServiceRegistry(); + ( (ServiceRegistryImplementor) basicRegistry ).destroy(); } } - public static class MetadataSources { - private final List annotatedMappingClassNames = new ArrayList(); - private final List converterDescriptors = new ArrayList(); - private final List namedMappingFileInputStreams = new ArrayList(); - private final List mappingFileResources = new ArrayList(); - private final List packageNames = new ArrayList(); + public static class MergedSettings { + private final JaccPermissionDeclarations jaccPermissions; - public List getAnnotatedMappingClassNames() { - return annotatedMappingClassNames; - } + private final Map configurationValues = new ConcurrentHashMap( 16, 0.75f, 1 ); - public List getConverterDescriptors() { - return converterDescriptors; - } + private List cacheRegionDefinitions; + private List cfgXmlNamedMappings; - public List getNamedMappingFileInputStreams() { - return namedMappingFileInputStreams; + public MergedSettings(JaccPermissionDeclarations jaccPermissions) { + this.jaccPermissions = jaccPermissions; } - public List getPackageNames() { - return packageNames; + public Map getConfigurationValues() { + return configurationValues; } - public List collectMappingClassNames() { - // todo : the complete answer to this involves looking through the mapping files as well. - // Really need the metamodel branch code to do that properly - return annotatedMappingClassNames; + public JaccPermissionDeclarations getJaccPermissions() { + return jaccPermissions; } - public static class ConverterDescriptor { - private final String converterClassName; - private final boolean autoApply; + public void add(CacheRegionDefinition cacheRegionDefinition) { + if ( cacheRegionDefinitions == null ) { + cacheRegionDefinitions = new ArrayList(); + } + cacheRegionDefinitions.add( cacheRegionDefinition ); + } - public ConverterDescriptor(String converterClassName, boolean autoApply) { - this.converterClassName = converterClassName; - this.autoApply = autoApply; + public void add(JaxbMapping jaxbMapping) { + if ( cfgXmlNamedMappings == null ) { + cfgXmlNamedMappings = new ArrayList(); } + cfgXmlNamedMappings.add( jaxbMapping ); } } + } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/JpaEntityNotFoundDelegate.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/JpaEntityNotFoundDelegate.java new file mode 100644 index 000000000000..0d982d11080d --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/JpaEntityNotFoundDelegate.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.boot.internal; + +import java.io.Serializable; +import javax.persistence.EntityNotFoundException; + +import org.hibernate.proxy.EntityNotFoundDelegate; + +/** + * EntityNotFoundDelegate implementation complying with the JPA spec by throwing {@link EntityNotFoundException}. + * + * @author Steve Ebersole + */ +class JpaEntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable { + /** + * Singleton access + */ + public static final JpaEntityNotFoundDelegate INSTANCE = new JpaEntityNotFoundDelegate(); + + public void handleEntityNotFound(String entityName, Serializable id) { + throw new EntityNotFoundException( "Unable to find " + entityName + " with id " + id ); + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java index 05fc13ff71f6..b05a743ca898 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java @@ -50,7 +50,7 @@ import org.hibernate.jpa.boot.archive.internal.ArchiveHelper; import org.hibernate.jpa.internal.EntityManagerMessageLogger; import org.hibernate.jpa.internal.util.ConfigurationHelper; -import org.hibernate.metamodel.source.XsdException; +import org.hibernate.metamodel.source.spi.XsdException; import org.jboss.logging.Logger; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java index 6df5baa5d874..2fe7b9db6c1c 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/ClassFileArchiveEntryHandler.java @@ -69,7 +69,7 @@ public void handleEntry(ArchiveEntry entry, ArchiveContext context) { return; } - // we are only interested in classes with certain annotations, so see if the ClassDescriptor + // we are only interested in classes with certain annotations, so see if the JavaTypeDescriptor // represents a class which contains any of those annotations if ( ! containsClassAnnotationsOfInterest( classFile ) ) { return; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java index 5e6fccb2fb0f..c79d3e3e9952 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/scan/spi/NonClassFileArchiveEntryHandler.java @@ -59,12 +59,13 @@ public void handleEntry(ArchiveEntry entry, ArchiveContext context) { @SuppressWarnings("SimplifiableIfStatement") private boolean acceptAsMappingFile(ArchiveEntry entry, ArchiveContext context) { - if ( entry.getName().endsWith( "hbm.xml" ) ) { + if ( entry.getNameWithinArchive().endsWith( "hbm.xml" ) ) { return scanOptions.canDetectHibernateMappingFiles(); } // todo : should really do this case-insensitively - if ( entry.getName().endsWith( "META-INF/orm.xml" ) ) { + // use getNameWithinArchive, not getName -- ensure paths are normalized (Windows, etc.) + if ( entry.getNameWithinArchive().endsWith( "META-INF/orm.xml" ) ) { if ( context.getPersistenceUnitDescriptor().getMappingFileNames().contains( "META-INF/orm.xml" ) ) { // if the user explicitly listed META-INF/orm.xml, only except the root one // diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/EntityManagerFactoryBuilder.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/EntityManagerFactoryBuilder.java index dc560c8a82f5..efcb4fe445b5 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/EntityManagerFactoryBuilder.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/spi/EntityManagerFactoryBuilder.java @@ -35,7 +35,7 @@ * The second phase is building the EntityManagerFactory instance via {@link #build}. * * If anything goes wrong during either phase and the bootstrap process needs to be aborted, {@link #cancel()} should - * be called. + * be called to release resources held between the 2 phases. * * @author Steve Ebersole * @author Scott Marlow diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ListIndexExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ListIndexExpression.java index be7716ab3d37..2bd3b39d8445 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ListIndexExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ListIndexExpression.java @@ -60,7 +60,7 @@ public void registerParameters(ParameterRegistry registry) { public String render(RenderingContext renderingContext) { return "index(" - + origin.getPathIdentifier() + '.' + getListAttribute().getName() + + origin.getPathIdentifier() + ")"; } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/SimpleCaseExpression.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/SimpleCaseExpression.java index 7dc469689899..d7dcb43ce573 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/SimpleCaseExpression.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/SimpleCaseExpression.java @@ -54,15 +54,15 @@ public class SimpleCaseExpression private Expression otherwiseResult; public class WhenClause { - private final C condition; + private final LiteralExpression condition; private final Expression result; - public WhenClause(C condition, Expression result) { + public WhenClause(LiteralExpression condition, Expression result) { this.condition = condition; this.result = result; } - public C getCondition() { + public LiteralExpression getCondition() { return condition; } @@ -99,7 +99,10 @@ private LiteralExpression buildLiteral(R result) { } public SimpleCase when(C condition, Expression result) { - WhenClause whenClause = new WhenClause( condition, result ); + WhenClause whenClause = new WhenClause( + new LiteralExpression( criteriaBuilder(), condition ), + result + ); whenClauses.add( whenClause ); adjustJavaType( result ); return this; @@ -141,10 +144,10 @@ public void registerParameters(ParameterRegistry registry) { public String render(RenderingContext renderingContext) { StringBuilder caseExpr = new StringBuilder(); caseExpr.append( "case " ) - .append( ( (Renderable) getExpression() ).render( renderingContext ) ) - .append( ' ' ); + .append( ( (Renderable) getExpression() ).render( renderingContext ) ); for ( WhenClause whenClause : getWhenClauses() ) { - caseExpr.append( ( (Renderable) whenClause.getCondition() ).render( renderingContext ) ) + caseExpr.append( " when " ) + .append( whenClause.getCondition().render( renderingContext ) ) .append( " then " ) .append( ( (Renderable) whenClause.getResult() ).render( renderingContext ) ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/AbstractPathImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/AbstractPathImpl.java index 8597fc9d4f00..79057ce3e7c6 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/AbstractPathImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/AbstractPathImpl.java @@ -139,12 +139,21 @@ public Path get(SingularAttribute attribute) { SingularAttributePath path = (SingularAttributePath) resolveCachedAttributePath( attribute.getName() ); if ( path == null ) { - path = new SingularAttributePath( criteriaBuilder(), attribute.getJavaType(), this, attribute ); + path = new SingularAttributePath( + criteriaBuilder(), + attribute.getJavaType(), + getPathSourceForSubPaths(), + attribute + ); registerAttributePath( attribute.getName(), path ); } return path; } + protected PathSource getPathSourceForSubPaths() { + return this; + } + @Override @SuppressWarnings({ "unchecked" }) public > Expression get(PluralAttribute attribute) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java index 6e21730cafb5..12ba246f8ab9 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java @@ -126,5 +126,15 @@ public void prepareAlias(RenderingContext renderingContext) { public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + + @Override + public String getPathIdentifier() { + return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; + } + + @Override + protected PathSource getPathSourceForSubPaths() { + return this; + } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java index 56482892fff7..178c0f7d9e91 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java @@ -134,5 +134,15 @@ public void prepareAlias(RenderingContext renderingContext) { public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + + @Override + public String getPathIdentifier() { + return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; + } + + @Override + protected PathSource getPathSourceForSubPaths() { + return this; + } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java index d6c16ef2a5a0..4d7312b47eca 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java @@ -155,5 +155,15 @@ public void prepareAlias(RenderingContext renderingContext) { public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + + @Override + public String getPathIdentifier() { + return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; + } + + @Override + protected PathSource getPathSourceForSubPaths() { + return this; + } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/RootImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/RootImpl.java index df5641811c04..c174362e27c1 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/RootImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/RootImpl.java @@ -30,6 +30,7 @@ import org.hibernate.jpa.criteria.CriteriaBuilderImpl; import org.hibernate.jpa.criteria.CriteriaSubqueryImpl; import org.hibernate.jpa.criteria.FromImplementor; +import org.hibernate.jpa.criteria.PathSource; import org.hibernate.jpa.criteria.compile.RenderingContext; /** @@ -137,8 +138,22 @@ public void prepareAlias(RenderingContext renderingContext) { @Override public String render(RenderingContext renderingContext) { + return getTreatFragment(); + } + + protected String getTreatFragment() { return "treat(" + original.getAlias() + " as " + treatAsType.getName() + ")"; } + + @Override + public String getPathIdentifier() { + return getTreatFragment(); + } + + @Override + protected PathSource getPathSourceForSubPaths() { + return this; + } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java index 8cfeabfa4adf..0fe091bd30d7 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java @@ -131,5 +131,15 @@ public void prepareAlias(RenderingContext renderingContext) { public String render(RenderingContext renderingContext) { return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + + @Override + public String getPathIdentifier() { + return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; + } + + @Override + protected PathSource getPathSourceForSubPaths() { + return this; + } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/AbstractPredicateImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/AbstractPredicateImpl.java index d90b273962eb..04d3dd2e9ee4 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/AbstractPredicateImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/AbstractPredicateImpl.java @@ -40,14 +40,13 @@ public abstract class AbstractPredicateImpl extends ExpressionImpl implements PredicateImplementor, Serializable { - private boolean negated; protected AbstractPredicateImpl(CriteriaBuilderImpl criteriaBuilder) { super( criteriaBuilder, Boolean.class ); } public boolean isNegated() { - return negated; + return false; } public Predicate not() { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/NegatedPredicateWrapper.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/NegatedPredicateWrapper.java index 45d1818e0987..20b9802ffb99 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/NegatedPredicateWrapper.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/NegatedPredicateWrapper.java @@ -107,19 +107,19 @@ public void registerParameters(ParameterRegistry registry) { @Override public String render(boolean isNegated, RenderingContext renderingContext) { - return render( renderingContext ); - } - - @Override - public String render(RenderingContext renderingContext) { if ( isJunction() ) { return CompoundPredicate.render( this, renderingContext ); } else { - return predicate.render( isNegated(), renderingContext ); + return predicate.render( isNegated, renderingContext ); } } + @Override + public String render(RenderingContext renderingContext) { + return render( isNegated(), renderingContext ); + } + @Override public String renderProjection(RenderingContext renderingContext) { return render( renderingContext ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java index 6090370205cc..d10640cab1e8 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/CallbackProcessorImpl.java @@ -27,14 +27,14 @@ import java.util.ArrayList; import java.util.List; -import org.hibernate.MappingException; +import org.hibernate.EntityMode; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.jpa.event.spi.jpa.Callback; import org.hibernate.jpa.event.spi.jpa.ListenerFactory; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.metamodel.source.binder.JpaCallbackClass; +import org.hibernate.metamodel.source.spi.JpaCallbackSource; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.jboss.logging.Logger; @@ -62,47 +62,51 @@ public CallbackProcessorImpl( @Override public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl callbackRegistry) { final EntityBinding entityBinding = (EntityBinding) entityObject; - final String entityClassName = entityBinding.getEntity().getClassName(); - if ( entityClassName == null ) { + if ( entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) { return; } - - try { - final Class entityClass = classLoaderService.classForName( entityClassName ); - for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) { - callbackRegistry.addEntityCallbacks( - entityClass, - annotationClass, - collectCallbacks( entityBinding, entityClass, annotationClass ) - ); - } - } - catch (ClassLoadingException e) { - throw new MappingException( "entity class not found: " + entityClassName, e ); + final Class entityClass = classLoaderService.classForName( + entityBinding.getEntity().getDescriptor().getName().toString() + ); + for ( final Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) { + callbackRegistry.addEntityCallbacks( + entityClass, + annotationClass, + collectCallbacks( entityBinding, entityClass, annotationClass ) + ); } } - private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) { - final List callbacks = new ArrayList(); - for ( JpaCallbackClass jpaCallbackClass : entityBinding.getJpaCallbackClasses() ) { - final Class listenerClass = classLoaderService.classForName( jpaCallbackClass.getName() ); - final String methodName = jpaCallbackClass.getCallbackMethod( annotationClass ); + private final static Callback[] EMPTY_CALLBACK = new Callback[0]; + private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) { + final List jpaCallbackSources = entityBinding.getJpaCallbackClasses(); + if ( CollectionHelper.isEmpty( jpaCallbackSources ) ) { + return EMPTY_CALLBACK; + } + final List result = new ArrayList( jpaCallbackSources.size() ); + for ( final JpaCallbackSource jpaCallbackSource : entityBinding.getJpaCallbackClasses() ) { + final Class listenerClass = classLoaderService.classForName( jpaCallbackSource.getName() ); + final String methodName = jpaCallbackSource.getCallbackMethod( annotationClass ); + if ( methodName == null ) { + continue; + } log.debugf( - "Adding $s.%s as %s callback for entity %s", + "Adding %s.%s as %s callback for entity %s", listenerClass.getName(), methodName, annotationClass.getName(), entityClass.getName() ); - final Callback callback = jpaCallbackClass.isListener() + final Callback callback = jpaCallbackSource.isListener() ? createListenerCallback( listenerClass, entityClass, methodName ) : createBeanCallback( listenerClass, methodName ); - assert callback != null; - callbacks.add(callback); + if ( callback != null ) { + result.add( callback ); + } } - return callbacks.toArray(new Callback[callbacks.size()]); + return result.toArray( new Callback[result.size()] ); } private Callback createListenerCallback( @@ -132,9 +136,7 @@ private Callback createListenerCallback( if (argType != Object.class && argType != entityClass) { continue; } - if (!method.isAccessible()) { - method.setAccessible( true ); - } + method.setAccessible( true ); return new ListenerCallback( listenerInstance, method ); } @@ -151,7 +153,7 @@ private Callback createBeanCallback( Class callbackClass, for (Method method : callbackClass.getDeclaredMethods()) { if (!method.getName().equals(methodName)) continue; if (method.getParameterTypes().length != 0) continue; - if (!method.isAccessible()) method.setAccessible(true); + method.setAccessible(true); return new EntityCallback(method); } return null; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/LegacyCallbackProcessor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/LegacyCallbackProcessor.java index a72c155f8e7b..ce507d1a8765 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/LegacyCallbackProcessor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/internal/jpa/LegacyCallbackProcessor.java @@ -104,7 +104,7 @@ public Callback[] resolveCallbacks(XClass beanClass, Class annotation, Reflectio .getName() + " - " + xMethod ); } - if (!method.isAccessible()) method.setAccessible(true); + method.setAccessible(true); log.debugf("Adding %s as %s callback for entity %s", methodName, annotation.getSimpleName(), diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java index 0688d81389b5..1038cf087105 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java @@ -25,7 +25,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Iterator; import java.util.Map; import org.hibernate.HibernateException; @@ -59,12 +58,10 @@ import org.hibernate.jpa.event.internal.jpa.CallbackProcessorImpl; import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl; -import org.hibernate.jpa.event.internal.jpa.LegacyCallbackProcessor; import org.hibernate.jpa.event.internal.jpa.StandardListenerFactory; import org.hibernate.jpa.event.spi.jpa.ListenerFactory; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; @@ -86,78 +83,78 @@ public void integrate( Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - // first, register the JPA-specific persist cascade style - CascadeStyles.registerCascadeStyle( - "persist", - new PersistCascadeStyle() - ); - - - // then prepare listeners - final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); - - eventListenerRegistry.addDuplicationStrategy( JPA_DUPLICATION_STRATEGY ); - - // op listeners - eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, JpaAutoFlushEventListener.INSTANCE ); - eventListenerRegistry.setListeners( EventType.DELETE, new JpaDeleteEventListener() ); - eventListenerRegistry.setListeners( EventType.FLUSH_ENTITY, new JpaFlushEntityEventListener() ); - eventListenerRegistry.setListeners( EventType.FLUSH, JpaFlushEventListener.INSTANCE ); - eventListenerRegistry.setListeners( EventType.MERGE, new JpaMergeEventListener() ); - eventListenerRegistry.setListeners( EventType.PERSIST, new JpaPersistEventListener() ); - eventListenerRegistry.setListeners( EventType.PERSIST_ONFLUSH, new JpaPersistOnFlushEventListener() ); - eventListenerRegistry.setListeners( EventType.SAVE, new JpaSaveEventListener() ); - eventListenerRegistry.setListeners( EventType.SAVE_UPDATE, new JpaSaveOrUpdateEventListener() ); - - // post op listeners - eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener() ); - eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener() ); - eventListenerRegistry.prependListeners( EventType.POST_LOAD, new JpaPostLoadEventListener() ); - eventListenerRegistry.prependListeners( EventType.POST_UPDATE, new JpaPostUpdateEventListener() ); - - for ( Map.Entry entry : configuration.getProperties().entrySet() ) { - if ( ! String.class.isInstance( entry.getKey() ) ) { - continue; - } - final String propertyName = (String) entry.getKey(); - if ( ! propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) { - continue; - } - final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 ); - final EventType eventType = EventType.resolveEventTypeByName( eventTypeName ); - final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); - for ( String listenerImpl : ( (String) entry.getValue() ).split( " ," ) ) { - eventListenerGroup.appendListener( instantiate( listenerImpl, serviceRegistry ) ); - } - } - - // handle JPA "entity listener classes"... - - this.callbackRegistry = new CallbackRegistryImpl(); - final Object beanManagerRef = configuration.getProperties().get( AvailableSettings.CDI_BEAN_MANAGER ); - this.jpaListenerFactory = beanManagerRef == null - ? new StandardListenerFactory() - : buildBeanManagerListenerFactory( beanManagerRef ); - this.callbackProcessor = new LegacyCallbackProcessor( jpaListenerFactory, configuration.getReflectionManager() ); - - Iterator classes = configuration.getClassMappings(); - while ( classes.hasNext() ) { - final PersistentClass clazz = (PersistentClass) classes.next(); - if ( clazz.getClassName() == null ) { - // we can have non java class persisted by hibernate - continue; - } - callbackProcessor.processCallbacksForEntity( clazz.getClassName(), callbackRegistry ); - } - - for ( EventType eventType : EventType.values() ) { - final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); - for ( Object listener : eventListenerGroup.listeners() ) { - if ( CallbackRegistryConsumer.class.isInstance( listener ) ) { - ( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( callbackRegistry ); - } - } - } +// // first, register the JPA-specific persist cascade style +// CascadeStyles.registerCascadeStyle( +// "persist", +// new PersistCascadeStyle() +// ); +// +// +// // then prepare listeners +// final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); +// +// eventListenerRegistry.addDuplicationStrategy( JPA_DUPLICATION_STRATEGY ); +// +// // op listeners +// eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, JpaAutoFlushEventListener.INSTANCE ); +// eventListenerRegistry.setListeners( EventType.DELETE, new JpaDeleteEventListener() ); +// eventListenerRegistry.setListeners( EventType.FLUSH_ENTITY, new JpaFlushEntityEventListener() ); +// eventListenerRegistry.setListeners( EventType.FLUSH, JpaFlushEventListener.INSTANCE ); +// eventListenerRegistry.setListeners( EventType.MERGE, new JpaMergeEventListener() ); +// eventListenerRegistry.setListeners( EventType.PERSIST, new JpaPersistEventListener() ); +// eventListenerRegistry.setListeners( EventType.PERSIST_ONFLUSH, new JpaPersistOnFlushEventListener() ); +// eventListenerRegistry.setListeners( EventType.SAVE, new JpaSaveEventListener() ); +// eventListenerRegistry.setListeners( EventType.SAVE_UPDATE, new JpaSaveOrUpdateEventListener() ); +// +// // post op listeners +// eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener() ); +// eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener() ); +// eventListenerRegistry.prependListeners( EventType.POST_LOAD, new JpaPostLoadEventListener() ); +// eventListenerRegistry.prependListeners( EventType.POST_UPDATE, new JpaPostUpdateEventListener() ); +// +// for ( Map.Entry entry : configuration.getProperties().entrySet() ) { +// if ( ! String.class.isInstance( entry.getKey() ) ) { +// continue; +// } +// final String propertyName = (String) entry.getKey(); +// if ( ! propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) { +// continue; +// } +// final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 ); +// final EventType eventType = EventType.resolveEventTypeByName( eventTypeName ); +// final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); +// for ( String listenerImpl : ( (String) entry.getValue() ).split( " ," ) ) { +// eventListenerGroup.appendListener( instantiate( listenerImpl, serviceRegistry ) ); +// } +// } +// +// // handle JPA "entity listener classes"... +// +// this.callbackRegistry = new CallbackRegistryImpl(); +// final Object beanManagerRef = configuration.getProperties().get( AvailableSettings.CDI_BEAN_MANAGER ); +// this.jpaListenerFactory = beanManagerRef == null +// ? new StandardListenerFactory() +// : buildBeanManagerListenerFactory( beanManagerRef ); +// this.callbackProcessor = new LegacyCallbackProcessor( jpaListenerFactory, configuration.getReflectionManager() ); +// +// Iterator classes = configuration.getClassMappings(); +// while ( classes.hasNext() ) { +// final PersistentClass clazz = (PersistentClass) classes.next(); +// if ( clazz.getClassName() == null ) { +// // we can have non java class persisted by hibernate +// continue; +// } +// callbackProcessor.processCallbacksForEntity( clazz.getClassName(), callbackRegistry ); +// } +// +// for ( EventType eventType : EventType.values() ) { +// final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); +// for ( Object listener : eventListenerGroup.listeners() ) { +// if ( CallbackRegistryConsumer.class.isInstance( listener ) ) { +// ( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( callbackRegistry ); +// } +// } +// } } private static final String CDI_LISTENER_FACTORY_CLASS = "org.hibernate.jpa.event.internal.jpa.BeanManagerListenerFactory"; @@ -242,7 +239,7 @@ public void integrate( // handle JPA "entity listener classes"... this.callbackRegistry = new CallbackRegistryImpl(); - final Object beanManagerRef = sessionFactory.getProperties().get( AvailableSettings.CDI_BEAN_MANAGER ); + final Object beanManagerRef = sessionFactory.getSessionFactoryOptions().getBeanManagerReference(); this.jpaListenerFactory = beanManagerRef == null ? new StandardListenerFactory() : buildBeanManagerListenerFactory( beanManagerRef ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/AbstractGraphNode.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/AbstractGraphNode.java index 5da3b05140bc..3a5018736ae3 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/AbstractGraphNode.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/AbstractGraphNode.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; + import javax.persistence.AttributeNode; import javax.persistence.metamodel.Attribute; @@ -36,7 +37,6 @@ import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.jpa.HibernateEntityManagerFactory; import org.hibernate.jpa.spi.HibernateEntityManagerFactoryAware; - import org.jboss.logging.Logger; /** @@ -44,7 +44,7 @@ * * @author Steve Ebersole */ -public abstract class AbstractGraphNode implements GraphNodeImplementor, HibernateEntityManagerFactoryAware{ +public abstract class AbstractGraphNode implements GraphNodeImplementor, HibernateEntityManagerFactoryAware { private static final Logger log = Logger.getLogger( AbstractGraphNode.class ); private final HibernateEntityManagerFactory entityManagerFactory; @@ -200,4 +200,9 @@ public SubgraphImpl addKeySubgraph(String attributeName) { public SubgraphImpl addKeySubgraph(String attributeName, Class type) { return addAttribute( attributeName ).makeKeySubgraph( type ); } + + @Override + public boolean containsAttribute(String name) { + return attributeNodeMap != null && attributeNodeMap.containsKey( name ); + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/SubgraphImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/SubgraphImpl.java index 1002af990579..b7ced5591c94 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/SubgraphImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/SubgraphImpl.java @@ -122,7 +122,7 @@ public List> getAttributeNodes() { @Override @SuppressWarnings("unchecked") protected Attribute resolveAttribute(String attributeName) { - final Attribute attribute = managedType.getDeclaredAttribute( attributeName ); + final Attribute attribute = managedType.getAttribute( attributeName ); if ( attribute == null ) { throw new IllegalArgumentException( String.format( diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerFactoryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerFactoryImpl.java index 1b168adc76ab..312a48c24cc1 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerFactoryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerFactoryImpl.java @@ -28,7 +28,6 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -56,7 +55,6 @@ import org.hibernate.Hibernate; import org.hibernate.SessionFactory; import org.hibernate.cache.spi.RegionFactory; -import org.hibernate.cfg.Configuration; import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.engine.spi.NamedQueryDefinition; @@ -78,11 +76,13 @@ import org.hibernate.jpa.graph.internal.EntityGraphImpl; import org.hibernate.jpa.graph.internal.SubgraphImpl; import org.hibernate.jpa.internal.metamodel.EntityTypeImpl; -import org.hibernate.jpa.internal.metamodel.MetamodelImpl; +import org.hibernate.jpa.internal.metamodel.MetamodelImplementor; +import org.hibernate.jpa.internal.metamodel.builder.JpaMetaModelPopulationSetting; +import org.hibernate.jpa.internal.metamodel.builder.MetamodelBuilder; import org.hibernate.jpa.internal.util.PersistenceUtilHelper; import org.hibernate.metadata.ClassMetadata; +import org.hibernate.metamodel.Metadata; import org.hibernate.procedure.ProcedureCall; -import org.hibernate.service.ServiceRegistry; import org.jboss.logging.Logger; @@ -104,7 +104,7 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory { private final transient boolean discardOnClose; private final transient Class sessionInterceptorClass; private final transient CriteriaBuilderImpl criteriaBuilder; - private final transient MetamodelImpl metamodel; + private final transient MetamodelImplementor metamodel; private final transient HibernatePersistenceUnitUtil util; private final transient Map properties; private final String entityManagerFactoryName; @@ -112,52 +112,29 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory { private final transient PersistenceUtilHelper.MetadataCache cache = new PersistenceUtilHelper.MetadataCache(); private final transient Map entityGraphs = new ConcurrentHashMap(); - @SuppressWarnings( "unchecked" ) - public EntityManagerFactoryImpl( - PersistenceUnitTransactionType transactionType, - boolean discardOnClose, - Class sessionInterceptorClass, - Configuration cfg, - ServiceRegistry serviceRegistry, - String persistenceUnitName) { - this( - persistenceUnitName, - (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry ), - new SettingsImpl().setReleaseResourcesOnCloseEnabled( discardOnClose ).setSessionInterceptorClass( sessionInterceptorClass ).setTransactionType( transactionType ), - cfg.getProperties(), - cfg - ); - } - public EntityManagerFactoryImpl( String persistenceUnitName, SessionFactoryImplementor sessionFactory, + Metadata metadata, SettingsImpl settings, - Map configurationValues, - Configuration cfg) { + Map configurationValues) { this.sessionFactory = (SessionFactoryImpl) sessionFactory; this.transactionType = settings.getTransactionType(); this.discardOnClose = settings.isReleaseResourcesOnCloseEnabled(); this.sessionInterceptorClass = settings.getSessionInterceptorClass(); - final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg ); + final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( configurationValues ); if ( JpaMetaModelPopulationSetting.DISABLED == jpaMetaModelPopulationSetting ) { this.metamodel = null; } else { - this.metamodel = MetamodelImpl.buildMetamodel( - cfg.getClassMappings(), - cfg.getMappedSuperclassMappingsCopy(), - sessionFactory, - JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED == jpaMetaModelPopulationSetting - ); + this.metamodel = MetamodelBuilder.oneShot( sessionFactory, metadata, jpaMetaModelPopulationSetting ); } this.criteriaBuilder = new CriteriaBuilderImpl( this ); this.util = new HibernatePersistenceUnitUtil( this ); HashMap props = new HashMap(); addAll( props, sessionFactory.getProperties() ); - addAll( props, cfg.getProperties() ); addAll( props, configurationValues ); maskOutSensitiveInformation( props ); this.properties = Collections.unmodifiableMap( props ); @@ -170,37 +147,23 @@ public EntityManagerFactoryImpl( } this.entityManagerFactoryName = entityManagerFactoryName; - applyNamedEntityGraphs( cfg.getNamedEntityGraphs() ); + applyNamedEntityGraphs( metadata.getNamedEntityGraphs() ); EntityManagerFactoryRegistry.INSTANCE.addEntityManagerFactory( entityManagerFactoryName, this ); } - - private enum JpaMetaModelPopulationSetting { - ENABLED, - DISABLED, - IGNORE_UNSUPPORTED; - - private static JpaMetaModelPopulationSetting parse(String setting) { - if ( "enabled".equalsIgnoreCase( setting ) ) { - return ENABLED; - } - else if ( "disabled".equalsIgnoreCase( setting ) ) { - return DISABLED; - } - else { - return IGNORE_UNSUPPORTED; - } - } - } - protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Configuration cfg) { + protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Map configurationValues) { String setting = ConfigurationHelper.getString( AvailableSettings.JPA_METAMODEL_POPULATION, - cfg.getProperties(), + configurationValues, null ); if ( setting == null ) { - setting = ConfigurationHelper.getString( AvailableSettings.JPA_METAMODEL_GENERATION, cfg.getProperties(), null ); + setting = ConfigurationHelper.getString( + AvailableSettings.JPA_METAMODEL_GENERATION, + configurationValues, + null + ); if ( setting != null ) { log.infof( "Encountered deprecated setting [%s], use [%s] instead", @@ -232,8 +195,8 @@ private void maskOutIfSet(HashMap props, String setting) { } @SuppressWarnings("unchecked") - private void applyNamedEntityGraphs(Collection namedEntityGraphs) { - for ( NamedEntityGraphDefinition definition : namedEntityGraphs ) { + private void applyNamedEntityGraphs(Map namedEntityGraphs) { + for ( NamedEntityGraphDefinition definition : namedEntityGraphs.values() ) { log.debugf( "Applying named entity graph [name=%s, entity-name=%s, jpa-entity-name=%s", definition.getRegisteredName(), diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java index 07399e245f63..2eb79ea4cd48 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerMessageLogger.java @@ -71,13 +71,6 @@ public interface EntityManagerMessageLogger extends CoreMessageLogger { @Message( value = "Exploded jar file not a directory (ignored): %s", id = 15006 ) void explodedJarNotDirectory( URL jarUrl ); - @LogMessage( level = ERROR ) - @Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 ) - void illegalArgumentOnStaticMetamodelFieldInjection( String name, - String name2, - String name3, - String name4 ); - @LogMessage( level = ERROR ) @Message( value = "Malformed URL: %s", id = 15008 ) void malformedUrl( URL jarUrl, @@ -93,11 +86,6 @@ void malformedUrlWarning( URL jarUrl, void unableToFindFile( URL jarUrl, @Cause Exception e ); - @LogMessage( level = ERROR ) - @Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 ) - void unableToLocateStaticMetamodelField( String name, - String name2 ); - @LogMessage( level = INFO ) @Message( value = "Using provided datasource", id = 15012 ) void usingProvidedDataSource(); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractIdentifiableType.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractIdentifiableType.java index 25337d08b09d..eb650b73f4d2 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractIdentifiableType.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractIdentifiableType.java @@ -67,6 +67,13 @@ public AbstractIdentifiableType( this.isVersioned = versioned; } + @Override + @SuppressWarnings("unchecked") + public AbstractIdentifiableType getSupertype() { + // overridden simply to perform the cast + return (AbstractIdentifiableType) super.getSupertype(); + } + public boolean hasIdClass() { return hasIdClass; } @@ -76,13 +83,6 @@ public boolean hasSingleIdAttribute() { return !hasIdClass() && hasIdentifierProperty; } - @Override - @SuppressWarnings("unchecked") - public AbstractIdentifiableType getSupertype() { - // overridden simply to perform the cast - return (AbstractIdentifiableType) super.getSupertype(); - } - @Override @SuppressWarnings({ "unchecked" }) public SingularAttribute getId(Class javaType) { @@ -300,14 +300,17 @@ private void checkDeclaredVersion() { return version; } + @Override public Builder getBuilder() { final AbstractManagedType.Builder managedBuilder = super.getBuilder(); return new Builder() { + @Override public void applyIdAttribute(SingularAttributeImpl idAttribute) { AbstractIdentifiableType.this.id = idAttribute; managedBuilder.addAttribute( idAttribute ); } + @Override public void applyIdClassAttributes(Set> idClassAttributes) { for ( SingularAttribute idClassAttribute : idClassAttributes ) { if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) { @@ -318,12 +321,13 @@ public void applyIdClassAttributes(Set> idClassAt } AbstractIdentifiableType.this.idClassAttributes = idClassAttributes; } - + @Override public void applyVersionAttribute(SingularAttributeImpl versionAttribute) { AbstractIdentifiableType.this.version = versionAttribute; managedBuilder.addAttribute( versionAttribute ); } + @Override public void addAttribute(Attribute attribute) { managedBuilder.addAttribute( attribute ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractManagedType.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractManagedType.java index 784154175813..1cd85d0a6fb4 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractManagedType.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractManagedType.java @@ -63,11 +63,11 @@ protected AbstractManagedType(Class javaType, String typeName, AbstractManage this.superType = superType; } - protected AbstractManagedType getSupertype() { + public AbstractManagedType getSupertype() { return superType; } - private boolean locked; + private boolean locked = false; public Builder getBuilder() { if ( locked ) { @@ -75,7 +75,6 @@ public Builder getBuilder() { } return new Builder() { @Override - @SuppressWarnings("unchecked") public void addAttribute(Attribute attribute) { declaredAttributes.put( attribute.getName(), attribute ); final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType(); @@ -127,28 +126,19 @@ public static interface Builder { if ( attribute == null && getSupertype() != null ) { attribute = getSupertype().getAttribute( name ); } - checkNotNull( "Attribute ", attribute, name ); return attribute; } @Override public Attribute getDeclaredAttribute(String name) { - Attribute attr = declaredAttributes.get( name ); + final Attribute attr = declaredAttributes.get( name ); checkNotNull( "Attribute ", attr, name ); return attr; } private void checkNotNull(String attributeType, Attribute attribute, String name) { - if ( attribute == null ) { - throw new IllegalArgumentException( - String.format( - "Unable to locate %s with the the given name [%s] on this ManagedType [%s]", - attributeType, - name, - getTypeName() - ) - ); + throw new IllegalArgumentException( attributeType + " named " + name + " is not present" ); } } @@ -174,7 +164,6 @@ private void checkNotNull(String attributeType, Attribute attribute, String if ( attribute == null && getSupertype() != null ) { attribute = getSupertype().getSingularAttribute( name ); } - checkNotNull( "SingularAttribute ", attribute, name ); return attribute; } @@ -215,8 +204,8 @@ private void checkTypeForSingleAttribute( } throw new IllegalArgumentException( attributeType + " named " + name - + ( javaType != null ? " and of type " + javaType.getName() : "" ) - + " is not present" + + ( javaType != null ? " and of type " + javaType.getName() : "" ) + + " is not present" ); } } @@ -343,7 +332,6 @@ private void basicListCheck(PluralAttribute attribute, String n } @Override - @SuppressWarnings("unchecked") public ListAttribute getDeclaredList(String name) { final PluralAttribute attribute = declaredPluralAttributes.get( name ); basicListCheck( attribute, name ); @@ -369,7 +357,6 @@ private void basicMapCheck(PluralAttribute attribute, String na } @Override - @SuppressWarnings("unchecked") public MapAttribute getDeclaredMap(String name) { final PluralAttribute attribute = declaredPluralAttributes.get( name ); basicMapCheck( attribute, name ); @@ -388,7 +375,6 @@ public CollectionAttribute getCollection(String name, Class } @Override - @SuppressWarnings("unchecked") public CollectionAttribute getDeclaredCollection(String name, Class elementType) { final PluralAttribute attribute = declaredPluralAttributes.get( name ); checkCollectionElementType( attribute, name, elementType ); @@ -410,8 +396,8 @@ private void checkTypeForPluralAttributes( || attribute.getCollectionType() != collectionType ) { throw new IllegalArgumentException( attributeType + " named " + name - + ( elementType != null ? " and of element type " + elementType : "" ) - + " is not present" + + ( elementType != null ? " and of element type " + elementType : "" ) + + " is not present" ); } } @@ -432,7 +418,6 @@ private void checkSetElementType(PluralAttribute attribute, } @Override - @SuppressWarnings("unchecked") public SetAttribute getDeclaredSet(String name, Class elementType) { final PluralAttribute attribute = declaredPluralAttributes.get( name ); checkSetElementType( attribute, name, elementType ); @@ -455,7 +440,6 @@ private void checkListElementType(PluralAttribute attribute } @Override - @SuppressWarnings("unchecked") public ListAttribute getDeclaredList(String name, Class elementType) { final PluralAttribute attribute = declaredPluralAttributes.get( name ); checkListElementType( attribute, name, elementType ); @@ -486,7 +470,6 @@ private void checkMapKeyType(MapAttribute mapAttribute, S } @Override - @SuppressWarnings("unchecked") public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { final PluralAttribute attribute = declaredPluralAttributes.get( name ); checkMapValueType( attribute, name, valueType ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractType.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractType.java index 84cb83723b2f..4fe383ab9f57 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractType.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AbstractType.java @@ -36,15 +36,6 @@ public abstract class AbstractType implements Type, Serializable { private final Class javaType; private final String typeName; - /** - * Instantiates the type based on the given Java type. - * - * @param javaType The Java type of the JPA model type. - */ - protected AbstractType(Class javaType) { - this( javaType, javaType != null ? javaType.getName() : null ); - } - /** * Instantiates the type based on the given Java type. * diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AttributeFactory.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AttributeFactory.java deleted file mode 100755 index f8b0e88cd009..000000000000 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/AttributeFactory.java +++ /dev/null @@ -1,1073 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.jpa.internal.metamodel; - -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.TypeVariable; -import java.util.Iterator; -import javax.persistence.ManyToMany; -import javax.persistence.OneToOne; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.Type; - -import org.hibernate.annotations.common.AssertionFailure; -import org.hibernate.jpa.internal.EntityManagerMessageLogger; -import org.hibernate.jpa.internal.HEMLogging; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Map; -import org.hibernate.mapping.OneToMany; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Value; -import org.hibernate.property.Getter; -import org.hibernate.property.MapAccessor; -import org.hibernate.tuple.entity.EntityMetamodel; -import org.hibernate.type.ComponentType; -import org.hibernate.type.EmbeddedComponentType; -import org.hibernate.type.EntityType; - -/** - * A factory for building {@link Attribute} instances. Exposes 3 main services for building
      - *
    1. {@link #buildAttribute normal attributes}
    2. - *
    3. {@link #buildIdAttribute id attributes}
    4. - *
    5. {@link #buildVersionAttribute version attributes}
    6. - *
        - * - * @author Steve Ebersole - * @author Emmanuel Bernard - */ -public class AttributeFactory { - private static final EntityManagerMessageLogger LOG = HEMLogging.messageLogger( AttributeFactory.class ); - - private final MetadataContext context; - - public AttributeFactory(MetadataContext context) { - this.context = context; - } - - /** - * Build a normal attribute. - * - * @param ownerType The descriptor of the attribute owner (aka declarer). - * @param property The Hibernate property descriptor for the attribute - * @param The type of the owner - * @param The attribute type - * - * @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs) - */ - @SuppressWarnings({"unchecked"}) - public AttributeImplementor buildAttribute(AbstractManagedType ownerType, Property property) { - if ( property.isSynthetic() ) { - // hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel. - LOG.tracef( "Skipping synthetic property %s(%s)", ownerType.getTypeName(), property.getName() ); - return null; - } - LOG.trace( "Building attribute [" + ownerType.getTypeName() + "." + property.getName() + "]" ); - final AttributeContext attributeContext = wrap( ownerType, property ); - final AttributeMetadata attributeMetadata = - determineAttributeMetadata( attributeContext, normalMemberResolver ); - if ( attributeMetadata == null ) { - return null; - } - if ( attributeMetadata.isPlural() ) { - return buildPluralAttribute( (PluralAttributeMetadata) attributeMetadata ); - } - final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata) attributeMetadata; - final Type metaModelType = getMetaModelType( singularAttributeMetadata.getValueContext() ); - return new SingularAttributeImpl( - attributeMetadata.getName(), - attributeMetadata.getJavaType(), - ownerType, - attributeMetadata.getMember(), - false, - false, - property.isOptional(), - metaModelType, - attributeMetadata.getPersistentAttributeType() - ); - } - - private AttributeContext wrap(final AbstractManagedType ownerType, final Property property) { - return new AttributeContext() { - public AbstractManagedType getOwnerType() { - return ownerType; - } - - public Property getPropertyMapping() { - return property; - } - }; - } - - /** - * Build the identifier attribute descriptor - * - * @param ownerType The descriptor of the attribute owner (aka declarer). - * @param property The Hibernate property descriptor for the identifier attribute - * @param The type of the owner - * @param The attribute type - * - * @return The built attribute descriptor - */ - @SuppressWarnings({"unchecked"}) - public SingularAttributeImpl buildIdAttribute( - AbstractIdentifiableType ownerType, - Property property) { - LOG.trace( "Building identifier attribute [" + ownerType.getTypeName() + "." + property.getName() + "]" ); - final AttributeContext attributeContext = wrap( ownerType, property ); - final SingularAttributeMetadata attributeMetadata = - (SingularAttributeMetadata) determineAttributeMetadata( - attributeContext, - identifierMemberResolver - ); - final Type metaModelType = getMetaModelType( attributeMetadata.getValueContext() ); - return new SingularAttributeImpl.Identifier( - property.getName(), - attributeMetadata.getJavaType(), - ownerType, - attributeMetadata.getMember(), - metaModelType, - attributeMetadata.getPersistentAttributeType() - ); - } - - /** - * Build the version attribute descriptor - * - * @param ownerType The descriptor of the attribute owner (aka declarer). - * @param property The Hibernate property descriptor for the version attribute - * @param The type of the owner - * @param The attribute type - * - * @return The built attribute descriptor - */ - @SuppressWarnings({"unchecked"}) - public SingularAttributeImpl buildVersionAttribute( - AbstractIdentifiableType ownerType, - Property property) { - LOG.trace( "Building version attribute [ownerType.getTypeName()" + "." + "property.getName()]" ); - final AttributeContext attributeContext = wrap( ownerType, property ); - final SingularAttributeMetadata attributeMetadata = - (SingularAttributeMetadata) determineAttributeMetadata( attributeContext, versionMemberResolver ); - final Type metaModelType = getMetaModelType( attributeMetadata.getValueContext() ); - return new SingularAttributeImpl.Version( - property.getName(), - attributeMetadata.getJavaType(), - ownerType, - attributeMetadata.getMember(), - metaModelType, - attributeMetadata.getPersistentAttributeType() - ); - } - - @SuppressWarnings("unchecked") - private AttributeImplementor buildPluralAttribute(PluralAttributeMetadata attributeMetadata) { - final Type elementType = getMetaModelType( attributeMetadata.getElementValueContext() ); - if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) { - final Type keyType = getMetaModelType( attributeMetadata.getMapKeyValueContext() ); - return PluralAttributeImpl.create( - attributeMetadata.getOwnerType(), - elementType, - attributeMetadata.getJavaType(), - keyType - ) - .member( attributeMetadata.getMember() ) - .property( attributeMetadata.getPropertyMapping() ) - .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) - .build(); - } - return PluralAttributeImpl.create( - attributeMetadata.getOwnerType(), - elementType, - attributeMetadata.getJavaType(), - null - ) - .member( attributeMetadata.getMember() ) - .property( attributeMetadata.getPropertyMapping() ) - .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) - .build(); - } - - @SuppressWarnings("unchecked") - private Type getMetaModelType(ValueContext typeContext) { - switch ( typeContext.getValueClassification() ) { - case BASIC: { - return new BasicTypeImpl( - typeContext.getBindableType(), - Type.PersistenceType.BASIC - ); - } - case ENTITY: { - final org.hibernate.type.EntityType type = (EntityType) typeContext.getValue().getType(); - return (Type) context.locateEntityType( type.getAssociatedEntityName() ); - } - case EMBEDDABLE: { - final Component component = (Component) typeContext.getValue(); - final EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl( - typeContext.getBindableType(), - typeContext.getAttributeMetadata().getOwnerType(), - (ComponentType) typeContext.getValue().getType() - ); - context.registerEmbeddedableType( embeddableType ); - final Iterator subProperties = component.getPropertyIterator(); - while ( subProperties.hasNext() ) { - final Property property = subProperties.next(); - final AttributeImplementor attribute = buildAttribute( embeddableType, property ); - if ( attribute != null ) { - embeddableType.getBuilder().addAttribute( attribute ); - } - } - embeddableType.lock(); - return embeddableType; - } - default: { - throw new AssertionFailure( "Unknown type : " + typeContext.getValueClassification() ); - } - } - } - - private EntityMetamodel getDeclarerEntityMetamodel(AbstractIdentifiableType ownerType) { - final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); - if ( persistenceType == Type.PersistenceType.ENTITY ) { - return context.getSessionFactory() - .getEntityPersister( ownerType.getTypeName() ) - .getEntityMetamodel(); - } - else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) { - PersistentClass persistentClass = - context.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl) ownerType ); - return context.getSessionFactory() - .getEntityPersister( persistentClass.getClassName() ) - .getEntityMetamodel(); - } - else { - throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType ); - } - } - - /** - * A contract for defining the meta information about a {@link Value} - */ - private interface ValueContext { - /** - * Enum of the simplified types a value might be. These relate more to the Hibernate classification - * then the JPA classification - */ - enum ValueClassification { - EMBEDDABLE, - ENTITY, - BASIC - } - - /** - * Retrieve the value itself - * - * @return The value - */ - public Value getValue(); - - public Class getBindableType(); - - /** - * Retrieve the simplified value classification - * - * @return The value type - */ - public ValueClassification getValueClassification(); - - /** - * Retrieve the metadata about the attribute from which this value comes - * - * @return The "containing" attribute metadata. - */ - public AttributeMetadata getAttributeMetadata(); - } - - /** - * Basic contract for describing an attribute. The "description" is partially in terms - * of JPA ({@link #getPersistentAttributeType} and {@link #getOwnerType}), partially in - * terms of Hibernate ({@link #getPropertyMapping}) and partially just in terms of the java - * model itself ({@link #getName}, {@link #getMember} and {@link #getJavaType}). - * - * @param The attribute owner type - * @param The attribute type. - */ - private interface AttributeMetadata { - /** - * Retrieve the name of the attribute - * - * @return The attribute name - */ - public String getName(); - - /** - * Retrieve the member defining the attribute - * - * @return The attribute member - */ - public Member getMember(); - - /** - * Retrieve the attribute java type. - * - * @return The java type of the attribute. - */ - public Class getJavaType(); - - /** - * Get the JPA attribute type classification for this attribute. - * - * @return The JPA attribute type classification - */ - public Attribute.PersistentAttributeType getPersistentAttributeType(); - - /** - * Retrieve the attribute owner's metamodel information - * - * @return The metamodel information for the attribute owner - */ - public AbstractManagedType getOwnerType(); - - /** - * Retrieve the Hibernate property mapping related to this attribute. - * - * @return The Hibernate property mapping - */ - public Property getPropertyMapping(); - - /** - * Is the attribute plural (a collection)? - * - * @return True if it is plural, false otherwise. - */ - public boolean isPlural(); - } - - /** - * Attribute metadata contract for a non-plural attribute. - * - * @param The owner type - * @param The attribute type - */ - private interface SingularAttributeMetadata extends AttributeMetadata { - /** - * Retrieve the value context for this attribute - * - * @return The attributes value context - */ - public ValueContext getValueContext(); - } - - /** - * Attribute metadata contract for a plural attribute. - * - * @param The owner type - * @param The attribute type (the collection type) - * @param The collection element type - */ - @SuppressWarnings("UnusedDeclaration") - private interface PluralAttributeMetadata extends AttributeMetadata { - /** - * Retrieve the JPA collection type classification for this attribute - * - * @return The JPA collection type classification - */ - public PluralAttribute.CollectionType getAttributeCollectionType(); - - /** - * Retrieve the value context for the collection's elements. - * - * @return The value context for the collection's elements. - */ - public ValueContext getElementValueContext(); - - /** - * Retrieve the value context for the collection's keys (if a map, null otherwise). - * - * @return The value context for the collection's keys (if a map, null otherwise). - */ - public ValueContext getMapKeyValueContext(); - } - - /** - * Bundle's a Hibernate property mapping together with the JPA metamodel information - * of the attribute owner. - * - * @param The owner type. - */ - private interface AttributeContext { - /** - * Retrieve the attribute owner. - * - * @return The owner. - */ - public AbstractManagedType getOwnerType(); - - /** - * Retrieve the Hibernate property mapping. - * - * @return The Hibernate property mapping. - */ - public Property getPropertyMapping(); - } - - /** - * Contract for how we resolve the {@link Member} for a give attribute context. - */ - private interface MemberResolver { - public Member resolveMember(AttributeContext attributeContext); - } - - /** - * Here is most of the nuts and bolts of this factory, where we interpret the known JPA metadata - * against the known Hibernate metadata and build a descriptor for the attribute. - * - * @param attributeContext The attribute to be described - * @param memberResolver Strategy for how to resolve the member defining the attribute. - * @param The owner type - * @param The attribute type - * - * @return The attribute description - */ - @SuppressWarnings({"unchecked"}) - private AttributeMetadata determineAttributeMetadata( - AttributeContext attributeContext, - MemberResolver memberResolver) { - LOG.trace( - "Starting attribute metadata determination [" + attributeContext.getPropertyMapping() - .getName() + "]" - ); - final Member member = memberResolver.resolveMember( attributeContext ); - LOG.trace( " Determined member [" + member + "]" ); - - final Value value = attributeContext.getPropertyMapping().getValue(); - final org.hibernate.type.Type type = value.getType(); - LOG.trace( " Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]" ); - - if ( type.isAnyType() ) { - // ANY mappings are currently not supported in the JPA metamodel; see HHH-6589 - if ( context.isIgnoreUnsupported() ) { - return null; - } - else { - throw new UnsupportedOperationException( "ANY not supported" ); - } - } - else if ( type.isAssociationType() ) { - // collection or entity - if ( type.isEntityType() ) { - // entity - return new SingularAttributeMetadataImpl( - attributeContext.getPropertyMapping(), - attributeContext.getOwnerType(), - member, - determineSingularAssociationAttributeType( member ) - ); - } - // collection - if ( value instanceof Collection ) { - final Collection collValue = (Collection) value; - final Value elementValue = collValue.getElement(); - final org.hibernate.type.Type elementType = elementValue.getType(); - - // First, determine the type of the elements and use that to help determine the - // collection type) - final Attribute.PersistentAttributeType elementPersistentAttributeType; - final Attribute.PersistentAttributeType persistentAttributeType; - if ( elementType.isAnyType() ) { - if ( context.isIgnoreUnsupported() ) { - return null; - } - else { - throw new UnsupportedOperationException( "collection of any not supported yet" ); - } - } - final boolean isManyToMany = isManyToMany( member ); - if ( elementValue instanceof Component ) { - elementPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED; - persistentAttributeType = Attribute.PersistentAttributeType.ELEMENT_COLLECTION; - } - else if ( elementType.isAssociationType() ) { - elementPersistentAttributeType = isManyToMany ? - Attribute.PersistentAttributeType.MANY_TO_MANY : - Attribute.PersistentAttributeType.ONE_TO_MANY; - persistentAttributeType = elementPersistentAttributeType; - } - else { - elementPersistentAttributeType = Attribute.PersistentAttributeType.BASIC; - persistentAttributeType = Attribute.PersistentAttributeType.ELEMENT_COLLECTION; - } - - final Attribute.PersistentAttributeType keyPersistentAttributeType; - - // Finally, we determine the type of the map key (if needed) - if ( value instanceof Map ) { - final Value keyValue = ( (Map) value ).getIndex(); - final org.hibernate.type.Type keyType = keyValue.getType(); - - if ( keyType.isAnyType() ) { - if ( context.isIgnoreUnsupported() ) { - return null; - } - else { - throw new UnsupportedOperationException( "collection of any not supported yet" ); - } - } - if ( keyValue instanceof Component ) { - keyPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED; - } - else if ( keyType.isAssociationType() ) { - keyPersistentAttributeType = Attribute.PersistentAttributeType.MANY_TO_ONE; - } - else { - keyPersistentAttributeType = Attribute.PersistentAttributeType.BASIC; - } - } - else { - keyPersistentAttributeType = null; - } - return new PluralAttributeMetadataImpl( - attributeContext.getPropertyMapping(), attributeContext.getOwnerType(), - member, persistentAttributeType, elementPersistentAttributeType, - keyPersistentAttributeType - ); - } - else if ( value instanceof OneToMany ) { - // TODO : is this even possible??? Really OneToMany should be describing the - // element value within a o.h.mapping.Collection (see logic branch above) - throw new IllegalArgumentException( "HUH???" ); -// final boolean isManyToMany = isManyToMany( member ); -// //one to many with FK => entity -// return new PluralAttributeMetadataImpl( -// attributeContext.getPropertyMapping(), -// attributeContext.getOwnerType(), -// member, -// isManyToMany -// ? Attribute.PersistentAttributeType.MANY_TO_MANY -// : Attribute.PersistentAttributeType.ONE_TO_MANY -// value, -// AttributeContext.TypeStatus.ENTITY, -// Attribute.PersistentAttributeType.ONE_TO_MANY, -// null, null, null -// ); - } - } - else if ( attributeContext.getPropertyMapping().isComposite() ) { - // component - return new SingularAttributeMetadataImpl( - attributeContext.getPropertyMapping(), - attributeContext.getOwnerType(), - member, - Attribute.PersistentAttributeType.EMBEDDED - ); - } - else { - // basic type - return new SingularAttributeMetadataImpl( - attributeContext.getPropertyMapping(), - attributeContext.getOwnerType(), - member, - Attribute.PersistentAttributeType.BASIC - ); - } - throw new UnsupportedOperationException( "oops, we are missing something: " + attributeContext.getPropertyMapping() ); - } - - public static Attribute.PersistentAttributeType determineSingularAssociationAttributeType(Member member) { - if ( Field.class.isInstance( member ) ) { - return ( (Field) member ).getAnnotation( OneToOne.class ) != null - ? Attribute.PersistentAttributeType.ONE_TO_ONE - : Attribute.PersistentAttributeType.MANY_TO_ONE; - } - else if ( MapMember.class.isInstance( member ) ) { - return Attribute.PersistentAttributeType.MANY_TO_ONE; // curious to see how this works for non-annotated methods - } - else { - return ( (Method) member ).getAnnotation( OneToOne.class ) != null - ? Attribute.PersistentAttributeType.ONE_TO_ONE - : Attribute.PersistentAttributeType.MANY_TO_ONE; - } - } - - private abstract class BaseAttributeMetadata implements AttributeMetadata { - private final Property propertyMapping; - private final AbstractManagedType ownerType; - private final Member member; - private final Class javaType; - private final Attribute.PersistentAttributeType persistentAttributeType; - - @SuppressWarnings({"unchecked"}) - protected BaseAttributeMetadata( - Property propertyMapping, - AbstractManagedType ownerType, - Member member, - Attribute.PersistentAttributeType persistentAttributeType) { - this.propertyMapping = propertyMapping; - this.ownerType = ownerType; - this.member = member; - this.persistentAttributeType = persistentAttributeType; - - final Class declaredType; - - if ( member == null ) { - // assume we have a MAP entity-mode "class" - declaredType = propertyMapping.getType().getReturnedClass(); - } - else if ( Field.class.isInstance( member ) ) { - declaredType = ( (Field) member ).getType(); - } - else if ( Method.class.isInstance( member ) ) { - declaredType = ( (Method) member ).getReturnType(); - } - else if ( MapMember.class.isInstance( member ) ) { - declaredType = ( (MapMember) member ).getType(); - } - else { - throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" ); - } - this.javaType = accountForPrimitiveTypes( declaredType ); - } - - public String getName() { - return propertyMapping.getName(); - } - - public Member getMember() { - return member; - } - - public String getMemberDescription() { - return determineMemberDescription( getMember() ); - } - - public String determineMemberDescription(Member member) { - return member.getDeclaringClass().getName() + '#' + member.getName(); - } - - public Class getJavaType() { - return javaType; - } - - public Attribute.PersistentAttributeType getPersistentAttributeType() { - return persistentAttributeType; - } - - public AbstractManagedType getOwnerType() { - return ownerType; - } - - public boolean isPlural() { - return propertyMapping.getType().isCollectionType(); - } - - public Property getPropertyMapping() { - return propertyMapping; - } - } - - @SuppressWarnings({"unchecked"}) - protected Class accountForPrimitiveTypes(Class declaredType) { -// if ( !declaredType.isPrimitive() ) { -// return declaredType; -// } -// -// if ( Boolean.TYPE.equals( declaredType ) ) { -// return (Class) Boolean.class; -// } -// if ( Character.TYPE.equals( declaredType ) ) { -// return (Class) Character.class; -// } -// if( Byte.TYPE.equals( declaredType ) ) { -// return (Class) Byte.class; -// } -// if ( Short.TYPE.equals( declaredType ) ) { -// return (Class) Short.class; -// } -// if ( Integer.TYPE.equals( declaredType ) ) { -// return (Class) Integer.class; -// } -// if ( Long.TYPE.equals( declaredType ) ) { -// return (Class) Long.class; -// } -// if ( Float.TYPE.equals( declaredType ) ) { -// return (Class) Float.class; -// } -// if ( Double.TYPE.equals( declaredType ) ) { -// return (Class) Double.class; -// } -// -// throw new IllegalArgumentException( "Unexpected type [" + declaredType + "]" ); - // if the field is defined as int, return int not Integer... - return declaredType; - } - - private class SingularAttributeMetadataImpl - extends BaseAttributeMetadata - implements SingularAttributeMetadata { - private final ValueContext valueContext; - - private SingularAttributeMetadataImpl( - Property propertyMapping, - AbstractManagedType ownerType, - Member member, - Attribute.PersistentAttributeType persistentAttributeType) { - super( propertyMapping, ownerType, member, persistentAttributeType ); - valueContext = new ValueContext() { - public Value getValue() { - return getPropertyMapping().getValue(); - } - - public Class getBindableType() { - return getAttributeMetadata().getJavaType(); - } - - public ValueClassification getValueClassification() { - switch ( getPersistentAttributeType() ) { - case EMBEDDED: { - return ValueClassification.EMBEDDABLE; - } - case BASIC: { - return ValueClassification.BASIC; - } - default: { - return ValueClassification.ENTITY; - } - } - } - - public AttributeMetadata getAttributeMetadata() { - return SingularAttributeMetadataImpl.this; - } - }; - } - - public ValueContext getValueContext() { - return valueContext; - } - } - - private class PluralAttributeMetadataImpl - extends BaseAttributeMetadata - implements PluralAttributeMetadata { - private final PluralAttribute.CollectionType attributeCollectionType; - private final Attribute.PersistentAttributeType elementPersistentAttributeType; - private final Attribute.PersistentAttributeType keyPersistentAttributeType; - private final Class elementJavaType; - private final Class keyJavaType; - private final ValueContext elementValueContext; - private final ValueContext keyValueContext; - - private PluralAttributeMetadataImpl( - Property propertyMapping, - AbstractManagedType ownerType, - Member member, - Attribute.PersistentAttributeType persistentAttributeType, - Attribute.PersistentAttributeType elementPersistentAttributeType, - Attribute.PersistentAttributeType keyPersistentAttributeType) { - super( propertyMapping, ownerType, member, persistentAttributeType ); - this.attributeCollectionType = determineCollectionType( getJavaType() ); - this.elementPersistentAttributeType = elementPersistentAttributeType; - this.keyPersistentAttributeType = keyPersistentAttributeType; - - ParameterizedType signatureType = getSignatureType( member ); - if ( keyPersistentAttributeType == null ) { - elementJavaType = signatureType != null ? - getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : - Object.class; //FIXME and honor targetEntity? - keyJavaType = null; - } - else { - keyJavaType = signatureType != null ? - getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : - Object.class; //FIXME and honor targetEntity? - elementJavaType = signatureType != null ? - getClassFromGenericArgument( signatureType.getActualTypeArguments()[1] ) : - Object.class; //FIXME and honor targetEntity? - } - - this.elementValueContext = new ValueContext() { - public Value getValue() { - return ( (Collection) getPropertyMapping().getValue() ).getElement(); - } - - public Class getBindableType() { - return elementJavaType; - } - - public ValueClassification getValueClassification() { - switch ( PluralAttributeMetadataImpl.this.elementPersistentAttributeType ) { - case EMBEDDED: { - return ValueClassification.EMBEDDABLE; - } - case BASIC: { - return ValueClassification.BASIC; - } - default: { - return ValueClassification.ENTITY; - } - } - } - - public AttributeMetadata getAttributeMetadata() { - return PluralAttributeMetadataImpl.this; - } - }; - - // interpret the key, if one - if ( keyPersistentAttributeType != null ) { - this.keyValueContext = new ValueContext() { - public Value getValue() { - return ( (Map) getPropertyMapping().getValue() ).getIndex(); - } - - public Class getBindableType() { - return keyJavaType; - } - - public ValueClassification getValueClassification() { - switch ( PluralAttributeMetadataImpl.this.keyPersistentAttributeType ) { - case EMBEDDED: { - return ValueClassification.EMBEDDABLE; - } - case BASIC: { - return ValueClassification.BASIC; - } - default: { - return ValueClassification.ENTITY; - } - } - } - - public AttributeMetadata getAttributeMetadata() { - return PluralAttributeMetadataImpl.this; - } - }; - } - else { - keyValueContext = null; - } - } - - private Class getClassFromGenericArgument(java.lang.reflect.Type type) { - if ( type instanceof Class ) { - return (Class) type; - } - else if ( type instanceof TypeVariable ) { - final java.lang.reflect.Type upperBound = ( (TypeVariable) type ).getBounds()[0]; - return getClassFromGenericArgument( upperBound ); - } - else if ( type instanceof ParameterizedType ) { - final java.lang.reflect.Type rawType = ( (ParameterizedType) type ).getRawType(); - return getClassFromGenericArgument( rawType ); - } - else { - throw new AssertionFailure( - "Fail to process type argument in a generic declaration. Member : " + getMemberDescription() - + " Type: " + type.getClass() - ); - } - } - - public ValueContext getElementValueContext() { - return elementValueContext; - } - - public PluralAttribute.CollectionType getAttributeCollectionType() { - return attributeCollectionType; - } - - public ValueContext getMapKeyValueContext() { - return keyValueContext; - } - } - - public static ParameterizedType getSignatureType(Member member) { - final java.lang.reflect.Type type; - if ( Field.class.isInstance( member ) ) { - type = ( (Field) member ).getGenericType(); - } - else if ( Method.class.isInstance( member ) ) { - type = ( (Method) member ).getGenericReturnType(); - } - else { - type = ( (MapMember) member ).getType(); - } - //this is a raw type - if ( type instanceof Class ) { - return null; - } - return (ParameterizedType) type; - } - - public static PluralAttribute.CollectionType determineCollectionType(Class javaType) { - if ( java.util.List.class.isAssignableFrom( javaType ) ) { - return PluralAttribute.CollectionType.LIST; - } - else if ( java.util.Set.class.isAssignableFrom( javaType ) ) { - return PluralAttribute.CollectionType.SET; - } - else if ( java.util.Map.class.isAssignableFrom( javaType ) ) { - return PluralAttribute.CollectionType.MAP; - } - else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) { - return PluralAttribute.CollectionType.COLLECTION; - } - else { - throw new IllegalArgumentException( "Expecting collection type [" + javaType.getName() + "]" ); - } - } - - public static boolean isManyToMany(Member member) { - if ( Field.class.isInstance( member ) ) { - return ( (Field) member ).getAnnotation( ManyToMany.class ) != null; - } - else if ( Method.class.isInstance( member ) ) { - return ( (Method) member ).getAnnotation( ManyToMany.class ) != null; - } - - return false; - } - - private final MemberResolver embeddedMemberResolver = new MemberResolver() { - @Override - public Member resolveMember(AttributeContext attributeContext) { - final EmbeddableTypeImpl embeddableType = (EmbeddableTypeImpl) attributeContext.getOwnerType(); - final String attributeName = attributeContext.getPropertyMapping().getName(); - - final Getter getter = embeddableType.getHibernateType() - .getComponentTuplizer() - .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ); - return MapAccessor.MapGetter.class.isInstance( getter ) - ? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() ) - : getter.getMember(); - } - }; - - - private final MemberResolver virtualIdentifierMemberResolver = new MemberResolver() { - @Override - public Member resolveMember(AttributeContext attributeContext) { - final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); - final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); - if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { - throw new IllegalArgumentException( "expecting IdClass mapping" ); - } - org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType(); - if ( !EmbeddedComponentType.class.isInstance( type ) ) { - throw new IllegalArgumentException( "expecting IdClass mapping" ); - } - - final EmbeddedComponentType componentType = (EmbeddedComponentType) type; - final String attributeName = attributeContext.getPropertyMapping().getName(); - - final Getter getter = componentType.getComponentTuplizer() - .getGetter( componentType.getPropertyIndex( attributeName ) ); - - return MapAccessor.MapGetter.class.isInstance( getter ) - ? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() ) - : getter.getMember(); - } - }; - - /** - * A {@link Member} resolver for normal attributes. - */ - private final MemberResolver normalMemberResolver = new MemberResolver() { - @Override - public Member resolveMember(AttributeContext attributeContext) { - final AbstractManagedType ownerType = attributeContext.getOwnerType(); - final Property property = attributeContext.getPropertyMapping(); - final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); - if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) { - return embeddedMemberResolver.resolveMember( attributeContext ); - } - else if ( Type.PersistenceType.ENTITY == persistenceType - || Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) { - final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) ownerType; - final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); - final String propertyName = property.getName(); - final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName ); - if ( index == null ) { - // just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping - return virtualIdentifierMemberResolver.resolveMember( attributeContext ); - } - else { - final Getter getter = entityMetamodel.getTuplizer().getGetter( index ); - return MapAccessor.MapGetter.class.isInstance( getter ) - ? new MapMember( propertyName, property.getType().getReturnedClass() ) - : getter.getMember(); - } - } - else { - throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType ); - } - } - }; - - private final MemberResolver identifierMemberResolver = new MemberResolver() { - @Override - public Member resolveMember(AttributeContext attributeContext) { - final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); - final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); - if ( !attributeContext.getPropertyMapping().getName() - .equals( entityMetamodel.getIdentifierProperty().getName() ) ) { - // this *should* indicate processing part of an IdClass... - return virtualIdentifierMemberResolver.resolveMember( attributeContext ); - } - final Getter getter = entityMetamodel.getTuplizer().getIdentifierGetter(); - return MapAccessor.MapGetter.class.isInstance( getter ) - ? new MapMember( - entityMetamodel.getIdentifierProperty().getName(), - entityMetamodel.getIdentifierProperty().getType().getReturnedClass() - ) - : getter.getMember(); - } - }; - - private final MemberResolver versionMemberResolver = new MemberResolver() { - @Override - public Member resolveMember(AttributeContext attributeContext) { - final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); - final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); - final String versionPropertyName = attributeContext.getPropertyMapping().getName(); - if ( !versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) { - // this should never happen, but to be safe... - throw new IllegalArgumentException( "Given property did not match declared version property" ); - } - - final Getter getter = entityMetamodel.getTuplizer().getVersionGetter(); - return MapAccessor.MapGetter.class.isInstance( getter ) - ? new MapMember( - versionPropertyName, - attributeContext.getPropertyMapping().getType().getReturnedClass() - ) - : getter.getMember(); - } - }; -} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EmbeddableTypeImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EmbeddableTypeImpl.java index 662ae99a687f..ee6b8fdc5a63 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EmbeddableTypeImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EmbeddableTypeImpl.java @@ -42,6 +42,7 @@ public EmbeddableTypeImpl(Class javaType, AbstractManagedType parent, Compone this.hibernateType = hibernateType; } + @Override public PersistenceType getPersistenceType() { return PersistenceType.EMBEDDABLE; } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EntityTypeImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EntityTypeImpl.java index 4e87e934432e..29c6d23b30ca 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EntityTypeImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/EntityTypeImpl.java @@ -26,8 +26,6 @@ import java.io.Serializable; import javax.persistence.metamodel.EntityType; -import org.hibernate.mapping.PersistentClass; - /** * Defines the Hibernate implementation of the JPA {@link EntityType} contract. * @@ -37,17 +35,16 @@ public class EntityTypeImpl extends AbstractIdentifiableType implements EntityType, Serializable { private final String jpaEntityName; - @SuppressWarnings("unchecked") - public EntityTypeImpl(Class javaType, AbstractIdentifiableType superType, PersistentClass persistentClass) { - super( - javaType, - persistentClass.getEntityName(), - superType, - persistentClass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ), - persistentClass.hasIdentifierProperty(), - persistentClass.isVersioned() - ); - this.jpaEntityName = persistentClass.getJpaEntityName(); + public EntityTypeImpl( + Class javaType, + AbstractIdentifiableType superType, + String entityName, + String jpaEntityName, + boolean hasIdClass, + boolean hasIdentifierProperty, + boolean isVersioned) { + super( javaType, entityName, superType, hasIdClass, hasIdentifierProperty, isVersioned ); + this.jpaEntityName = jpaEntityName; } @Override diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MappedSuperclassTypeImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MappedSuperclassTypeImpl.java index d11fe32901d8..bbd6883bd3c4 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MappedSuperclassTypeImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MappedSuperclassTypeImpl.java @@ -25,8 +25,6 @@ import javax.persistence.metamodel.MappedSuperclassType; -import org.hibernate.mapping.MappedSuperclass; - /** * @author Emmanuel Bernard * @author Steve Ebersole @@ -34,16 +32,11 @@ public class MappedSuperclassTypeImpl extends AbstractIdentifiableType implements MappedSuperclassType { public MappedSuperclassTypeImpl( Class javaType, - MappedSuperclass mappedSuperclass, - AbstractIdentifiableType superType) { - super( - javaType, - javaType.getName(), - superType, - mappedSuperclass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ), - mappedSuperclass.hasIdentifierProperty(), - mappedSuperclass.isVersioned() - ); + AbstractIdentifiableType superType, + boolean hasIdClass, + boolean hasIdentifierProperty, + boolean versioned) { + super( javaType, javaType.getName(), superType, hasIdClass, hasIdentifierProperty, versioned ); } @Override diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetadataContext.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetadataContext.java deleted file mode 100755 index f2a87370e102..000000000000 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetadataContext.java +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2013, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.jpa.internal.metamodel; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.IdentifiableType; -import javax.persistence.metamodel.MappedSuperclassType; -import javax.persistence.metamodel.SingularAttribute; - -import org.hibernate.annotations.common.AssertionFailure; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.jpa.internal.EntityManagerMessageLogger; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.KeyValue; -import org.hibernate.mapping.MappedSuperclass; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; - -import org.jboss.logging.Logger; - -/** - * Defines a context for storing information during the building of the {@link MetamodelImpl}. - *

        - * This contextual information includes data needing to be processed in a second pass as well as - * cross-references into the built metamodel classes. - *

        - * At the end of the day, clients are interested in the {@link #getEntityTypeMap} and {@link #getEmbeddableTypeMap} - * results, which represent all the registered {@linkplain #registerEntityType entities} and - * {@linkplain #registerEmbeddedableType embeddables} respectively. - * - * @author Steve Ebersole - * @author Emmanuel Bernard - */ -class MetadataContext { - - private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class, - MetadataContext.class.getName()); - - private final SessionFactoryImplementor sessionFactory; - private Set knownMappedSuperclasses; - private final boolean ignoreUnsupported; - private final AttributeFactory attributeFactory = new AttributeFactory( this ); - - private Map,EntityTypeImpl> entityTypes - = new HashMap, EntityTypeImpl>(); - private Map> entityTypesByEntityName - = new HashMap>(); - private Map> entityTypesByPersistentClass - = new HashMap>(); - private Map, EmbeddableTypeImpl> embeddables - = new HashMap, EmbeddableTypeImpl>(); - private Map> mappedSuperclassByMappedSuperclassMapping - = new HashMap>(); - //this list contains MappedSuperclass and EntityTypes ordered by superclass first - private List orderedMappings = new ArrayList(); - /** - * Stack of PersistentClass being process. Last in the list is the highest in the stack. - * - */ - private List stackOfPersistentClassesBeingProcessed - = new ArrayList(); - private Map, PersistentClass> mappedSuperClassTypeToPersistentClass - = new HashMap, PersistentClass>(); - - public MetadataContext( - SessionFactoryImplementor sessionFactory, - Set mappedSuperclasses, - boolean ignoreUnsupported) { - this.sessionFactory = sessionFactory; - this.knownMappedSuperclasses = mappedSuperclasses; - this.ignoreUnsupported = ignoreUnsupported; - } - - /*package*/ SessionFactoryImplementor getSessionFactory() { - return sessionFactory; - } - - /*package*/ boolean isIgnoreUnsupported() { - return ignoreUnsupported; - } - - /** - * Retrieves the {@linkplain Class java type} to {@link EntityTypeImpl} map. - * - * @return The {@linkplain Class java type} to {@link EntityTypeImpl} map. - */ - public Map, EntityTypeImpl> getEntityTypeMap() { - return Collections.unmodifiableMap( entityTypes ); - } - - public Map, EmbeddableTypeImpl> getEmbeddableTypeMap() { - return Collections.unmodifiableMap( embeddables ); - } - - public Map,MappedSuperclassType> getMappedSuperclassTypeMap() { - // we need to actually build this map... - final Map,MappedSuperclassType> mappedSuperClassTypeMap = CollectionHelper.mapOfSize( - mappedSuperclassByMappedSuperclassMapping.size() - ); - - for ( MappedSuperclassTypeImpl mappedSuperclassType : mappedSuperclassByMappedSuperclassMapping.values() ) { - mappedSuperClassTypeMap.put( - mappedSuperclassType.getJavaType(), - mappedSuperclassType - ); - } - - return mappedSuperClassTypeMap; - } - - /*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl entityType) { - entityTypes.put( entityType.getBindableJavaType(), entityType ); - entityTypesByEntityName.put( persistentClass.getEntityName(), entityType ); - entityTypesByPersistentClass.put( persistentClass, entityType ); - orderedMappings.add( persistentClass ); - } - - /*package*/ void registerEmbeddedableType(EmbeddableTypeImpl embeddableType) { - embeddables.put( embeddableType.getJavaType(), embeddableType ); - } - - /*package*/ void registerMappedSuperclassType( - MappedSuperclass mappedSuperclass, - MappedSuperclassTypeImpl mappedSuperclassType) { - mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType ); - orderedMappings.add( mappedSuperclass ); - mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() ); - - knownMappedSuperclasses.remove( mappedSuperclass ); - } - - /** - * Given a Hibernate {@link PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType} - * implementation. May retur null if the given {@link PersistentClass} has not yet been processed. - * - * @param persistentClass The Hibernate (config time) metamodel instance representing an entity. - * @return Tne corresponding JPA {@link org.hibernate.type.EntityType}, or null if not yet processed. - */ - public EntityTypeImpl locateEntityType(PersistentClass persistentClass) { - return entityTypesByPersistentClass.get( persistentClass ); - } - - /** - * Given a Java {@link Class}, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May - * return null which could means that no such mapping exists at least at this time. - * - * @param javaType The java class. - * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null. - */ - public EntityTypeImpl locateEntityType(Class javaType) { - return entityTypes.get( javaType ); - } - - /** - * Given an entity-name, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May - * return null which could means that no such mapping exists at least at this time. - * - * @param entityName The entity-name. - * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null. - */ - public EntityTypeImpl locateEntityType(String entityName) { - return entityTypesByEntityName.get( entityName ); - } - - public Map> getEntityTypesByEntityName() { - return Collections.unmodifiableMap( entityTypesByEntityName ); - } - - @SuppressWarnings({ "unchecked" }) - public void wrapUp() { - LOG.trace("Wrapping up metadata context..."); - - //we need to process types from superclasses to subclasses - for (Object mapping : orderedMappings) { - if ( PersistentClass.class.isAssignableFrom( mapping.getClass() ) ) { - @SuppressWarnings( "unchecked" ) - final PersistentClass safeMapping = (PersistentClass) mapping; - LOG.trace("Starting entity [" + safeMapping.getEntityName() + "]"); - try { - final EntityTypeImpl jpa2Mapping = entityTypesByPersistentClass.get( safeMapping ); - applyIdMetadata( safeMapping, jpa2Mapping ); - applyVersionAttribute( safeMapping, jpa2Mapping ); - Iterator properties = safeMapping.getDeclaredPropertyIterator(); - while ( properties.hasNext() ) { - final Property property = properties.next(); - if ( property.getValue() == safeMapping.getIdentifierMapper() ) { - // property represents special handling for id-class mappings but we have already - // accounted for the embedded property mappings in #applyIdMetadata && - // #buildIdClassAttributes - continue; - } - if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) { - // skip the version property, it was already handled previously. - continue; - } - final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property ); - if ( attribute != null ) { - jpa2Mapping.getBuilder().addAttribute( attribute ); - } - } - jpa2Mapping.lock(); - populateStaticMetamodel( jpa2Mapping ); - } - finally { - LOG.trace("Completed entity [" + safeMapping.getEntityName() + "]"); - } - } - else if ( MappedSuperclass.class.isAssignableFrom( mapping.getClass() ) ) { - @SuppressWarnings( "unchecked" ) - final MappedSuperclass safeMapping = (MappedSuperclass) mapping; - LOG.trace("Starting mapped superclass [" + safeMapping.getMappedClass().getName() + "]"); - try { - final MappedSuperclassTypeImpl jpa2Mapping = mappedSuperclassByMappedSuperclassMapping.get( - safeMapping - ); - applyIdMetadata( safeMapping, jpa2Mapping ); - applyVersionAttribute( safeMapping, jpa2Mapping ); - Iterator properties = safeMapping.getDeclaredPropertyIterator(); - while ( properties.hasNext() ) { - final Property property = properties.next(); - if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) { - // skip the version property, it was already handled previously. - continue; - } - final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property ); - if ( attribute != null ) { - jpa2Mapping.getBuilder().addAttribute( attribute ); - } - } - jpa2Mapping.lock(); - populateStaticMetamodel( jpa2Mapping ); - } - finally { - LOG.trace("Completed mapped superclass [" + safeMapping.getMappedClass().getName() + "]"); - } - } - else { - throw new AssertionFailure( "Unexpected mapping type: " + mapping.getClass() ); - } - } - - for ( EmbeddableTypeImpl embeddable : embeddables.values() ) { - populateStaticMetamodel( embeddable ); - } - } - - - private void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) { - if ( persistentClass.hasIdentifierProperty() ) { - final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty(); - if (declaredIdentifierProperty != null) { - jpaEntityType.getBuilder().applyIdAttribute( - attributeFactory.buildIdAttribute( jpaEntityType, declaredIdentifierProperty ) - ); - } - } - else if ( persistentClass.hasIdentifierMapper() ) { - @SuppressWarnings( "unchecked") - Iterator propertyIterator = persistentClass.getIdentifierMapper().getPropertyIterator(); - Set> attributes = buildIdClassAttributes( jpaEntityType, propertyIterator ); - jpaEntityType.getBuilder().applyIdClassAttributes( attributes ); - } - else { - final KeyValue value = persistentClass.getIdentifier(); - if (value instanceof Component ) { - final Component component = ( Component ) value; - if ( component.getPropertySpan() > 1 ) { - //FIXME we are an Hibernate embedded id (ie not type) - } - else { - //FIXME take care of declared vs non declared property - jpaEntityType.getBuilder().applyIdAttribute( - attributeFactory.buildIdAttribute( - jpaEntityType, - (Property) component.getPropertyIterator().next() ) - ); - } - } - } - } - - private void applyIdMetadata(MappedSuperclass mappingType, MappedSuperclassTypeImpl jpaMappingType) { - if ( mappingType.hasIdentifierProperty() ) { - final Property declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty(); - if (declaredIdentifierProperty != null) { - jpaMappingType.getBuilder().applyIdAttribute( - attributeFactory.buildIdAttribute( jpaMappingType, declaredIdentifierProperty ) - ); - } - } - //an MappedSuperclass can have no identifier if the id is set below in the hierarchy - else if ( mappingType.getIdentifierMapper() != null ){ - @SuppressWarnings( "unchecked") - Iterator propertyIterator = mappingType.getIdentifierMapper().getPropertyIterator(); - Set> attributes = buildIdClassAttributes( jpaMappingType, propertyIterator ); - jpaMappingType.getBuilder().applyIdClassAttributes( attributes ); - } - } - - private void applyVersionAttribute(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) { - final Property declaredVersion = persistentClass.getDeclaredVersion(); - if (declaredVersion != null) { - jpaEntityType.getBuilder().applyVersionAttribute( - attributeFactory.buildVersionAttribute( jpaEntityType, declaredVersion ) - ); - } - } - - private void applyVersionAttribute(MappedSuperclass mappingType, MappedSuperclassTypeImpl jpaMappingType) { - final Property declaredVersion = mappingType.getDeclaredVersion(); - if ( declaredVersion != null ) { - jpaMappingType.getBuilder().applyVersionAttribute( - attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion ) - ); - } - } - - private Set> buildIdClassAttributes( - AbstractIdentifiableType ownerType, - Iterator propertyIterator) { - LOG.trace("Building old-school composite identifier [" + ownerType.getJavaType().getName() + "]"); - Set> attributes = new HashSet>(); - while ( propertyIterator.hasNext() ) { - attributes.add( attributeFactory.buildIdAttribute( ownerType, propertyIterator.next() ) ); - } - return attributes; - } - - private void populateStaticMetamodel(AbstractManagedType managedType) { - final Class managedTypeClass = managedType.getJavaType(); - if ( managedTypeClass == null ) { - // should indicate MAP entity mode, skip... - return; - } - final String metamodelClassName = managedTypeClass.getName() + "_"; - try { - final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); - // we found the class; so populate it... - registerAttributes( metamodelClass, managedType ); - } - catch ( ClassNotFoundException ignore ) { - // nothing to do... - } - - // todo : this does not account for @MappeSuperclass, mainly because this is not being tracked in our - // internal metamodel as populated from the annotatios properly - AbstractManagedType superType = managedType.getSupertype(); - if ( superType != null ) { - populateStaticMetamodel( superType ); - } - } - - private final Set processedMetamodelClasses = new HashSet(); - - private void registerAttributes(Class metamodelClass, AbstractManagedType managedType) { - if ( ! processedMetamodelClasses.add( metamodelClass ) ) { - return; - } - - // push the attributes on to the metamodel class... - for ( Attribute attribute : managedType.getDeclaredAttributes() ) { - registerAttribute( metamodelClass, attribute ); - } - - if ( IdentifiableType.class.isInstance( managedType ) ) { - final AbstractIdentifiableType entityType = ( AbstractIdentifiableType ) managedType; - - // handle version - if ( entityType.hasDeclaredVersionAttribute() ) { - registerAttribute( metamodelClass, entityType.getDeclaredVersion() ); - } - - // handle id-class mappings specially - if ( entityType.hasIdClass() ) { - final Set> attributes = entityType.getIdClassAttributesSafely(); - if ( attributes != null ) { - for ( SingularAttribute attribute : attributes ) { - registerAttribute( metamodelClass, attribute ); - } - } - } - } - } - - private void registerAttribute(Class metamodelClass, Attribute attribute) { - final String name = attribute.getName(); - try { - // there is a shortcoming in the existing Hibernate code in terms of the way MappedSuperclass - // support was bolted on which comes to bear right here when the attribute is an embeddable type - // defined on a MappedSuperclass. We do not have the correct information to determine the - // appropriate attribute declarer in such cases and so the incoming metamodelClass most likely - // does not represent the declarer in such cases. - // - // As a result, in the case of embeddable classes we simply use getField rather than get - // getDeclaredField - final Field field = attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED - ? metamodelClass.getField( name ) - : metamodelClass.getDeclaredField( name ); - try { - if ( ! field.isAccessible() ) { - // should be public anyway, but to be sure... - field.setAccessible( true ); - } - field.set( null, attribute ); - } - catch ( IllegalAccessException e ) { - // todo : exception type? - throw new AssertionFailure( - "Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name, - e - ); - } - catch ( IllegalArgumentException e ) { - // most likely a mismatch in the type we are injecting and the defined field; this represents a - // mismatch in how the annotation processor interpretted the attribute and how our metamodel - // and/or annotation binder did. - -// This is particularly the case as arrays are nto handled propery by the StaticMetamodel generator - -// throw new AssertionFailure( -// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name -// + "; expected type : " + attribute.getClass().getName() -// + "; encountered type : " + field.getType().getName() -// ); - LOG.illegalArgumentOnStaticMetamodelFieldInjection(metamodelClass.getName(), - name, - attribute.getClass().getName(), - field.getType().getName()); - } - } - catch ( NoSuchFieldException e ) { - LOG.unableToLocateStaticMetamodelField(metamodelClass.getName(), name); -// throw new AssertionFailure( -// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name -// ); - } - } - - public MappedSuperclassTypeImpl locateMappedSuperclassType(MappedSuperclass mappedSuperclass) { - return mappedSuperclassByMappedSuperclassMapping.get(mappedSuperclass); - } - - public void pushEntityWorkedOn(PersistentClass persistentClass) { - stackOfPersistentClassesBeingProcessed.add(persistentClass); - } - - public void popEntityWorkedOn(PersistentClass persistentClass) { - final PersistentClass stackTop = stackOfPersistentClassesBeingProcessed.remove( - stackOfPersistentClassesBeingProcessed.size() - 1 - ); - if (stackTop != persistentClass) { - throw new AssertionFailure( "Inconsistent popping: " - + persistentClass.getEntityName() + " instead of " + stackTop.getEntityName() ); - } - } - - private PersistentClass getEntityWorkedOn() { - return stackOfPersistentClassesBeingProcessed.get( - stackOfPersistentClassesBeingProcessed.size() - 1 - ); - } - - public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl mappedSuperclassType) { - final PersistentClass persistentClass = mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType ); - if (persistentClass == null) { - throw new AssertionFailure( "Could not find PersistentClass for MappedSuperclassType: " - + mappedSuperclassType.getJavaType() ); - } - return persistentClass; - } - - public Set getUnusedMappedSuperclasses() { - return new HashSet( knownMappedSuperclasses ); - } -} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImpl.java index f5bc46a1fec0..8dced6ceb090 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImpl.java @@ -22,9 +22,7 @@ package org.hibernate.jpa.internal.metamodel; import java.io.Serializable; -import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.persistence.metamodel.EmbeddableType; @@ -33,12 +31,9 @@ import javax.persistence.metamodel.MappedSuperclassType; import javax.persistence.metamodel.Metamodel; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.jpa.internal.EntityManagerMessageLogger; import org.hibernate.jpa.internal.HEMLogging; -import org.hibernate.mapping.MappedSuperclass; -import org.hibernate.mapping.PersistentClass; /** * Hibernate implementation of the JPA {@link Metamodel} contract. @@ -46,137 +41,14 @@ * @author Steve Ebersole * @author Emmanuel Bernard */ -public class MetamodelImpl implements Metamodel, Serializable { +public class MetamodelImpl implements MetamodelImplementor, Serializable { private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( MetamodelImpl.class ); private final Map,EntityTypeImpl> entities; + private final Map, MappedSuperclassTypeImpl> mappedSuperclassTypeMap; private final Map, EmbeddableTypeImpl> embeddables; - private final Map, MappedSuperclassType> mappedSuperclassTypeMap; private final Map> entityTypesByEntityName; - /** - * Build the metamodel using the information from the collection of Hibernate - * {@link PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}. - * - * @param persistentClasses Iterator over the Hibernate (config-time) metamodel - * @param sessionFactory The Hibernate session factory. - * @return The built metamodel - * - * @deprecated use {@link #buildMetamodel(Iterator,Set,SessionFactoryImplementor,boolean)} instead - */ - @Deprecated - public static MetamodelImpl buildMetamodel( - Iterator persistentClasses, - SessionFactoryImplementor sessionFactory) { - return buildMetamodel( persistentClasses, Collections.emptySet(), sessionFactory, false ); - } - - /** - * Build the metamodel using the information from the collection of Hibernate - * {@link PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}. - * - * @param persistentClasses Iterator over the Hibernate (config-time) metamodel - * @param mappedSuperclasses All known MappedSuperclasses - * @param sessionFactory The Hibernate session factory. - * @param ignoreUnsupported ignore unsupported/unknown annotations (like @Any) - * - * @return The built metamodel - */ - public static MetamodelImpl buildMetamodel( - Iterator persistentClasses, - Set mappedSuperclasses, - SessionFactoryImplementor sessionFactory, - boolean ignoreUnsupported) { - MetadataContext context = new MetadataContext( sessionFactory, mappedSuperclasses, ignoreUnsupported ); - while ( persistentClasses.hasNext() ) { - PersistentClass pc = persistentClasses.next(); - locateOrBuildEntityType( pc, context ); - } - handleUnusedMappedSuperclasses( context ); - context.wrapUp(); - return new MetamodelImpl( context.getEntityTypeMap(), context.getEmbeddableTypeMap(), context.getMappedSuperclassTypeMap(), context.getEntityTypesByEntityName() ); - } - - private static void handleUnusedMappedSuperclasses(MetadataContext context) { - final Set unusedMappedSuperclasses = context.getUnusedMappedSuperclasses(); - if ( !unusedMappedSuperclasses.isEmpty() ) { - for ( MappedSuperclass mappedSuperclass : unusedMappedSuperclasses ) { - log.unusedMappedSuperclass( mappedSuperclass.getMappedClass().getName() ); - locateOrBuildMappedsuperclassType( mappedSuperclass, context ); - } - } - } - - private static EntityTypeImpl locateOrBuildEntityType(PersistentClass persistentClass, MetadataContext context) { - EntityTypeImpl entityType = context.locateEntityType( persistentClass ); - if ( entityType == null ) { - entityType = buildEntityType( persistentClass, context ); - } - return entityType; - } - - //TODO remove / reduce @SW scope - @SuppressWarnings( "unchecked" ) - private static EntityTypeImpl buildEntityType(PersistentClass persistentClass, MetadataContext context) { - final Class javaType = persistentClass.getMappedClass(); - context.pushEntityWorkedOn(persistentClass); - final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass(); - AbstractIdentifiableType superType = superMappedSuperclass == null - ? null - : locateOrBuildMappedsuperclassType( superMappedSuperclass, context ); - //no mappedSuperclass, check for a super entity - if (superType == null) { - final PersistentClass superPersistentClass = persistentClass.getSuperclass(); - superType = superPersistentClass == null - ? null - : locateOrBuildEntityType( superPersistentClass, context ); - } - EntityTypeImpl entityType = new EntityTypeImpl( - javaType, - superType, - persistentClass - ); - - context.registerEntityType( persistentClass, entityType ); - context.popEntityWorkedOn(persistentClass); - return entityType; - } - - private static MappedSuperclassTypeImpl locateOrBuildMappedsuperclassType( - MappedSuperclass mappedSuperclass, MetadataContext context) { - MappedSuperclassTypeImpl mappedSuperclassType = context.locateMappedSuperclassType( mappedSuperclass ); - if ( mappedSuperclassType == null ) { - mappedSuperclassType = buildMappedSuperclassType(mappedSuperclass, context); - } - return mappedSuperclassType; - } - - //TODO remove / reduce @SW scope - @SuppressWarnings( "unchecked" ) - private static MappedSuperclassTypeImpl buildMappedSuperclassType( - MappedSuperclass mappedSuperclass, - MetadataContext context) { - final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); - AbstractIdentifiableType superType = superMappedSuperclass == null - ? null - : locateOrBuildMappedsuperclassType( superMappedSuperclass, context ); - //no mappedSuperclass, check for a super entity - if (superType == null) { - final PersistentClass superPersistentClass = mappedSuperclass.getSuperPersistentClass(); - superType = superPersistentClass == null - ? null - : locateOrBuildEntityType( superPersistentClass, context ); - } - final Class javaType = mappedSuperclass.getMappedClass(); - MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl( - javaType, - mappedSuperclass, - superType - ); - context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType ); - return mappedSuperclassType; - } - /** * Instantiate the metamodel. * @@ -184,14 +56,14 @@ private static MappedSuperclassTypeImpl buildMappedSuperclassType( * @param embeddables The embeddable (component) mappings. * @param mappedSuperclassTypeMap The {@link javax.persistence.MappedSuperclass} mappings */ - private MetamodelImpl( + public MetamodelImpl( Map, EntityTypeImpl> entities, + Map, MappedSuperclassTypeImpl> mappedSuperclassTypeMap, Map, EmbeddableTypeImpl> embeddables, - Map, MappedSuperclassType> mappedSuperclassTypeMap, Map> entityTypesByEntityName) { this.entities = entities; - this.embeddables = embeddables; this.mappedSuperclassTypeMap = mappedSuperclassTypeMap; + this.embeddables = embeddables; this.entityTypesByEntityName = entityTypesByEntityName; } @@ -253,6 +125,7 @@ public Set> getEmbeddables() { return new HashSet>( embeddables.values() ); } + @Override public EntityTypeImpl getEntityTypeByName(String entityName) { return entityTypesByEntityName.get( entityName ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImplementor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImplementor.java new file mode 100644 index 000000000000..957b3813eb8b --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetamodelImplementor.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel; + +/** + * @author Steve Ebersole + */ +public interface MetamodelImplementor extends javax.persistence.metamodel.Metamodel { + public EntityTypeImpl getEntityTypeByName(String entityName); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/PluralAttributeImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/PluralAttributeImpl.java index 7c9fb05f8f74..fcc31400e89a 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/PluralAttributeImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/PluralAttributeImpl.java @@ -34,7 +34,7 @@ import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.Type; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; /** * @author Emmanuel Bernard @@ -46,112 +46,96 @@ public abstract class PluralAttributeImpl private final Type elementType; - private PluralAttributeImpl(Builder builder) { + @SuppressWarnings("unchecked") + private PluralAttributeImpl(Builder builder) { super( - builder.property.getName(), + builder.attributeBinding.getAttribute().getName(), builder.collectionClass, - builder.type, + builder.owner, builder.member, builder.persistentAttributeType ); - this.elementType = builder.attributeType; + this.elementType = builder.elementType; } - public static class Builder { - private final Type attributeType; - private final AbstractManagedType type; + public static class Builder { + private final Class collectionClass; + private AbstractManagedType owner; + private PluralAttributeBinding attributeBinding; private Member member; + private Type keyType; + private Type elementType; private PersistentAttributeType persistentAttributeType; - private Property property; - private Class collectionClass; - private Type keyType; - - private Builder(AbstractManagedType ownerType, Type attrType, Class collectionClass, Type keyType) { - this.type = ownerType; - this.attributeType = attrType; + public Builder(Class collectionClass) { this.collectionClass = collectionClass; - this.keyType = keyType; } - public Builder member(Member member) { + public Builder owner(AbstractManagedType owner) { + this.owner = owner; + return this; + } + + public Builder member(Member member) { this.member = member; return this; } - public Builder property(Property property) { - this.property = property; + public Builder binding(PluralAttributeBinding attributeBinding) { + this.attributeBinding = attributeBinding; + return this; + } + + public Builder elementType(Type elementType) { + this.elementType = elementType; + return this; + } + + public Builder keyType(Type keyType) { + this.keyType = keyType; return this; } - public Builder persistentAttributeType(PersistentAttributeType attrType) { + public Builder persistentAttributeType(PersistentAttributeType attrType) { this.persistentAttributeType = attrType; return this; } @SuppressWarnings( "unchecked" ) - public PluralAttributeImpl build() { + public PluralAttributeImpl build() { //apply strict spec rules first if ( Map.class.equals( collectionClass ) ) { - final Builder,E,K> builder = (Builder,E,K>) this; - return ( PluralAttributeImpl ) new MapAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new MapAttributeImpl( this ); } else if ( Set.class.equals( collectionClass ) ) { - final Builder, E,?> builder = (Builder, E,?>) this; - return ( PluralAttributeImpl ) new SetAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new SetAttributeImpl( this ); } else if ( List.class.equals( collectionClass ) ) { - final Builder, E,?> builder = (Builder, E,?>) this; - return ( PluralAttributeImpl ) new ListAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new ListAttributeImpl( this ); } else if ( Collection.class.equals( collectionClass ) ) { - final Builder,E,?> builder = (Builder, E,?>) this; - return ( PluralAttributeImpl ) new CollectionAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new CollectionAttributeImpl( this ); } //apply loose rules if ( Map.class.isAssignableFrom( collectionClass ) ) { - final Builder,E,K> builder = (Builder,E,K>) this; - return ( PluralAttributeImpl ) new MapAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new MapAttributeImpl( this ); } else if ( Set.class.isAssignableFrom( collectionClass ) ) { - final Builder, E,?> builder = (Builder, E,?>) this; - return ( PluralAttributeImpl ) new SetAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new SetAttributeImpl( this ); } else if ( List.class.isAssignableFrom( collectionClass ) ) { - final Builder, E,?> builder = (Builder, E,?>) this; - return ( PluralAttributeImpl ) new ListAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new ListAttributeImpl( this ); } else if ( Collection.class.isAssignableFrom( collectionClass ) ) { - final Builder,E,?> builder = (Builder, E,?>) this; - return ( PluralAttributeImpl ) new CollectionAttributeImpl( - builder - ); + return ( PluralAttributeImpl ) new CollectionAttributeImpl( this ); } - throw new UnsupportedOperationException( "Unkown collection: " + collectionClass ); + throw new UnsupportedOperationException( "Unknown collection: " + collectionClass ); } } - public static Builder create( - AbstractManagedType ownerType, - Type attrType, - Class collectionClass, - Type keyType) { - return new Builder(ownerType, attrType, collectionClass, keyType); + public static Builder builder(Class collectionClass) { + return new Builder( collectionClass ); } @Override @@ -180,7 +164,7 @@ public Class getBindableJavaType() { } static class SetAttributeImpl extends PluralAttributeImpl,E> implements SetAttribute { - SetAttributeImpl(Builder,E,?> xceBuilder) { + SetAttributeImpl(Builder xceBuilder) { super( xceBuilder ); } @@ -191,7 +175,7 @@ public CollectionType getCollectionType() { } static class CollectionAttributeImpl extends PluralAttributeImpl,E> implements CollectionAttribute { - CollectionAttributeImpl(Builder,E,?> xceBuilder) { + CollectionAttributeImpl(Builder xceBuilder) { super( xceBuilder ); } @@ -202,7 +186,7 @@ public CollectionType getCollectionType() { } static class ListAttributeImpl extends PluralAttributeImpl,E> implements ListAttribute { - ListAttributeImpl(Builder,E,?> xceBuilder) { + ListAttributeImpl(Builder xceBuilder) { super( xceBuilder ); } @@ -215,7 +199,8 @@ public CollectionType getCollectionType() { static class MapAttributeImpl extends PluralAttributeImpl,V> implements MapAttribute { private final Type keyType; - MapAttributeImpl(Builder,V,K> xceBuilder) { + @SuppressWarnings("unchecked") + MapAttributeImpl(Builder xceBuilder) { super( xceBuilder ); this.keyType = xceBuilder.keyType; } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeBuilder.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeBuilder.java new file mode 100644 index 000000000000..ecaa86e8e1ed --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeBuilder.java @@ -0,0 +1,700 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import javax.persistence.OneToOne; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Attribute.PersistentAttributeType; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Type; + +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.internal.metamodel.AbstractIdentifiableType; +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.jpa.internal.metamodel.BasicTypeImpl; +import org.hibernate.jpa.internal.metamodel.EmbeddableTypeImpl; +import org.hibernate.jpa.internal.metamodel.MappedSuperclassTypeImpl; +import org.hibernate.jpa.internal.metamodel.PluralAttributeImpl; +import org.hibernate.jpa.internal.metamodel.SingularAttributeImpl; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeIndexNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.MapBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingEmbedded; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.tuple.entity.EntityMetamodel; +import org.hibernate.type.ComponentType; +import org.hibernate.type.EmbeddedComponentType; + +import org.jboss.logging.Logger; + +/** + * A factory for building {@link javax.persistence.metamodel.Attribute} instances. Exposes 3 main services:
          + *
        1. {@link #buildAttribute} for building normal attributes
        2. + *
        3. {@link #buildIdAttribute} for building identifier attributes
        4. + *
        5. {@link #buildVersionAttribute} for building version attributes}
        6. + *
            + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class AttributeBuilder { + private static final Logger LOG = Logger.getLogger( AttributeBuilder.class.getName() ); + + /** + * The context for attribute building + */ + public static interface Context { + public Type locateEntityTypeByName(String entityName); + + public void registerEmbeddedableType(EmbeddableTypeImpl embeddableType); + + public SessionFactoryImplementor getSessionFactory(); + + public EntityPersister getSubClassEntityPersister(MappedSuperclassTypeImpl mappedSuperclass); + + public void handleUnsupportedFeature(UnsupportedFeature feature); + } + + private final Context context; + + public AttributeBuilder(Context context) { + this.context = context; + } + + /** + * Build a normal attribute. + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param attributeBinding The Hibernate attribute binding descriptor + * @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs) + */ + public Attribute buildAttribute(AbstractManagedType ownerType, AttributeBinding attributeBinding) { + if ( attributeBinding.getAttribute().isSynthetic() ) { + // hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel. + LOG.tracef( + "Skipping synthetic property %s(%s)", + ownerType.getJavaType().getName(), + attributeBinding.getAttribute().getName() + ); + return null; + } + LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + attributeBinding.getAttribute().getName() + "]"); + final AttributeMetadata attributeMetadata = determineAttributeMetadata( + ownerType, + attributeBinding, + NORMAL_MEMBER_RESOLVER + ); + if ( attributeMetadata == null ) { + return null; + } + if ( attributeMetadata.isPlural() ) { + return buildPluralAttribute( (PluralAttributeMetadata) attributeMetadata ); + } + final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata)attributeMetadata; + final Type metaModelType = getSingularAttributeMetaModelType( singularAttributeMetadata.getAttributeTypeDescriptor() ); + //noinspection unchecked + return new SingularAttributeImpl( + attributeMetadata.getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + false, + false, + true, // todo : need to handle this somehow : property.isOptional(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + /** + * Build the identifier attribute descriptor + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param attributeBinding The Hibernate attribute binding descriptor + * + * @return The built attribute descriptor + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildIdAttribute(AbstractIdentifiableType ownerType, AttributeBinding attributeBinding) { + LOG.trace( + "Building identifier attribute [" + ownerType.getJavaType().getName() + "#" + + attributeBinding.getAttribute().getName() + "]" + ); + final SingularAttributeMetadata attributeMetadata = (SingularAttributeMetadata) determineAttributeMetadata( + ownerType, + attributeBinding, + IDENTIFIER_MEMBER_RESOLVER + ); + final Type metaModelType = getSingularAttributeMetaModelType( attributeMetadata.getAttributeTypeDescriptor() ); + return new SingularAttributeImpl.Identifier( + attributeBinding.getAttribute().getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + /** + * Build the version attribute descriptor + * + * @param ownerType The descriptor of the attribute owner (aka declarer). + * @param attributeBinding The Hibernate attribute binding descriptor + * + * @return The built attribute descriptor + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildVersionAttribute(AbstractIdentifiableType ownerType, AttributeBinding attributeBinding) { + LOG.trace("Building version attribute [ownerType.getJavaType().getName()" + "." + "property.getName()]"); + final SingularAttributeMetadata attributeMetadata = (SingularAttributeMetadata) determineAttributeMetadata( + ownerType, + attributeBinding, + VERSION_MEMBER_RESOLVER + ); + final Type metaModelType = getSingularAttributeMetaModelType( attributeMetadata.getAttributeTypeDescriptor() ); + return new SingularAttributeImpl.Version( + attributeBinding.getAttribute().getName(), + attributeMetadata.getJavaType(), + ownerType, + attributeMetadata.getMember(), + metaModelType, + attributeMetadata.getPersistentAttributeType() + ); + } + + @SuppressWarnings( "unchecked" ) + private PluralAttribute buildPluralAttribute(PluralAttributeMetadata attributeMetadata) { + final PluralAttributeBinding pluralAttributeBinding = + (PluralAttributeBinding) attributeMetadata.getAttributeBinding(); + + final Type elementType = getPluralAttributeElementMetaModelType( + attributeMetadata.getElementAttributeTypeDescriptor() + ); + if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) { + final Type keyType = getPluralAttributeMapKeyMetaModelType( + attributeMetadata.getMapKeyAttributeTypeDescriptor() + ); + return PluralAttributeImpl.builder( attributeMetadata.getJavaType() ) + .owner( attributeMetadata.getOwnerType() ) + .elementType( elementType ) + .keyType( keyType ) + .member( attributeMetadata.getMember() ) + .binding( pluralAttributeBinding ) + .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) + .build(); + } + return PluralAttributeImpl.builder( attributeMetadata.getJavaType() ) + .owner( attributeMetadata.getOwnerType() ) + .elementType( elementType ) + .member( attributeMetadata.getMember() ) + .binding( pluralAttributeBinding ) + .persistentAttributeType( attributeMetadata.getPersistentAttributeType() ) + .build(); + } + + @SuppressWarnings( "unchecked" ) + private Type getSingularAttributeMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + AttributeBinding attributeBinding = + attributeTypeDescriptor + .getAttributeMetadata() + .getAttributeBinding(); + if ( !attributeBinding.getAttribute().isSingular() ) { + throw new IllegalArgumentException( + String.format( + "Expected singular attribute binding, but it was plural: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + switch ( attributeTypeDescriptor.getValueClassification() ) { + case BASIC: { + return getBasicAttributeMetaModelType( attributeTypeDescriptor ); + } + case ENTITY: { + return getEntityAttributeMetaModelType( attributeTypeDescriptor ); + } + case EMBEDDABLE: { + if ( ! ( attributeBinding instanceof EmbeddedAttributeBinding ) ) { + throw new IllegalArgumentException( + String.format( + "Unexpected type of attribute binding. Expected: %s; Actual: %s", + EmbeddedAttributeBinding.class.getName(), + attributeBinding.getClass().getName() + ) + ); + } + return getEmbeddableAttributeMetaModelType( + attributeTypeDescriptor, + ( (EmbeddedAttributeBinding) attributeBinding ).getEmbeddableBinding() + ); + } + default: { + throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private Type getPluralAttributeElementMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + final AttributeBinding attributeBinding = + attributeTypeDescriptor + .getAttributeMetadata() + .getAttributeBinding(); + if ( attributeBinding.getAttribute().isSingular() ) { + throw new IllegalArgumentException( + String.format( + "Expected plural attribute binding, but it was singular: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + switch ( attributeTypeDescriptor.getValueClassification() ) { + case BASIC: { + return getBasicAttributeMetaModelType( attributeTypeDescriptor ); + } + case ENTITY: { + return getEntityAttributeMetaModelType( attributeTypeDescriptor ); + } + case EMBEDDABLE: { + final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + final PluralAttributeElementBindingEmbedded pluralAttributeElementBindingEmbedded = + (PluralAttributeElementBindingEmbedded) pluralAttributeBinding.getPluralAttributeElementBinding(); + return getEmbeddableAttributeMetaModelType( + attributeTypeDescriptor, + pluralAttributeElementBindingEmbedded.getEmbeddableBinding() + ); + } + default: { + throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private Type getPluralAttributeMapKeyMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + final AttributeBinding attributeBinding = + attributeTypeDescriptor + .getAttributeMetadata() + .getAttributeBinding(); + if ( attributeBinding.getAttribute().isSingular() ) { + throw new IllegalArgumentException( + String.format( + "Expected plural attribute binding, but it was singular: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + if ( ! ( attributeBinding instanceof MapBinding ) ) { + throw new IllegalArgumentException( + String.format( + "Expected a map binding: %s", + attributeBinding.getAttribute().getName() + ) + ); + } + switch ( attributeTypeDescriptor.getValueClassification() ) { + case BASIC: { + return getBasicAttributeMetaModelType( attributeTypeDescriptor ); + } + case ENTITY: { + return getEntityAttributeMetaModelType( attributeTypeDescriptor ); + } + case EMBEDDABLE: { + final MapBinding mapBinding = (MapBinding) attributeBinding; + final CompositePluralAttributeIndexBinding pluralAttributeIndexBinding = + (CompositePluralAttributeIndexBinding) mapBinding.getPluralAttributeIndexBinding(); + return getEmbeddableAttributeMetaModelType( + attributeTypeDescriptor, + pluralAttributeIndexBinding.getCompositeAttributeBindingContainer() + ); + } + default: { + throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private Type getBasicAttributeMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + checkCorrectValueClassification( attributeTypeDescriptor, AttributeTypeDescriptor.ValueClassification.BASIC ); + return new BasicTypeImpl( + attributeTypeDescriptor.getBindableType(), + Type.PersistenceType.BASIC + ); + } + + @SuppressWarnings( "unchecked" ) + private Type getEntityAttributeMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) { + checkCorrectValueClassification( attributeTypeDescriptor, AttributeTypeDescriptor.ValueClassification.ENTITY ); + final org.hibernate.type.EntityType type = (org.hibernate.type.EntityType) attributeTypeDescriptor.getHibernateType(); + return (Type) context.locateEntityTypeByName( type.getAssociatedEntityName() ); + } + + @SuppressWarnings( "unchecked" ) + private Type getEmbeddableAttributeMetaModelType( + AttributeTypeDescriptor attributeTypeDescriptor, + EmbeddableBinding embeddableBinding) { + checkCorrectValueClassification( attributeTypeDescriptor, AttributeTypeDescriptor.ValueClassification.EMBEDDABLE ); + if ( ! embeddableBinding.isAggregated() ) { + throw new IllegalArgumentException( + "Composite attribute binding is not aggregated." + ); + } + final EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl( + attributeTypeDescriptor.getBindableType(), + attributeTypeDescriptor.getAttributeMetadata().getOwnerType(), + (ComponentType) attributeTypeDescriptor.getHibernateType() + ); + context.registerEmbeddedableType( embeddableType ); + for ( AttributeBinding subAttributeBinding : embeddableBinding.attributeBindings() ) { + final Attribute attribute = buildAttribute( embeddableType, subAttributeBinding ); + if ( attribute != null ) { + embeddableType.getBuilder().addAttribute( attribute ); + } + } + embeddableType.lock(); + return embeddableType; + } + + private void checkCorrectValueClassification( + AttributeTypeDescriptor attributeTypeDescriptor, + AttributeTypeDescriptor.ValueClassification expectedValueClassification) { + if ( attributeTypeDescriptor.getValueClassification() != expectedValueClassification ) { + throw new IllegalArgumentException( + String.format( + "Unexpected value classification for [%s]; expected:[%s] actual:[%s]", + attributeTypeDescriptor, + expectedValueClassification, + attributeTypeDescriptor.getValueClassification() + ) + ); + } + } + + private EntityMetamodel getDeclarerEntityMetamodel(AbstractIdentifiableType ownerType) { + final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); + + if ( persistenceType == Type.PersistenceType.ENTITY) { + return context.getSessionFactory() + .getEntityPersister( ownerType.getTypeName() ) + .getEntityMetamodel(); + } + else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) { + return context.getSubClassEntityPersister( (MappedSuperclassTypeImpl) ownerType ) + .getEntityMetamodel(); + } + else { + throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType ); + } + } + + /** + * Here is most of the nuts and bolts of this factory, where we interpret the known JPA metadata + * against the known Hibernate metadata and build a descriptor for the attribute. + * + * @param jpaOwner The JPA representation of the attribute owner + * @param attributeBinding Hibernate metamodel representation of the attribute binding + * @param memberResolver Strategy for how to resolve the member defining the attribute. + * + * @return The attribute description + */ + @SuppressWarnings({ "unchecked" }) + private AttributeMetadata determineAttributeMetadata( + AbstractManagedType jpaOwner, + AttributeBinding attributeBinding, + MemberResolver memberResolver) { + LOG.trace("Starting attribute metadata determination [" + attributeBinding.getAttribute().getName() + "]"); + final Member member = memberResolver.resolveMember( jpaOwner, attributeBinding ); + LOG.trace(" Determined member [" + member + "]"); + + final org.hibernate.type.Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + LOG.trace(" Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]"); + + if ( type.isAnyType() ) { + // ANY mappings are currently not supported in the JPA metamodel; see HHH-6589 + context.handleUnsupportedFeature( UnsupportedFeature.ANY ); + return null; + } + + if ( attributeBinding.getAttribute().isSingular() ) { + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + + final PersistentAttributeType jpaAttributeType; + if ( singularAttributeBinding.getAttribute().getSingularAttributeType().isAggregate() ) { + jpaAttributeType = PersistentAttributeType.EMBEDDED; + } + else if ( singularAttributeBinding.getAttribute().getSingularAttributeType().isAssociation() ) { + jpaAttributeType = determineSingularAssociationAttributeType( member ); + } + else { + jpaAttributeType = PersistentAttributeType.BASIC; + } + return new SingularAttributeMetadataImpl( attributeBinding, jpaOwner, member, jpaAttributeType ); + } + else { + final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + + if ( pluralAttributeBinding.getAttribute().getPluralAttributeNature() == PluralAttributeNature.ARRAY ) { + context.handleUnsupportedFeature( UnsupportedFeature.ARRAY ); + return null; + } + + // First, determine the type of the elements and use that to help determine the + // collection type) + final PluralAttributeElementBinding elementBinding = pluralAttributeBinding.getPluralAttributeElementBinding(); + final PluralAttributeElementNature elementNature = elementBinding.getNature(); + final PersistentAttributeType persistentAttributeType; + final PersistentAttributeType elementPersistentAttributeType; + PersistentAttributeType keyPersistentAttributeType = null; + + if ( elementNature == PluralAttributeElementNature.MANY_TO_ANY ) { + // ANY mappings are currently not supported in the JPA metamodel; see HHH-6589 + context.handleUnsupportedFeature( UnsupportedFeature.ANY ); + return null; + } + else if ( elementNature == PluralAttributeElementNature.BASIC ) { + elementPersistentAttributeType = PersistentAttributeType.BASIC; + persistentAttributeType = PersistentAttributeType.ELEMENT_COLLECTION; + } + else if ( elementNature == PluralAttributeElementNature.AGGREGATE ) { + elementPersistentAttributeType = PersistentAttributeType.EMBEDDED; + persistentAttributeType = PersistentAttributeType.ELEMENT_COLLECTION; + } + else { + elementPersistentAttributeType = elementNature == PluralAttributeElementNature.MANY_TO_MANY + ? PersistentAttributeType.MANY_TO_MANY + : PersistentAttributeType.ONE_TO_MANY; + persistentAttributeType = elementPersistentAttributeType; + } + + // For maps, also check the key binding + if ( pluralAttributeBinding.getAttribute().getPluralAttributeNature() == PluralAttributeNature.MAP ) { + final IndexedPluralAttributeBinding indexedPluralAttributeBinding + = (IndexedPluralAttributeBinding) pluralAttributeBinding; + final PluralAttributeIndexNature indexNature + = indexedPluralAttributeBinding.getPluralAttributeIndexBinding().getNature(); + + if ( indexNature == PluralAttributeIndexNature.MANY_TO_ANY ) { + context.handleUnsupportedFeature( UnsupportedFeature.ANY ); + return null; + } + else if ( indexNature == PluralAttributeIndexNature.MANY_TO_MANY ) { + keyPersistentAttributeType = PersistentAttributeType.MANY_TO_ONE; + } + else if ( indexNature == PluralAttributeIndexNature.AGGREGATE ) { + keyPersistentAttributeType = PersistentAttributeType.EMBEDDED; + } + else { + keyPersistentAttributeType = PersistentAttributeType.BASIC; + } + } + + return new PluralAttributeMetadataImpl( + pluralAttributeBinding, + jpaOwner, + member, + persistentAttributeType, + elementPersistentAttributeType, + keyPersistentAttributeType + ); + } + } + + public static PersistentAttributeType determineSingularAssociationAttributeType(Member member) { + if ( Field.class.isInstance( member ) ) { + return ( (Field) member ).getAnnotation( OneToOne.class ) != null + ? PersistentAttributeType.ONE_TO_ONE + : PersistentAttributeType.MANY_TO_ONE; + } + else { + return ( (Method) member ).getAnnotation( OneToOne.class ) != null + ? PersistentAttributeType.ONE_TO_ONE + : PersistentAttributeType.MANY_TO_ONE; + } + } + + public static ParameterizedType getSignatureType(Member member) { + final java.lang.reflect.Type type = Field.class.isInstance( member ) + ? ( ( Field ) member ).getGenericType() + : ( ( Method ) member ).getGenericReturnType(); + //this is a raw type + if ( type instanceof Class ) return null; + return (ParameterizedType) type; + } + + public static Class determineDeclaredType( Member member ) { + final Class declaredType; + // we can support method or field members here. Is there really any other valid type? + if ( Field.class.isInstance( member ) ) { + declaredType = ( (Field) member ).getType(); + } + else if ( Method.class.isInstance( member ) ) { + declaredType = ( (Method) member ).getReturnType(); + } + else { + throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" ); + } + return declaredType; + } + + public static PluralAttribute.CollectionType determineCollectionType(Class javaType) { + if ( java.util.List.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.LIST; + } + else if ( java.util.Set.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.SET; + } + else if ( java.util.Map.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.MAP; + } + else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) { + return PluralAttribute.CollectionType.COLLECTION; + } + else { + throw new IllegalArgumentException( "Expecting collection type [" + javaType.getName() + "]" ); + } + } + +// public static boolean isManyToMany(Member member) { +// return Field.class.isInstance( member ) +// ? ( (Field) member ).getAnnotation( ManyToMany.class ) != null +// : ( (Method) member ).getAnnotation( ManyToMany.class ) != null; +// } + + private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl ) owner; + final String attributeName = attributeBinding.getAttribute().getName(); + return embeddableType.getHibernateType() + .getComponentTuplizer() + .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ) + .getMember(); + } + }; + + + private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + if ( ! entityMetamodel.getIdentifierProperty().isVirtual() ) { + throw new IllegalArgumentException( "expecting a virtual (non-aggregated composite) identifier mapping" ); + } + org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType(); + if ( entityMetamodel.getIdentifierProperty().hasIdentifierMapper() ) { + if ( ! ComponentType.class.isInstance( type ) ) { + throw new IllegalArgumentException( "expecting an idclass identifier mapping" ); + } + } + else { + if ( ! EmbeddedComponentType.class.isInstance( type ) ) { + throw new IllegalArgumentException( "expecting a non-aggregated composite identifier mapping" ); + } + } + + final ComponentType componentType = (ComponentType) type; + final String attributeName = attributeBinding.getAttribute().getName(); + return componentType.getComponentTuplizer() + .getGetter( componentType.getPropertyIndex( attributeName ) ) + .getMember(); + } + }; + + /** + * A {@link java.lang.reflect.Member} resolver for normal attributes. + */ + private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final Type.PersistenceType persistenceType = owner.getPersistenceType(); + if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) { + return EMBEDDED_MEMBER_RESOLVER.resolveMember( owner, attributeBinding ); + } + else if ( Type.PersistenceType.ENTITY == persistenceType + || Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) { + final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + final String propertyName = attributeBinding.getAttribute().getName(); + final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName ); + if ( index == null ) { + // just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping + return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( owner, attributeBinding ); + } + else { + return entityMetamodel.getTuplizer() + .getGetter( index ) + .getMember(); + } + } + else { + throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType ); + } + } + }; + + private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + final String attributeName = attributeBinding.getAttribute().getName(); + if ( ! attributeName.equals( entityMetamodel.getIdentifierProperty().getName() ) ) { + // this *should* indicate processing part of an IdClass... + return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( owner, attributeBinding ); + } + return entityMetamodel.getTuplizer().getIdentifierGetter().getMember(); + } + }; + + private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() { + @Override + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) { + final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) owner; + final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); + final String versionPropertyName = attributeBinding.getAttribute().getName(); + if ( ! versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) { + // this should never happen, but to be safe... + throw new IllegalArgumentException( "Given property did not match declared version property" ); + } + return entityMetamodel.getTuplizer().getVersionGetter().getMember(); + } + }; +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeMetadata.java new file mode 100644 index 000000000000..cb9fb29675dd --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeMetadata.java @@ -0,0 +1,93 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Member; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * Basic contract for describing an attribute in a format needed while building the JPA metamodel. + * + * The "description" is described:
              + *
            1. partially in terms of JPA ({@link #getPersistentAttributeType} and {@link #getOwnerType})
            2. + *
            3. partially in terms of Hibernate metamodel ({@link #getAttributeBinding})
            4. + *
            5. and partially just in terms of the java model itself ({@link #getMember} and {@link #getJavaType})
            6. + *
            + * + * @param The attribute owner type + * @param The attribute type. + */ +public interface AttributeMetadata { + /** + * Retrieve the name of the attribute + * + * @return The attribute name + */ + public String getName(); + + /** + * Retrieve the member defining the attribute + * + * @return The attribute member + */ + public Member getMember(); + + /** + * Retrieve the attribute java type. + * + * @return The java type of the attribute. + */ + public Class getJavaType(); + + /** + * Get the JPA attribute type classification for this attribute. + * + * @return The JPA attribute type classification + */ + public Attribute.PersistentAttributeType getPersistentAttributeType(); + + /** + * Retrieve the attribute owner's metamodel information + * + * @return The metamodel information for the attribute owner + */ + public AbstractManagedType getOwnerType(); + + /** + * Retrieve the Hibernate property mapping related to this attribute. + * + * @return The Hibernate property mapping + */ + public AttributeBinding getAttributeBinding(); + + /** + * Is the attribute plural (a collection)? + * + * @return True if it is plural, false otherwise. + */ + public boolean isPlural(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeTypeDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeTypeDescriptor.java new file mode 100644 index 000000000000..8b637d104acd --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/AttributeTypeDescriptor.java @@ -0,0 +1,60 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +/** + * Centralized access to a variety of information about a the type of an attribute being built for the JPA metamodel. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public interface AttributeTypeDescriptor { + /** + * Enum of the simplified types a value might be. These relate more to the Hibernate classification + * then the JPA classification + */ + enum ValueClassification { + EMBEDDABLE, + ENTITY, + BASIC + } + + public org.hibernate.type.Type getHibernateType(); + + public Class getBindableType(); + + /** + * Retrieve the simplified value classification + * + * @return The value type + */ + public ValueClassification getValueClassification(); + + /** + * Retrieve the metadata about the attribute from which this value comes + * + * @return The "containing" attribute metadata. + */ + public AttributeMetadata getAttributeMetadata(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/BaseAttributeMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/BaseAttributeMetadata.java new file mode 100644 index 000000000000..1d8bcf8c2177 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/BaseAttributeMetadata.java @@ -0,0 +1,100 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Member; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * Base implementation of AttributeMetadata + * + * @author Steve Ebersole + */ +public abstract class BaseAttributeMetadata implements AttributeMetadata { + private final AttributeBinding attributeBinding; + private final AbstractManagedType ownerType; + private final Member member; + private final Class javaType; + private final Attribute.PersistentAttributeType persistentAttributeType; + + @SuppressWarnings({ "unchecked" }) + public BaseAttributeMetadata( + AttributeBinding attributeBinding, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType) { + this.attributeBinding = attributeBinding; + this.ownerType = ownerType; + this.member = member; + this.persistentAttributeType = persistentAttributeType; + + this.javaType = (Class) AttributeBuilder.determineDeclaredType( member ); + } + + @Override + public String getName() { + return attributeBinding.getAttribute().getName(); + } + + @Override + public Member getMember() { + return member; + } + + public String getMemberDescription() { + return determineMemberDescription( getMember() ); + } + + public String determineMemberDescription(Member member) { + return member.getDeclaringClass().getName() + '#' + member.getName(); + } + + @Override + public Class getJavaType() { + return javaType; + } + + @Override + public Attribute.PersistentAttributeType getPersistentAttributeType() { + return persistentAttributeType; + } + + @Override + public AbstractManagedType getOwnerType() { + return ownerType; + } + + @Override + public boolean isPlural() { + return ! attributeBinding.getAttribute().isSingular(); + } + + @Override + public AttributeBinding getAttributeBinding() { + return attributeBinding; + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/JpaMetaModelPopulationSetting.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/JpaMetaModelPopulationSetting.java new file mode 100644 index 000000000000..3bcda959b918 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/JpaMetaModelPopulationSetting.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +/** +* @author Steve Ebersole +*/ +public enum JpaMetaModelPopulationSetting { + ENABLED, + DISABLED, + IGNORE_UNSUPPORTED; + + public static JpaMetaModelPopulationSetting parse(String setting) { + if ( "enabled".equalsIgnoreCase( setting ) ) { + return ENABLED; + } + else if ( "disabled".equalsIgnoreCase( setting ) ) { + return DISABLED; + } + else { + return IGNORE_UNSUPPORTED; + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/MemberResolver.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/MemberResolver.java new file mode 100644 index 000000000000..c543d7a793f2 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/MemberResolver.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Member; + +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** + * Contract for how we resolve the {@link java.lang.reflect.Member} for a given attribute context. + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public interface MemberResolver { + /** + * Resolve the member. + * + * @param owner The JPA Metamodel representation of the class tha owns the member to be resolved + * @param attributeBinding Hibernate metamodel representation of the attribute for which to resolve the member. + * + * @return The resolved member. + */ + public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/MetamodelBuilder.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/MetamodelBuilder.java new file mode 100644 index 000000000000..181811455efe --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/MetamodelBuilder.java @@ -0,0 +1,577 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; + +import org.hibernate.EntityMode; +import org.hibernate.HibernateException; +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.internal.metamodel.AbstractIdentifiableType; +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.jpa.internal.metamodel.EmbeddableTypeImpl; +import org.hibernate.jpa.internal.metamodel.EntityTypeImpl; +import org.hibernate.jpa.internal.metamodel.MappedSuperclassTypeImpl; +import org.hibernate.jpa.internal.metamodel.MetamodelImpl; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HierarchyDetails; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.domain.Entity; +import org.hibernate.metamodel.spi.domain.Hierarchical; +import org.hibernate.metamodel.spi.domain.MappedSuperclass; +import org.hibernate.persister.entity.EntityPersister; + +import org.jboss.logging.Logger; + +/** + * Defines the contract for building JPA Metamodel + *

            + * Contract is made up of:

              + *
            1. Instantiating this builder
            2. + *
            3. adding all managed mapping classes to it ({@link #add})
            4. + *
            5. calling {@link #buildMetamodel}
            6. + *
            + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public class MetamodelBuilder { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + MetamodelBuilder.class.getName() + ); + private final SessionFactoryImplementor sessionFactory; + private final ClassLoaderService classLoaderService; + + + // these maps eventually make up the JPA Metamodel + private final Map,EntityTypeImpl> entityTypeMap = new HashMap, EntityTypeImpl>(); + private final Map, EmbeddableTypeImpl> embeddableTypeMap = new HashMap, EmbeddableTypeImpl>(); + private final Map, MappedSuperclassTypeImpl> mappedSuperclassTypeMap = new HashMap, MappedSuperclassTypeImpl>(); + + // these fields are needed just for the duration of building the metamodel + private final JpaMetaModelPopulationSetting populationSetting; + private final AttributeBuilder attributeBuilder; + private final Map> entityTypeByNameMap = new HashMap>(); + private final Map mappedSuperclassEntityNameMap = new HashMap(); + private List entityBindingList = new ArrayList(); + private Set alreadyProcessed = new HashSet(); + + public static MetamodelImpl oneShot( + SessionFactoryImplementor sessionFactory, + Metadata metadata, + JpaMetaModelPopulationSetting populationSetting) { + MetamodelBuilder builder = new MetamodelBuilder( sessionFactory, populationSetting ); + for ( EntityBinding eb : metadata.getEntityBindings() ) { + builder.add( eb ); + } + return builder.buildMetamodel(); + } + + public MetamodelBuilder(SessionFactoryImplementor sessionFactory, JpaMetaModelPopulationSetting populationSetting) { + this.sessionFactory = sessionFactory; + this.classLoaderService = sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ); + this.populationSetting = populationSetting; + this.attributeBuilder = new AttributeBuilder( new AttributeBuilderContext() ); + } + + public void add(EntityBinding entityBinding) { + if ( entityBinding.getHierarchyDetails().getEntityMode() == EntityMode.POJO ) { + locateOrBuildEntityType( entityBinding ); + } + entityBindingList.add( entityBinding ); + } + + private EntityTypeImpl locateOrBuildEntityType(EntityBinding binding) { + EntityTypeImpl entityType = entityTypeByNameMap.get( binding.getEntityName() ); + if ( entityType == null ) { + entityType = buildEntityType( binding ); + } + return entityType; + } + + @SuppressWarnings("unchecked") + private EntityTypeImpl buildEntityType(EntityBinding entityBinding) { + final ClassLoaderService cls = sessionFactory.getServiceRegistry().getService( ClassLoaderService.class ); + final Class javaType = cls.classForName( entityBinding.getEntity().getDescriptor().getName().toString() ); + final AbstractIdentifiableType superType = locateOrBuildSuperType( entityBinding.getEntity().getSuperType(), entityBinding ); + + EntityTypeImpl entityType = new EntityTypeImpl( + javaType, + superType, + entityBinding.getEntityName(), + entityBinding.getJpaEntityName(), + entityBinding.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().definedIdClass(), + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() != null, + entityBinding.getHierarchyDetails().isVersioned() + ); + + entityTypeMap.put( javaType, entityType ); + entityTypeByNameMap.put( entityBinding.getEntityName(), entityType ); + return entityType; + } + + /** + * IMPORTANT!!! This method is called in 2 somewhat different cases:
              + *
            1. resolving super class for @Entity
            2. + *
            3. resolving super class for @MappedSuperclass
            4. + *
            + * Make sure changes fit both uses + * + * @param hierarchical Hibernate metamodel descriptor of the super class + * @param entityBinding The Hibernate metamodel entity binding; could be describing different class between the + * 2 use cases described above. + * + * @return The super type. + */ + private AbstractIdentifiableType locateOrBuildSuperType(Hierarchical hierarchical, EntityBinding entityBinding) { + if ( hierarchical == null ) { + return null; + } + + // the super type here could be either a "mapped superclass" or an entity + if ( Entity.class.isInstance( hierarchical ) ) { + // make sure super entity binding points to same... + final EntityBinding superBinding = entityBinding.getSuperEntityBinding(); + if ( superBinding == null ) { + throw new IllegalStateException( "EntityBinding with super class of Entity type did not specify super entity binding" ); + } + if ( superBinding.getEntity() != hierarchical ) { + throw new IllegalStateException( "Super entity binding and descriptor referenced different descriptors" ); + } + return locateOrBuildEntityType( superBinding ); + } + else if ( MappedSuperclass.class.isInstance( hierarchical ) ) { + return locateOrBuildMappedSuperclassType( (MappedSuperclass) hierarchical, entityBinding ); + } + else { + throw new IllegalStateException( + "Unexpected type for entity super descriptor; expecting Entity or Superclass, found [" + + hierarchical.getDescriptor().getName().toString() + "]" + ); + } + } + + private MappedSuperclassTypeImpl locateOrBuildMappedSuperclassType(MappedSuperclass mappedSuperclass, EntityBinding entityBinding) { + MappedSuperclassTypeImpl mappedSuperclassType = mappedSuperclassTypeMap.get( + loadClass( mappedSuperclass.getDescriptor() ) + ); + if ( mappedSuperclassType == null ) { + mappedSuperclassType = buildMappedSuperclassType( mappedSuperclass, entityBinding ); + } + return mappedSuperclassType; + } + + private Class loadClass(JavaTypeDescriptor descriptor) { + return classLoaderService.classForName( descriptor.getName().toString() ); + } + + @SuppressWarnings("unchecked") + private MappedSuperclassTypeImpl buildMappedSuperclassType(MappedSuperclass mappedSuperclass, EntityBinding entityBinding) { + final Class javaType = loadClass( mappedSuperclass.getDescriptor() ); + final AbstractIdentifiableType superSuperType = locateOrBuildSuperType( mappedSuperclass.getSuperType(), entityBinding ); + + MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl( + javaType, + superSuperType, + entityBinding.getHierarchyDetails().getEntityIdentifier().isNonAggregatedComposite() + && entityBinding.getHierarchyDetails().getEntityIdentifier().getIdClassClass() != null, + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() != null, + entityBinding.getHierarchyDetails().isVersioned() + ); + + mappedSuperclassTypeMap.put( javaType, mappedSuperclassType ); + mappedSuperclassEntityNameMap.put( mappedSuperclassType, entityBinding.getEntityName() ); + return mappedSuperclassType; + } + + public MetamodelImpl buildMetamodel() { + LOG.trace( "Building JPA Metamodel instance..." ); + // we need to process types from superclasses to subclasses + for ( EntityBinding entityBinding : entityBindingList ) { + processHierarchy( entityBinding ); + } + + handleUnusedMappedSuperclasses(); + + for ( EmbeddableTypeImpl embeddable : embeddableTypeMap.values() ) { + populateStaticMetamodel( embeddable ); + } + + return new MetamodelImpl( + entityTypeMap, + mappedSuperclassTypeMap, + embeddableTypeMap, + entityTypeByNameMap + ); + } + + private void handleUnusedMappedSuperclasses() { + // todo : keep running track of MappedSuperclasses as we process them and: + // 1) warn user about them + // 2) build a mapping for them +// final Set unusedMappedSuperclasses = context.getUnusedMappedSuperclasses(); +// if ( !unusedMappedSuperclasses.isEmpty() ) { +// for ( MappedSuperclass mappedSuperclass : unusedMappedSuperclasses ) { +// log.unusedMappedSuperclass( mappedSuperclass.getMappedClass().getName() ); +// locateOrBuildMappedsuperclassType( mappedSuperclass, context ); +// } +// } + } + + private void processHierarchy(EntityBinding entityBinding) { + LOG.trace( " Starting binding [" + entityBinding.getEntityName() + "]" ); + processType( entityBinding.getEntity(), entityBinding ); + } + + /** + * Performs a depth-first traversal of the super types... + * + * @param hierarchical The type descriptor to process + * @param entityBinding + */ + private void processType(Hierarchical hierarchical, EntityBinding entityBinding) { + if ( hierarchical == null ) { + return; + } + + if ( alreadyProcessed.contains( hierarchical ) ) { + return; + } + alreadyProcessed.add( hierarchical ); + + // perform a depth-first traversal of the super types... + processSuperType( hierarchical, entityBinding ); + + final AbstractIdentifiableType jpaDescriptor = Entity.class.isInstance( hierarchical ) + ? entityTypeByNameMap.get( hierarchical.getName() ) + : mappedSuperclassTypeMap.get( loadClass( hierarchical.getDescriptor() ) ); + if ( jpaDescriptor == null && entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) { + return; + } + applyIdMetadata( hierarchical, entityBinding.getHierarchyDetails(), jpaDescriptor ); + applyVersionAttribute( hierarchical, entityBinding.getHierarchyDetails(), jpaDescriptor ); + + for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) { + if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) { + continue; + } + if ( entityBinding.getHierarchyDetails().isVersioned() ) { + if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ) { + // skip the version property, it was already handled previously. + continue; + } + } + final Attribute attribute = attributeBuilder.buildAttribute( jpaDescriptor, attributeBinding ); + if ( attribute != null ) { + //noinspection unchecked + jpaDescriptor.getBuilder().addAttribute( attribute ); + } + } + jpaDescriptor.lock(); + populateStaticMetamodel( jpaDescriptor ); + } + + private void processSuperType(Hierarchical descriptor, EntityBinding entityBinding) { + final Hierarchical superDescriptor = descriptor.getSuperType(); + final EntityBinding superEntityBinding = Entity.class.isInstance( superDescriptor ) + ? entityBinding.getSuperEntityBinding() + : entityBinding; + processType( superDescriptor, superEntityBinding ); + } + + private void applyIdMetadata( + Hierarchical descriptor, + HierarchyDetails hierarchyDetails, + AbstractIdentifiableType jpaDescriptor) { + switch ( hierarchyDetails.getEntityIdentifier().getNature() ) { + case SIMPLE: { + SingularAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( idAttributeBinding != null ) { + if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + //noinspection unchecked + jpaDescriptor.getBuilder().applyIdAttribute( + attributeBuilder.buildIdAttribute( jpaDescriptor, idAttributeBinding ) + ); + } + } + break; + } + case AGGREGATED_COMPOSITE: { + EmbeddedAttributeBinding idAttributeBinding = + (EmbeddedAttributeBinding) hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( idAttributeBinding != null ) { + if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + //noinspection unchecked + jpaDescriptor.getBuilder().applyIdAttribute( + attributeBuilder.buildIdAttribute( jpaDescriptor, idAttributeBinding ) + ); + } + } + break; + } + default: { + // nature == (non-aggregated) COMPOSITE + EmbeddedAttributeBinding idAttributeBinding = + (EmbeddedAttributeBinding) hierarchyDetails.getEntityIdentifier().getAttributeBinding(); + if ( idAttributeBinding != null ) { + if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + Set idClassAttributes = new HashSet(); + for ( AttributeBinding idClassAttributeBinding : idAttributeBinding.getEmbeddableBinding().attributeBindings() ) { + idClassAttributes.add( attributeBuilder.buildIdAttribute( jpaDescriptor, idClassAttributeBinding ) ); + } + //noinspection unchecked + jpaDescriptor.getBuilder().applyIdClassAttributes( idClassAttributes ); + } + } + } + } + } + + private void applyVersionAttribute( + Hierarchical descriptor, + HierarchyDetails hierarchyDetails, + AbstractIdentifiableType jpaDescriptor) { + if ( !hierarchyDetails.isVersioned() ) { + return; + } + + final BasicAttributeBinding versionBinding = hierarchyDetails.getEntityVersion().getVersioningAttributeBinding(); + if ( versionBinding != null ) { + if ( versionBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) { + //noinspection unchecked + jpaDescriptor.getBuilder().applyVersionAttribute( + attributeBuilder.buildVersionAttribute( jpaDescriptor, versionBinding ) + ); + } + } + } + + private void populateStaticMetamodel(AbstractManagedType jpaDescriptor) { + if ( populationSetting == JpaMetaModelPopulationSetting.DISABLED ) { + return; + } + final Class managedTypeClass = jpaDescriptor.getJavaType(); + final String metamodelClassName = managedTypeClass.getName() + "_"; + try { + final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); + // we found the class; so populate it... + registerAttributes( metamodelClass, jpaDescriptor ); + } + catch ( ClassNotFoundException ignore ) { + // nothing to do... + } + + AbstractManagedType superType = jpaDescriptor.getSupertype(); + if ( superType != null ) { + populateStaticMetamodel( superType ); + } + + } + + + private final Set processedMetamodelClasses = new HashSet(); + + private void registerAttributes(Class metamodelClass, AbstractManagedType managedType) { + if ( !processedMetamodelClasses.add( metamodelClass ) ) { + return; + } + + // push the attributes on to the metamodel class... + for ( Object attribute : managedType.getDeclaredAttributes() ) { + + registerAttribute( metamodelClass, (Attribute) attribute ); + } + if ( IdentifiableType.class.isInstance( managedType ) ) { + final AbstractIdentifiableType entityType = (AbstractIdentifiableType) managedType; + // handle version + if ( entityType.hasDeclaredVersionAttribute() ) { + registerAttribute( metamodelClass, entityType.getDeclaredVersion() ); + } + + // handle id-class mappings specially + if ( !entityType.hasSingleIdAttribute() ) { + final Set> attributes = entityType.getIdClassAttributes(); + if ( attributes != null ) { + for ( SingularAttribute attribute : attributes ) { + registerAttribute( metamodelClass, attribute ); + } + } + } + } + + + } + + private void registerAttribute(Class metamodelClass, Attribute attribute) { + final String name = attribute.getName(); + try { + // there is a shortcoming in the existing Hibernate code in terms of the way MappedSuperclass + // support was bolted on which comes to bear right here when the attribute is an embeddable type + // defined on a MappedSuperclass. We do not have the correct information to determine the + // appropriate attribute declarer in such cases and so the incoming metamodelClass most likely + // does not represent the declarer in such cases. + // + // As a result, in the case of embeddable classes we simply use getField rather than get + // getDeclaredField + final Field field = attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED + ? metamodelClass.getField( name ) + : metamodelClass.getDeclaredField( name ); + try { + if ( ! field.isAccessible() ) { + // should be public anyway, but to be sure... + field.setAccessible( true ); + } + field.set( null, attribute ); + } + catch ( IllegalAccessException e ) { + // todo : exception type? + throw new AssertionFailure( + "Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name, + e + ); + } + catch ( IllegalArgumentException e ) { + // most likely a mismatch in the type we are injecting and the defined field; this represents a + // mismatch in how the annotation processor interpretted the attribute and how our metamodel + // and/or annotation binder did. + +// This is particularly the case as arrays are nto handled propery by the StaticMetamodel generator + +// throw new AssertionFailure( +// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name +// + "; expected type : " + attribute.getClass().getName() +// + "; encountered type : " + field.getType().getName() +// ); + LOG.illegalArgumentOnStaticMetamodelFieldInjection(metamodelClass.getName(), + name, + attribute.getClass().getName(), + field.getType().getName()); + } + } + catch ( NoSuchFieldException e ) { + LOG.unableToLocateStaticMetamodelField(metamodelClass.getName(), name); +// throw new AssertionFailure( +// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name +// ); + } + } + + +// private void populateStaticMetamodel(EmbeddableTypeImpl embeddable) { +// if ( populationSetting == JpaMetaModelPopulationSetting.DISABLED ) { +// return; +// } +// final Class managedTypeClass = embeddable.getJavaType(); +// final String metamodelClassName = managedTypeClass.getName() + "_"; +// try { +// final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); +// // we found the class; so populate it... +// registerAttributes( metamodelClass, embeddable ); +// } +// catch ( ClassNotFoundException ignore ) { +// // nothing to do... +// } +// +// AbstractManagedType superType = embeddable.getSupertype(); +// if ( superType != null ) { +// populateStaticMetamodel( superType ); +// } +// } + + + /** + * Implementation of AttributeBuilder.Context + */ + class AttributeBuilderContext implements AttributeBuilder.Context { + public AttributeBuilderContext() { + } + + public Type locateEntityTypeByName(String entityName) { + return entityTypeByNameMap.get( entityName ); + } + + @Override + public void registerEmbeddedableType(EmbeddableTypeImpl embeddableType) { + embeddableTypeMap.put( embeddableType.getJavaType(), embeddableType ); + } + + public SessionFactoryImplementor getSessionFactory() { + return sessionFactory; + } + + @Override + public EntityPersister getSubClassEntityPersister(MappedSuperclassTypeImpl mappedSuperclass) { + final String entityName = mappedSuperclassEntityNameMap.get( mappedSuperclass ); + if ( entityName == null ) { + throw new HibernateException( + String.format( + "Could not resolve @MappedSuperclass [%s] to entity name", + mappedSuperclass.getJavaType().getName() + ) + ); + } + final EntityPersister entityPersister = sessionFactory.getEntityPersister( entityName ); + if ( entityPersister == null ) { + throw new HibernateException( + String.format( + "Unable to resolve entity name [%s] to EntityPersister for @MappedSuperclass [%s]", + entityName, + mappedSuperclass.getJavaType().getName() + ) + ); + } + return entityPersister; + } + + @Override + public void handleUnsupportedFeature(UnsupportedFeature feature) { + if ( populationSetting == JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED ) { + LOG.debug( "Ignoring mapping construct not supported as part of JPA metamodel [" + feature.getMessage() + "]" ); + } + else { + throw new UnsupportedOperationException( feature.getMessage() ); + } + } + } + +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/PluralAttributeMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/PluralAttributeMetadata.java new file mode 100644 index 000000000000..6f2400fdd968 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/PluralAttributeMetadata.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import javax.persistence.metamodel.PluralAttribute; + +/** + * Attribute metadata contract for a plural attribute. + * @param The owner type + * @param The attribute type (the collection type) + * @param The collection element type + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +interface PluralAttributeMetadata extends AttributeMetadata { + /** + * Retrieve the JPA collection type classification for this attribute + * + * @return The JPA collection type classification + */ + public PluralAttribute.CollectionType getAttributeCollectionType(); + + /** + * Retrieve the value context for the collection's elements. + * + * @return The value context for the collection's elements. + */ + public AttributeTypeDescriptor getElementAttributeTypeDescriptor(); + + /** + * Retrieve the value context for the collection's keys (if a map, null otherwise). + * + * @return The value context for the collection's keys (if a map, null otherwise). + */ + public AttributeTypeDescriptor getMapKeyAttributeTypeDescriptor(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/PluralAttributeMetadataImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/PluralAttributeMetadataImpl.java new file mode 100644 index 000000000000..3bfdca276252 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/PluralAttributeMetadataImpl.java @@ -0,0 +1,184 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Member; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.TypeVariable; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.PluralAttribute; + +import org.hibernate.annotations.common.AssertionFailure; +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; + +/** +* @author Steve Ebersole +*/ +public class PluralAttributeMetadataImpl + extends BaseAttributeMetadata + implements PluralAttributeMetadata { + private final PluralAttribute.CollectionType attributeCollectionType; + private final Attribute.PersistentAttributeType elementPersistentAttributeType; + private final Attribute.PersistentAttributeType keyPersistentAttributeType; + private final Class elementJavaType; + private final Class keyJavaType; + private final AttributeTypeDescriptor elementAttributeTypeDescriptor; + private final AttributeTypeDescriptor keyAttributeTypeDescriptor; + + PluralAttributeMetadataImpl( + PluralAttributeBinding attributeBinding, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType, + Attribute.PersistentAttributeType elementPersistentAttributeType, + Attribute.PersistentAttributeType keyPersistentAttributeType) { + super( attributeBinding, ownerType, member, persistentAttributeType ); + this.attributeCollectionType = AttributeBuilder.determineCollectionType( getJavaType() ); + this.elementPersistentAttributeType = elementPersistentAttributeType; + this.keyPersistentAttributeType = keyPersistentAttributeType; + + ParameterizedType signatureType = AttributeBuilder.getSignatureType( member ); + if ( keyPersistentAttributeType == null ) { + elementJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : + Object.class; //FIXME and honor targetEntity? + keyJavaType = null; + } + else { + keyJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) : + Object.class; //FIXME and honor targetEntity? + elementJavaType = signatureType != null ? + getClassFromGenericArgument( signatureType.getActualTypeArguments()[1] ) : + Object.class; //FIXME and honor targetEntity? + } + + this.elementAttributeTypeDescriptor = new AttributeTypeDescriptor() { + @Override + public org.hibernate.type.Type getHibernateType() { + return getAttributeBinding().getPluralAttributeElementBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + public Class getBindableType() { + return elementJavaType; + } + + public ValueClassification getValueClassification() { + switch ( PluralAttributeMetadataImpl.this.elementPersistentAttributeType ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return PluralAttributeMetadataImpl.this; + } + }; + + // interpret the key, if one + if ( keyPersistentAttributeType != null ) { + this.keyAttributeTypeDescriptor = new AttributeTypeDescriptor() { + @Override + public org.hibernate.type.Type getHibernateType() { + return ( (IndexedPluralAttributeBinding) getAttributeBinding() ).getPluralAttributeIndexBinding() + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + } + + public Class getBindableType() { + return keyJavaType; + } + + public ValueClassification getValueClassification() { + switch ( PluralAttributeMetadataImpl.this.keyPersistentAttributeType ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + public AttributeMetadata getAttributeMetadata() { + return PluralAttributeMetadataImpl.this; + } + }; + } + else { + keyAttributeTypeDescriptor = null; + } + } + + private Class getClassFromGenericArgument(java.lang.reflect.Type type) { + if ( type instanceof Class ) { + return (Class) type; + } + else if ( type instanceof TypeVariable ) { + final java.lang.reflect.Type upperBound = ( ( TypeVariable ) type ).getBounds()[0]; + return getClassFromGenericArgument( upperBound ); + } + else if ( type instanceof ParameterizedType ) { + final java.lang.reflect.Type rawType = ( (ParameterizedType) type ).getRawType(); + return getClassFromGenericArgument( rawType ); + } + else { + throw new AssertionFailure( + "Fail to process type argument in a generic declaration. Member : " + getMemberDescription() + + " Type: " + type.getClass() + ); + } + } + + @Override + public PluralAttributeBinding getAttributeBinding() { + return (PluralAttributeBinding) super.getAttributeBinding(); + } + + public AttributeTypeDescriptor getElementAttributeTypeDescriptor() { + return elementAttributeTypeDescriptor; + } + + public PluralAttribute.CollectionType getAttributeCollectionType() { + return attributeCollectionType; + } + + public AttributeTypeDescriptor getMapKeyAttributeTypeDescriptor() { + return keyAttributeTypeDescriptor; + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/SingularAttributeMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/SingularAttributeMetadata.java new file mode 100644 index 000000000000..e3658219321e --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/SingularAttributeMetadata.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +/** + * Attribute metadata contract for a non-plural attribute. + * @param The owner type + * @param The attribute type + * + * @author Steve Ebersole + * @author Emmanuel Bernard + */ +public interface SingularAttributeMetadata extends AttributeMetadata { + /** + * Retrieve the value context for this attribute + * + * @return The attributes value context + */ + public AttributeTypeDescriptor getAttributeTypeDescriptor(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/SingularAttributeMetadataImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/SingularAttributeMetadataImpl.java new file mode 100644 index 000000000000..7ca4e6ab7eee --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/SingularAttributeMetadataImpl.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +import java.lang.reflect.Member; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.jpa.internal.metamodel.AbstractManagedType; +import org.hibernate.metamodel.spi.binding.AttributeBinding; + +/** +* @author Steve Ebersole +*/ +public class SingularAttributeMetadataImpl + extends BaseAttributeMetadata + implements SingularAttributeMetadata { + private final AttributeTypeDescriptor attributeTypeDescriptor; + + public SingularAttributeMetadataImpl( + AttributeBinding attributeBinding, + AbstractManagedType ownerType, + Member member, + Attribute.PersistentAttributeType persistentAttributeType) { + super( attributeBinding, ownerType, member, persistentAttributeType ); + attributeTypeDescriptor = new AttributeTypeDescriptor() { + @Override + public org.hibernate.type.Type getHibernateType() { + return getAttributeMetadata().getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(); + } + + @Override + public Class getBindableType() { + return getAttributeMetadata().getJavaType(); + } + + @Override + public ValueClassification getValueClassification() { + switch ( getPersistentAttributeType() ) { + case EMBEDDED: { + return ValueClassification.EMBEDDABLE; + } + case BASIC: { + return ValueClassification.BASIC; + } + default: { + return ValueClassification.ENTITY; + } + } + } + + @Override + public AttributeMetadata getAttributeMetadata() { + return SingularAttributeMetadataImpl.this; + } + }; + } + + public AttributeTypeDescriptor getAttributeTypeDescriptor() { + return attributeTypeDescriptor; + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/UnsupportedFeature.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/UnsupportedFeature.java new file mode 100644 index 000000000000..e023cee160d6 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/builder/UnsupportedFeature.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.internal.metamodel.builder; + +/** + * Represents Hibernate mapping features that are not supported in JPA metamodel. Used to allow control over how + * such features are handled in regards to building the JPA {@link javax.persistence.metamodel.Metamodel} instance. + * + * @author Steve Ebersole +*/ +public enum UnsupportedFeature { + ANY( "ANY mappings not supported in JPA metamodel" ), + ARRAY( "Arrays (HBM mappings) are not supported in JPA metamodel" ); + + private final String message; + + UnsupportedFeature(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/GenerationSourceFromMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/GenerationSourceFromMetadata.java index 5810a8f21d8c..a38675b89db0 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/GenerationSourceFromMetadata.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/GenerationSourceFromMetadata.java @@ -23,10 +23,16 @@ */ package org.hibernate.jpa.internal.schemagen; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; -import org.hibernate.cfg.Configuration; -import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.schema.spi.SchemaCreator; +import org.hibernate.tool.schema.spi.SchemaDropper; +import org.hibernate.tool.schema.spi.SchemaManagementTool; +import org.hibernate.tool.schema.spi.Target; /** * Handle schema generation source from (annotation/xml) metadata. @@ -34,21 +40,60 @@ * @author Steve Ebersole */ public class GenerationSourceFromMetadata implements GenerationSource { - private final Configuration hibernateConfiguration; - private final Dialect dialect; + private final MetadataImplementor metadata; + private final ServiceRegistry serviceRegistry; + private final Map options; private final boolean creation; - public GenerationSourceFromMetadata(Configuration hibernateConfiguration, Dialect dialect, boolean creation) { - this.hibernateConfiguration = hibernateConfiguration; - this.dialect = dialect; + public GenerationSourceFromMetadata( + MetadataImplementor metadata, + ServiceRegistry serviceRegistry, + Map options, + boolean creation) { + this.metadata = metadata; + this.serviceRegistry = serviceRegistry; + this.options = options; this.creation = creation; } @Override public Iterable getCommands() { - return creation - ? Arrays.asList( hibernateConfiguration.generateSchemaCreationScript( dialect ) ) - : Arrays.asList( hibernateConfiguration.generateDropSchemaScript( dialect ) ); + final List commands = new ArrayList(); + final Target collector = new Target() { + @Override + public boolean acceptsImportScriptActions() { + // JpaSchemaGenerator handles import scripts + return false; + } + + @Override + public void prepare() { + } + + @Override + public void accept(String action) { + commands.add( action ); + } + + @Override + public void release() { + } + }; + + if ( creation ) { + final SchemaCreator schemaCreator = serviceRegistry.getService( SchemaManagementTool.class ) + .getSchemaCreator( options ); + // NOTE : false here is for `createSchemas` since JpaSchemaGenerator itself handles that + schemaCreator.doCreation( metadata.getDatabase(), false, collector ); + } + else { + final SchemaDropper schemaDropper = serviceRegistry.getService( SchemaManagementTool.class ) + .getSchemaDropper( options ); + // NOTE : false here is for `dropSchemas` since JpaSchemaGenerator itself handles that + schemaDropper.doDrop( metadata.getDatabase(), false, collector ); + } + + return commands; } @Override diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java index 9189bc62af3b..d888f2ec28e3 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java @@ -33,14 +33,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.persistence.PersistenceException; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter; @@ -55,12 +53,28 @@ import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.SchemaGenAction; import org.hibernate.jpa.SchemaGenSource; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractor; import org.jboss.logging.Logger; +import static org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_CONNECTION; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_CREATE_SCRIPT_SOURCE; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_CREATE_SOURCE; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_DATABASE_ACTION; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_DB_MAJOR_VERSION; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_DB_MINOR_VERSION; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_DB_NAME; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_DROP_SCRIPT_SOURCE; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_DROP_SOURCE; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_LOAD_SCRIPT_SOURCE; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_SCRIPTS_ACTION; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET; +import static org.hibernate.jpa.AvailableSettings.SCHEMA_GEN_SCRIPTS_DROP_TARGET; + /** * Class responsible for the JPA-defined schema generation behavior. * @@ -72,8 +86,8 @@ public class JpaSchemaGenerator { private JpaSchemaGenerator() { } - public static void performGeneration(Configuration hibernateConfiguration, ServiceRegistry serviceRegistry) { - new Generation( serviceRegistry ).execute( hibernateConfiguration ); + public static void performGeneration(MetadataImplementor metadata, Map settings, ServiceRegistry serviceRegistry) { + new Generation( serviceRegistry ).execute( metadata, settings ); } /** @@ -97,18 +111,12 @@ public Generation(ServiceRegistry serviceRegistry) { /** * Perform the generation, as indicated by the settings - * - * @param hibernateConfiguration The hibernate configuration */ - public void execute(Configuration hibernateConfiguration) { + public void execute(MetadataImplementor metadata, Map settings) { // First, determine the actions (if any) to be performed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - final SchemaGenAction databaseAction = SchemaGenAction.interpret( - hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DATABASE_ACTION ) - ); - final SchemaGenAction scriptsAction = SchemaGenAction.interpret( - hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_SCRIPTS_ACTION ) - ); + final SchemaGenAction databaseAction = SchemaGenAction.interpret( settings.get( SCHEMA_GEN_DATABASE_ACTION ) ); + final SchemaGenAction scriptsAction = SchemaGenAction.interpret( settings.get( SCHEMA_GEN_SCRIPTS_ACTION ) ); if ( databaseAction == SchemaGenAction.NONE && scriptsAction == SchemaGenAction.NONE ) { // no actions needed @@ -120,22 +128,23 @@ public void execute(Configuration hibernateConfiguration) { // Figure out the JDBC Connection context, if any ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ final JdbcConnectionContext jdbcConnectionContext = determineAppropriateJdbcConnectionContext( - hibernateConfiguration, + settings, serviceRegistry ); try { - final Dialect dialect = determineDialect( jdbcConnectionContext, hibernateConfiguration, serviceRegistry ); + final Dialect dialect = determineDialect( jdbcConnectionContext, settings, serviceRegistry ); // determine sources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // todo : need a way to force the Dialect to use into the SchemaManagementTool final List createSourceList = databaseAction.includesCreate() || scriptsAction.includesCreate() - ? buildCreateSourceList( hibernateConfiguration, dialect ) + ? buildCreateSourceList( settings, metadata, dialect ) : Collections.emptyList(); final List dropSourceList = databaseAction.includesDrop() || scriptsAction.includesDrop() - ? buildDropSourceList( hibernateConfiguration, dialect ) + ? buildDropSourceList( settings, metadata ) : Collections.emptyList(); @@ -143,22 +152,18 @@ public void execute(Configuration hibernateConfiguration) { final GenerationTarget databaseTarget = new GenerationTargetToDatabase( jdbcConnectionContext, databaseAction ); - final Object createScriptTargetSetting = hibernateConfiguration.getProperties().get( - AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET - ); - final Object dropScriptTargetSetting = hibernateConfiguration.getProperties().get( - AvailableSettings.SCHEMA_GEN_SCRIPTS_DROP_TARGET - ); + final Object createScriptTargetSetting = settings.get( SCHEMA_GEN_SCRIPTS_CREATE_TARGET ); + final Object dropScriptTargetSetting = settings.get( SCHEMA_GEN_SCRIPTS_DROP_TARGET ); final GenerationTarget scriptsTarget = new GenerationTargetToScript( interpretScriptTargetSetting( createScriptTargetSetting, scriptsAction.includesCreate(), - AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET + SCHEMA_GEN_SCRIPTS_CREATE_TARGET ), interpretScriptTargetSetting( dropScriptTargetSetting, scriptsAction.includesDrop(), - AvailableSettings.SCHEMA_GEN_SCRIPTS_DROP_TARGET + SCHEMA_GEN_SCRIPTS_DROP_TARGET ), scriptsAction ); @@ -167,12 +172,11 @@ public void execute(Configuration hibernateConfiguration) { // See if native Hibernate schema generation has also been requested and warn the user if so... - - final String hbm2ddl = hibernateConfiguration.getProperty( org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO ); + final String hbm2ddl = (String) settings.get( HBM2DDL_AUTO ); if ( StringHelper.isNotEmpty( hbm2ddl ) ) { log.warnf( - "Hibernate hbm2ddl-auto setting was specified [%s] in combination with JPA schema-generation; " + - "combination will likely cause trouble", + "Hibernate hbm2ddl-auto setting [%s] was specified in combination with " + + "JPA schema-generation; combination will likely cause trouble", hbm2ddl ); } @@ -245,30 +249,29 @@ public void release() { } } - private List buildCreateSourceList(Configuration hibernateConfiguration, Dialect dialect) { + private List buildCreateSourceList( + Map configurationValues, + MetadataImplementor metadata, + Dialect dialect) { final List generationSourceList = new ArrayList(); // If we are asked to perform CREATE SCHEMA commands do them first ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ final boolean createSchemas = ConfigurationHelper.getBoolean( AvailableSettings.SCHEMA_GEN_CREATE_SCHEMAS, - hibernateConfiguration.getProperties(), + configurationValues, false ); if ( createSchemas ) { - generationSourceList.add( new CreateSchemaCommandSource( hibernateConfiguration, dialect ) ); + generationSourceList.add( new CreateSchemaCommandSource( metadata, dialect ) ); } // Next figure out the intended sources of generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - SchemaGenSource sourceType = SchemaGenSource.interpret( - hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_CREATE_SOURCE ) - ); + SchemaGenSource sourceType = SchemaGenSource.interpret( configurationValues.get( SCHEMA_GEN_CREATE_SOURCE ) ); - final Object createScriptSourceSetting = hibernateConfiguration.getProperties().get( - AvailableSettings.SCHEMA_GEN_CREATE_SCRIPT_SOURCE - ); + final Object createScriptSourceSetting = configurationValues.get( SCHEMA_GEN_CREATE_SCRIPT_SOURCE ); if ( sourceType == null ) { if ( createScriptSourceSetting != null ) { @@ -290,26 +293,24 @@ private List buildCreateSourceList(Configuration hibernateConf : null; if ( sourceType == SchemaGenSource.METADATA ) { - generationSourceList.add( new GenerationSourceFromMetadata( hibernateConfiguration, dialect, true ) ); + generationSourceList.add( new GenerationSourceFromMetadata( metadata, serviceRegistry, configurationValues, true ) ); } else if ( sourceType == SchemaGenSource.SCRIPT ) { generationSourceList.add( new GenerationSourceFromScript( scriptSourceInput, scriptCommandExtractor ) ); } else if ( sourceType == SchemaGenSource.METADATA_THEN_SCRIPT ) { - generationSourceList.add( new GenerationSourceFromMetadata( hibernateConfiguration, dialect, true ) ); + generationSourceList.add( new GenerationSourceFromMetadata( metadata, serviceRegistry, configurationValues, true ) ); generationSourceList.add( new GenerationSourceFromScript( scriptSourceInput, scriptCommandExtractor ) ); } else if ( sourceType == SchemaGenSource.SCRIPT_THEN_METADATA ) { generationSourceList.add( new GenerationSourceFromScript( scriptSourceInput, scriptCommandExtractor ) ); - generationSourceList.add( new GenerationSourceFromMetadata( hibernateConfiguration, dialect, true ) ); + generationSourceList.add( new GenerationSourceFromMetadata( metadata, serviceRegistry, configurationValues, true ) ); } // finally, see if there is an import script specified ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - final Object importScriptSetting = hibernateConfiguration.getProperties().get( - AvailableSettings.SCHEMA_GEN_LOAD_SCRIPT_SOURCE - ); + final Object importScriptSetting = configurationValues.get( SCHEMA_GEN_LOAD_SCRIPT_SOURCE ); if ( importScriptSetting != null ) { final ScriptSourceInput importScriptInput = interpretScriptSourceSetting( importScriptSetting ); generationSourceList.add( new ImportScriptSource( importScriptInput, scriptCommandExtractor ) ); @@ -344,17 +345,12 @@ private ScriptSourceInput interpretScriptSourceSetting(Object scriptSourceSettin } } - private List buildDropSourceList(Configuration hibernateConfiguration, Dialect dialect) { + private List buildDropSourceList(Map configurationValues, MetadataImplementor metadata) { final List generationSourceList = new ArrayList(); - SchemaGenSource sourceType = SchemaGenSource.interpret( - hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DROP_SOURCE ) - ); - - final Object dropScriptSourceSetting = hibernateConfiguration.getProperties().get( - AvailableSettings.SCHEMA_GEN_DROP_SCRIPT_SOURCE - ); + SchemaGenSource sourceType = SchemaGenSource.interpret( configurationValues.get( SCHEMA_GEN_DROP_SOURCE ) ); + final Object dropScriptSourceSetting = configurationValues.get( SCHEMA_GEN_DROP_SCRIPT_SOURCE ); if ( sourceType == null ) { if ( dropScriptSourceSetting != null ) { sourceType = SchemaGenSource.SCRIPT; @@ -376,18 +372,18 @@ private List buildDropSourceList(Configuration hibernateConfig : null; if ( sourceType == SchemaGenSource.METADATA ) { - generationSourceList.add( new GenerationSourceFromMetadata( hibernateConfiguration, dialect, false ) ); + generationSourceList.add( new GenerationSourceFromMetadata( metadata, serviceRegistry, configurationValues, false ) ); } else if ( sourceType == SchemaGenSource.SCRIPT ) { generationSourceList.add( new GenerationSourceFromScript( scriptSourceInput, scriptCommandExtractor ) ); } else if ( sourceType == SchemaGenSource.METADATA_THEN_SCRIPT ) { - generationSourceList.add( new GenerationSourceFromMetadata( hibernateConfiguration, dialect, false ) ); + generationSourceList.add( new GenerationSourceFromMetadata( metadata, serviceRegistry, configurationValues, false ) ); generationSourceList.add( new GenerationSourceFromScript( scriptSourceInput, scriptCommandExtractor ) ); } else if ( sourceType == SchemaGenSource.SCRIPT_THEN_METADATA ) { generationSourceList.add( new GenerationSourceFromScript( scriptSourceInput, scriptCommandExtractor ) ); - generationSourceList.add( new GenerationSourceFromMetadata( hibernateConfiguration, dialect, false ) ); + generationSourceList.add( new GenerationSourceFromMetadata( metadata, serviceRegistry, configurationValues, false ) ); } return generationSourceList; @@ -395,14 +391,12 @@ else if ( sourceType == SchemaGenSource.SCRIPT_THEN_METADATA ) { } private static JdbcConnectionContext determineAppropriateJdbcConnectionContext( - Configuration hibernateConfiguration, + Map configurationValues, ServiceRegistry serviceRegistry) { final SqlStatementLogger sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger(); // see if a specific connection has been provided: - final Connection providedConnection = (Connection) hibernateConfiguration.getProperties().get( - AvailableSettings.SCHEMA_GEN_CONNECTION - ); + final Connection providedConnection = (Connection) configurationValues.get( SCHEMA_GEN_CONNECTION ); if ( providedConnection != null ) { return new JdbcConnectionContext( new ProvidedJdbcConnectionAccess( providedConnection ), sqlStatementLogger ); @@ -424,20 +418,20 @@ public Connection getJdbcConnection() { private static Dialect determineDialect( final JdbcConnectionContext jdbcConnectionContext, - final Configuration hibernateConfiguration, + final Map configurationValues, ServiceRegistry serviceRegistry) { return serviceRegistry.getService( DialectFactory.class ).buildDialect( - hibernateConfiguration.getProperties(), + configurationValues, new DialectResolutionInfoSource() { @Override public DialectResolutionInfo getDialectResolutionInfo() { // if the application supplied database name/version info, use that - final String explicitDbName = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_NAME ); + final String explicitDbName = (String) configurationValues.get( SCHEMA_GEN_DB_NAME ); if ( StringHelper.isNotEmpty( explicitDbName ) ) { - final String explicitDbMajor = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_MAJOR_VERSION ); - final String explicitDbMinor = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_MINOR_VERSION ); + final String explicitDbMajor = (String) configurationValues.get( SCHEMA_GEN_DB_MAJOR_VERSION ); + final String explicitDbMinor = (String) configurationValues.get( SCHEMA_GEN_DB_MINOR_VERSION ); return new DialectResolutionInfo() { @Override @@ -542,46 +536,13 @@ private static void releaseJdbcConnectionContext(JdbcConnectionContext jdbcConne private static class CreateSchemaCommandSource implements GenerationSource { - private final List commands; - - private CreateSchemaCommandSource(Configuration hibernateConfiguration, Dialect dialect) { - // NOTES: - // 1) catalogs are currently not handled here at all - // 2) schemas for sequences are not handled here at all - // Both of these are handle-able on the metamodel codebase - - final HashSet schemas = new HashSet(); -// final HashSet catalogs = new HashSet(); - - final Iterator

    tables = hibernateConfiguration.getTableMappings(); - while ( tables.hasNext() ) { - final Table table = tables.next(); -// catalogs.add( table.getCatalog() ); - schemas.add( table.getSchema() ); - } - -// final Iterator generators = hibernateConfiguration.iterateGenerators( dialect ); -// while ( generators.hasNext() ) { -// final IdentifierGenerator generator = generators.next(); -// if ( PersistentIdentifierGenerator.class.isInstance( generator ) ) { -//// catalogs.add( ( (PersistentIdentifierGenerator) generator ).getCatalog() ); -// schemas.add( ( (PersistentIdentifierGenerator) generator ).getSchema() ); -// } -// } - -// if ( schemas.isEmpty() && catalogs.isEmpty() ) { - if ( schemas.isEmpty() ) { - commands = Collections.emptyList(); - return; - } + private final List commands = new ArrayList(); - commands = new ArrayList(); - - for ( String schema : schemas ) { - commands.add( dialect.getCreateSchemaCommand( schema ) ); + private CreateSchemaCommandSource(MetadataImplementor metadata, Dialect dialect) { + for ( Schema schema : metadata.getDatabase().getSchemas() ) { + commands.add( dialect.getCreateSchemaCommand( schema.getName().getSchema().getText( dialect ) ) ); + // todo : research CREATE CATALOG commands. Always CREATE DATABASE? } - - // generate "create catalog" commands } @Override diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractQueryImpl.java old mode 100644 new mode 100755 index 0fbc0a80de7c..f858c489e7c1 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractQueryImpl.java @@ -124,10 +124,11 @@ public TypedQuery setLockMode(javax.persistence.LockModeType lockModeType) { throw new IllegalStateException( "Illegal attempt to set lock mode on a native SQL query" ); } - if ( ! isSelectQuery() ) { - throw new IllegalStateException( "Illegal attempt to set lock mode on a non-SELECT query" ); + if ( ! LockModeType.NONE.equals(lockModeType)) { + if ( ! isSelectQuery() ) { + throw new IllegalStateException( "Illegal attempt to set lock mode on a non-SELECT query" ); + } } - if ( ! canApplyAliasSpecificLockModeHints() ) { throw new IllegalStateException( "Not a JPAQL/Criteria query" ); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cacheable/annotation/ConfigurationTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cacheable/annotation/ConfigurationTest.java index 9566601eed35..5b4871cae830 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cacheable/annotation/ConfigurationTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cacheable/annotation/ConfigurationTest.java @@ -23,27 +23,11 @@ */ package org.hibernate.jpa.test.cacheable.annotation; -import javax.persistence.SharedCacheMode; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.cache.internal.NoCachingRegionFactory; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.jpa.test.PersistenceUnitInfoAdapter; -import org.hibernate.jpa.AvailableSettings; -import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl; -import org.hibernate.jpa.boot.spi.Bootstrap; -import org.hibernate.mapping.PersistentClass; - -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; /** * this is hacky transient step until EMF building is integrated with metamodel @@ -52,108 +36,114 @@ */ public class ConfigurationTest extends BaseUnitTestCase { @Test - public void testSharedCacheModeNone() { - Configuration config = buildConfiguration( SharedCacheMode.NONE ); - - PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - } - - @Test - public void testSharedCacheModeUnspecified() { - Configuration config = buildConfiguration( SharedCacheMode.UNSPECIFIED ); - - PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - } - - @Test - public void testSharedCacheModeAll() { - Configuration config = buildConfiguration( SharedCacheMode.ALL ); - - PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); - assertNotNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); - assertNotNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); - assertNotNull( pc.getCacheConcurrencyStrategy() ); + @FailureExpectedWithNewMetamodel + public void dummy() { + fail( "Help me!" ); } - @Test - public void testSharedCacheModeEnable() { - Configuration config = buildConfiguration( SharedCacheMode.ENABLE_SELECTIVE ); - - PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); - assertNotNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - } - - @Test - public void testSharedCacheModeDisable() { - Configuration config = buildConfiguration( SharedCacheMode.DISABLE_SELECTIVE ); - - PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); - assertNotNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); - assertNull( pc.getCacheConcurrencyStrategy() ); - - pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); - assertNotNull( pc.getCacheConcurrencyStrategy() ); - } - - @SuppressWarnings("unchecked") - private Configuration buildConfiguration(SharedCacheMode mode) { - Map settings = new HashMap(); - settings.put( AvailableSettings.SHARED_CACHE_MODE, mode ); - settings.put( Environment.CACHE_REGION_FACTORY, CustomRegionFactory.class.getName() ); - settings.put( - AvailableSettings.LOADED_CLASSES, - Arrays.asList( - ExplicitlyCacheableEntity.class, - ExplicitlyNonCacheableEntity.class, - NoCacheableAnnotationEntity.class - ) - ); - - PersistenceUnitInfoAdapter adapter = new PersistenceUnitInfoAdapter(); - - EntityManagerFactoryBuilderImpl emfb = (EntityManagerFactoryBuilderImpl) Bootstrap.getEntityManagerFactoryBuilder( - adapter, - settings - ); - - Configuration hibernateConfiguration = emfb.buildHibernateConfiguration( emfb.buildServiceRegistry() ); - hibernateConfiguration.buildMappings(); - return hibernateConfiguration; - } - - public static class CustomRegionFactory extends NoCachingRegionFactory { - public CustomRegionFactory() { - } - - @Override - public AccessType getDefaultAccessType() { - return AccessType.READ_WRITE; - } - } +// @Test +// public void testSharedCacheModeNone() { +// MetadataImplementor metadata = buildMetadata( SharedCacheMode.NONE ); +// +// PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// } +// +// @Test +// public void testSharedCacheModeUnspecified() { +// Configuration config = buildConfiguration( SharedCacheMode.UNSPECIFIED ); +// +// PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// } +// +// @Test +// public void testSharedCacheModeAll() { +// Configuration config = buildConfiguration( SharedCacheMode.ALL ); +// +// PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); +// assertNotNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); +// assertNotNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); +// assertNotNull( pc.getCacheConcurrencyStrategy() ); +// } +// +// @Test +// public void testSharedCacheModeEnable() { +// Configuration config = buildConfiguration( SharedCacheMode.ENABLE_SELECTIVE ); +// +// PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); +// assertNotNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// } +// +// @Test +// public void testSharedCacheModeDisable() { +// Configuration config = buildConfiguration( SharedCacheMode.DISABLE_SELECTIVE ); +// +// PersistentClass pc = config.getClassMapping( ExplicitlyCacheableEntity.class.getName() ); +// assertNotNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( ExplicitlyNonCacheableEntity.class.getName() ); +// assertNull( pc.getCacheConcurrencyStrategy() ); +// +// pc = config.getClassMapping( NoCacheableAnnotationEntity.class.getName() ); +// assertNotNull( pc.getCacheConcurrencyStrategy() ); +// } +// +// @SuppressWarnings("unchecked") +// private Configuration buildConfiguration(SharedCacheMode mode) { +// Map settings = new HashMap(); +// settings.put( AvailableSettings.SHARED_CACHE_MODE, mode ); +// settings.put( Environment.CACHE_REGION_FACTORY, CustomRegionFactory.class.getName() ); +// settings.put( +// AvailableSettings.LOADED_CLASSES, +// Arrays.asList( +// ExplicitlyCacheableEntity.class, +// ExplicitlyNonCacheableEntity.class, +// NoCacheableAnnotationEntity.class +// ) +// ); +// +// PersistenceUnitInfoAdapter adapter = new PersistenceUnitInfoAdapter(); +// +// EntityManagerFactoryBuilderImpl emfb = (EntityManagerFactoryBuilderImpl) Bootstrap.getEntityManagerFactoryBuilder( +// adapter, +// settings +// ); +// +// Configuration hibernateConfiguration = emfb.buildHibernateConfiguration( emfb.buildServiceRegistry() ); +// hibernateConfiguration.buildMappings(); +// return hibernateConfiguration; +// } +// +// public static class CustomRegionFactory extends NoCachingRegionFactory { +// public CustomRegionFactory() { +// } +// +// @Override +// public AccessType getDefaultAccessType() { +// return AccessType.READ_WRITE; +// } +// } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/callbacks/CallbacksTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/callbacks/CallbacksTest.java index f6926a136fdb..7b4caefcfaf2 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/callbacks/CallbacksTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/callbacks/CallbacksTest.java @@ -12,6 +12,7 @@ import org.hibernate.jpa.test.Kitten; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -131,7 +132,9 @@ public void testPrePersistOnCascade() throws Exception { } @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8931" ) public void testCallBackListenersHierarchy() throws Exception { + // used both to EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); Television tv = new Television(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Conference.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Conference.java index 18c8000b890e..ae9e0e6da461 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Conference.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Conference.java @@ -2,6 +2,7 @@ package org.hibernate.jpa.test.cascade; import java.io.Serializable; import java.util.Date; + import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; @@ -15,6 +16,9 @@ import javax.persistence.OneToOne; import javax.persistence.Table; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + /** * @author Emmanuel Bernard */ @@ -23,7 +27,8 @@ @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.CHAR) @DiscriminatorValue("X") -@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true) +@DynamicInsert +@DynamicUpdate public class Conference implements Serializable { private Long id; private Date date; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocument.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocument.java index cc5c1d34d2b2..4045ba9dc0c5 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocument.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocument.java @@ -2,6 +2,7 @@ package org.hibernate.jpa.test.cascade; import java.io.Serializable; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -10,6 +11,8 @@ import javax.persistence.OneToOne; import javax.persistence.Table; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Proxy; /** @@ -18,7 +21,8 @@ @Entity @Table(name = "portal_pk_docs_extraction") //@Cache(usage = READ_WRITE) -@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true) +@DynamicInsert +@DynamicUpdate @Proxy public class ExtractionDocument implements Serializable { private Long id; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocumentInfo.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocumentInfo.java index a2f849194f47..02d782265eb4 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocumentInfo.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/ExtractionDocumentInfo.java @@ -5,6 +5,7 @@ import java.util.Date; import java.util.Iterator; import java.util.List; + import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; @@ -17,13 +18,17 @@ import javax.persistence.Table; import javax.persistence.Transient; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + /** * @author Emmanuel Bernard */ @Entity @Table(name = "portal_pk_docs_extraction_info") //@Cache(usage = READ_WRITE) -@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true) +@DynamicInsert +@DynamicUpdate public class ExtractionDocumentInfo implements Serializable { private Long id; private Date lastModified; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Student.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Student.java index 590ea1fd0362..f46fab3e367a 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Student.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Student.java @@ -1,5 +1,7 @@ package org.hibernate.jpa.test.cascade; +import javax.persistence.Access; +import javax.persistence.AccessType; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -7,10 +9,8 @@ import javax.persistence.ManyToOne; import javax.persistence.OneToOne; -import org.hibernate.annotations.AccessType; - @Entity -@AccessType("field") +@Access(AccessType.FIELD) public class Student { @Id @GeneratedValue diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Teacher.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Teacher.java index bd0a12079181..d937b594eb61 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Teacher.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Teacher.java @@ -2,6 +2,9 @@ import java.util.HashSet; import java.util.Set; + +import javax.persistence.Access; +import javax.persistence.AccessType; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -9,10 +12,8 @@ import javax.persistence.OneToMany; import javax.persistence.OneToOne; -import org.hibernate.annotations.AccessType; - @Entity -@AccessType("field") +@Access(AccessType.FIELD) public class Teacher { @Id @GeneratedValue diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Troop.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Troop.java index a0ac5990e982..947a891be89b 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Troop.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/Troop.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.HashSet; import java.util.Set; + import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -22,9 +23,8 @@ public class Troop implements Serializable { private String name; private Set soldiers; - @OneToMany(mappedBy = "troop", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) + @OneToMany(mappedBy = "troop", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, orphanRemoval = true) @OrderBy(clause = "name desc") - @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) public Set getSoldiers() { return soldiers; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/multicircle/MultiCircleJpaCascadeTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/multicircle/MultiCircleJpaCascadeTest.java index 4ec860f7bddd..7f31b6bc85d3 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/multicircle/MultiCircleJpaCascadeTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/cascade/multicircle/MultiCircleJpaCascadeTest.java @@ -34,6 +34,7 @@ import org.hibernate.TransientPropertyValueException; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -175,7 +176,11 @@ public void cleanup() { } @Test + @FailureExpectedWithNewMetamodel public void testPersist() { + + // no idea why this fails with new metamodel + EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); em.persist( b ); @@ -186,7 +191,11 @@ public void testPersist() { } @Test + @FailureExpectedWithNewMetamodel public void testPersistNoCascadeToTransient() { + + // no idea why this fails with new metamodel + skipCleanup = true; EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java index 5b30f3fcc54a..706e093addd1 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java @@ -24,10 +24,15 @@ import java.io.File; -import org.junit.Assert; +import javax.persistence.EntityManagerFactory; + import org.junit.Test; -import org.hibernate.ejb.HibernatePersistence; +import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.HibernatePersistenceProvider; + +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; /** * @author Emmanuel Bernard @@ -40,8 +45,12 @@ public void testDatasourceInjection() throws Exception { sub.mkdir(); PersistenceUnitInfoImpl info = new PersistenceUnitInfoImpl( sub.toURI().toURL(), new String[]{} ); try { - new HibernatePersistence().createContainerEntityManagerFactory( info, null ); - Assert.fail( "FakeDatasource should have been used" ); + EntityManagerFactory emf = new HibernatePersistenceProvider().createContainerEntityManagerFactory( info, null ); + DatasourceConnectionProviderImpl cp = assertTyping( + DatasourceConnectionProviderImpl.class, + emf.unwrap( SessionFactoryImplementor.class ).getConnectionProvider() + ); + assertTyping( FakeDataSource.class, cp.getDataSource() ); } catch (FakeDataSourceException fde) { //success diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java new file mode 100644 index 000000000000..b7facb864847 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java @@ -0,0 +1,139 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.convert; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.AttributeConverter; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import org.junit.Test; + +import org.joda.time.LocalDate; +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; + +/** + * @author Steve Ebersole + */ +@TestForIssue( jiraKey = "HHH-8842" ) +public class BasicJodaTimeConversionTest extends BaseUnitTestCase { + static int callsToConverter = 0; + + public static class JodaLocalDateConverter implements AttributeConverter { + public Date convertToDatabaseColumn(LocalDate localDate) { + callsToConverter++; + return localDate.toDate(); + } + + public LocalDate convertToEntityAttribute(Date date) { + callsToConverter++; + return LocalDate.fromDateFields( date ); + } + } + + @Entity( name = "TheEntity" ) + public static class TheEntity { + @Id + public Integer id; + @Convert( converter = JodaLocalDateConverter.class ) + public LocalDate theDate; + + public TheEntity() { + } + + public TheEntity(Integer id, LocalDate theDate) { + this.id = id; + this.theDate = theDate; + } + } + + @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) + public void testSimpleConvertUsage() throws MalformedURLException { + final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { + @Override + public List getManagedClassNames() { + return Arrays.asList( TheEntity.class.getName() ); + } + }; + + final Map settings = new HashMap(); + settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); + + EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); + final EntityPersister ep = emf.unwrap( SessionFactoryImplementor.class ).getEntityPersister( TheEntity.class.getName() ); + final Type theDatePropertyType = ep.getPropertyType( "theDate" ); + final AttributeConverterTypeAdapter type = assertTyping( AttributeConverterTypeAdapter.class, theDatePropertyType ); + assertTyping( JodaLocalDateConverter.class, type.getAttributeConverter() ); + + try { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist( new TheEntity( 1, new LocalDate() ) ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 1, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.find( TheEntity.class, 1 ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 2, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete TheEntity" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } + finally { + emf.close(); + } + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionCompositeElementConversionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionCompositeElementConversionTest.java index 24d7784da7c1..5606e77ee84c 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionCompositeElementConversionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionCompositeElementConversionTest.java @@ -48,6 +48,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -59,6 +60,7 @@ @TestForIssue( jiraKey = "HHH-8529" ) public class CollectionCompositeElementConversionTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testElementCollectionConversion() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionElementConversionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionElementConversionTest.java index ee7e97ecdec4..c1f43acbaeef 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionElementConversionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/CollectionElementConversionTest.java @@ -49,6 +49,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -60,6 +61,7 @@ @TestForIssue( jiraKey = "HHH-8529" ) public class CollectionElementConversionTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testElementCollectionConversion() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/ExplicitDateConvertersTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/ExplicitDateConvertersTest.java new file mode 100644 index 000000000000..57138e4d8f3a --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/ExplicitDateConvertersTest.java @@ -0,0 +1,143 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.convert; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.AttributeConverter; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; + +/** + * @author Steve Ebersole + */ +@TestForIssue( jiraKey = "HHH-8807" ) +public class ExplicitDateConvertersTest extends BaseUnitTestCase { + + // NOTE : initially unable to reproduce the reported problem + + static int callsToConverter = 0; + + public static class LongToDateConverter implements AttributeConverter { + @Override + public Long convertToDatabaseColumn(Date attribute) { + callsToConverter++; + return attribute.getTime(); + } + + @Override + public Date convertToEntityAttribute(Long dbData) { + callsToConverter++; + return new Date( dbData ); + } + } + + @Entity( name = "Entity1" ) + public static class Entity1 { + @Id + private Integer id; + private String name; + @Convert( converter = LongToDateConverter.class ) + private Date theDate; + + public Entity1() { + } + + public Entity1(Integer id, String name, Date theDate) { + this.id = id; + this.name = name; + this.theDate = theDate; + } + } + + @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) + public void testSimpleConvertUsage() throws MalformedURLException { + final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { + @Override + public List getManagedClassNames() { + return Arrays.asList( Entity1.class.getName() ); + } + }; + + final Map settings = new HashMap(); + settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); + + EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); + final EntityPersister ep = emf.unwrap( SessionFactoryImplementor.class ).getEntityPersister( Entity1.class.getName() ); + final Type theDatePropertyType = ep.getPropertyType( "theDate" ); + final AttributeConverterTypeAdapter type = assertTyping( AttributeConverterTypeAdapter.class, theDatePropertyType ); + assertTyping( LongToDateConverter.class, type.getAttributeConverter() ); + + try { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist( new Entity1( 1, "1", new Date() ) ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 1, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.find( Entity1.class, 1 ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 2, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete Entity1" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } + finally { + emf.close(); + } + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/ExplicitEnumConvertersTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/ExplicitEnumConvertersTest.java new file mode 100644 index 000000000000..c6c254e43afe --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/ExplicitEnumConvertersTest.java @@ -0,0 +1,151 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.convert; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.AttributeConverter; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; + +/** + * @author Steve Ebersole + */ +@TestForIssue( jiraKey = "HHH-8809" ) +public class ExplicitEnumConvertersTest extends BaseUnitTestCase { + + // NOTE : initially unable to reproduce the reported problem + + public static enum MediaType { + MUSIC, + VIDEO, + PHOTO, + MUSIC_STREAM, + VIDEO_STREAM + } + + public static class MediaTypeConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(MediaType attribute) { + callsToConverter++; + return attribute.name(); + } + + @Override + public MediaType convertToEntityAttribute(String dbData) { + callsToConverter++; + return MediaType.valueOf( dbData ); + } + } + + static int callsToConverter = 0; + + @Entity( name = "Entity1" ) + public static class Entity1 { + @Id + private Integer id; + private String name; + @Convert( converter = MediaTypeConverter.class ) + private MediaType mediaType; + + public Entity1() { + } + + public Entity1(Integer id, String name, MediaType mediaType) { + this.id = id; + this.name = name; + this.mediaType = mediaType; + } + } + + @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) + public void testSimpleConvertUsage() throws MalformedURLException { + final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { + @Override + public List getManagedClassNames() { + return Arrays.asList( Entity1.class.getName() ); + } + }; + + final Map settings = new HashMap(); + settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); + + EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); + final EntityPersister ep = emf.unwrap( SessionFactoryImplementor.class ).getEntityPersister( Entity1.class.getName() ); + final Type theDatePropertyType = ep.getPropertyType( "mediaType" ); + final AttributeConverterTypeAdapter type = assertTyping( AttributeConverterTypeAdapter.class, theDatePropertyType ); + assertTyping( MediaTypeConverter.class, type.getAttributeConverter() ); + + try { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist( new Entity1( 1, "300", MediaType.VIDEO ) ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 1, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.find( Entity1.class, 1 ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 2, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete Entity1" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } + finally { + emf.close(); + } + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapElementConversionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapElementConversionTest.java index 8c4d0aa5c2f2..5bfc454da19c 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapElementConversionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapElementConversionTest.java @@ -47,6 +47,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -58,6 +59,7 @@ @TestForIssue( jiraKey = "HHH-8529" ) public class MapElementConversionTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testElementCollectionConversion() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapKeyConversionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapKeyConversionTest.java index 4261ab40956b..7a8d3327adca 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapKeyConversionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/MapKeyConversionTest.java @@ -45,6 +45,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -56,6 +57,7 @@ @TestForIssue( jiraKey = "HHH-8529" ) public class MapKeyConversionTest extends BaseUnitTestCase { @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testElementCollectionConversion() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/QueryTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/QueryTest.java index 5aebe30072d7..ffb5c046ef17 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/QueryTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/QueryTest.java @@ -34,6 +34,7 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -50,6 +51,7 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase { public static final float SALARY = 267.89f; @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testJpqlLiteral() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertAnnotationTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertAnnotationTest.java index f0397ab931df..6e69d36d3eac 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertAnnotationTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertAnnotationTest.java @@ -48,6 +48,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; @@ -61,6 +62,7 @@ public class SimpleConvertAnnotationTest extends BaseUnitTestCase { // test handling of an AttributeConverter explicitly named via a @Convert annotation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testSimpleConvertUsage() throws MalformedURLException { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertsAnnotationTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertsAnnotationTest.java index 4ea035de12a2..299861518715 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertsAnnotationTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleConvertsAnnotationTest.java @@ -48,6 +48,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; @@ -61,6 +62,7 @@ public class SimpleConvertsAnnotationTest extends BaseUnitTestCase { // test handling of an AttributeConverter explicitly named via a @Convert annotation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void testSimpleConvertUsage() throws MalformedURLException { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleEmbeddableOverriddenConverterTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleEmbeddableOverriddenConverterTest.java index ccd331ba14b7..24a75e6bf645 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleEmbeddableOverriddenConverterTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleEmbeddableOverriddenConverterTest.java @@ -23,19 +23,18 @@ */ package org.hibernate.jpa.test.convert; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import javax.persistence.Convert; import javax.persistence.Embeddable; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.EntityManagerFactory; import javax.persistence.Id; -import javax.persistence.MappedSuperclass; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.jpa.boot.spi.Bootstrap; import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; @@ -43,10 +42,9 @@ import org.hibernate.type.CompositeType; import org.hibernate.type.StringType; import org.hibernate.type.Type; - -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; @@ -60,6 +58,7 @@ public class SimpleEmbeddableOverriddenConverterTest extends BaseUnitTestCase { * Test outcome of annotations exclusively. */ @Test + @FailureExpectedWithNewMetamodel( message = "@Embeddables not automatically indexed by Jandex" ) public void testSimpleConvertOverrides() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleXmlOverriddenTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleXmlOverriddenTest.java index 96e8bc35ce77..1a09c3817335 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleXmlOverriddenTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/SimpleXmlOverriddenTest.java @@ -23,33 +23,29 @@ */ package org.hibernate.jpa.test.convert; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.EntityManagerFactory; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; - import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.jpa.boot.spi.Bootstrap; import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.type.StringType; import org.hibernate.type.Type; +import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; -import org.junit.Test; - -import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; -import static org.junit.Assert.fail; /** * Test simple application of Convert annotation via XML. @@ -57,12 +53,16 @@ * @author Steve Ebersole */ public class SimpleXmlOverriddenTest extends BaseUnitTestCase { + /** + * A baseline test, with an explicit @Convert annotation that should be in effect + */ @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) public void baseline() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override public List getManagedClassNames() { - return Arrays.asList( Super.class.getName(), Sub.class.getName() ); + return Arrays.asList( TheEntity.class.getName() ); } // No mapping file should mean that the converter is applied @@ -74,15 +74,11 @@ public List getManagedClassNames() { final SessionFactoryImplementor sfi = emf.unwrap( SessionFactoryImplementor.class ); try { - final EntityPersister ep = sfi.getEntityPersister( Sub.class.getName() ); + final EntityPersister ep = sfi.getEntityPersister( TheEntity.class.getName() ); Type type = ep.getPropertyType( "it" ); - try { - assertTyping( StringType.class, type ); - fail( "Expected AttributeConverter to be applied" ); - } - catch (AssertionError expected) { - } + AttributeConverterTypeAdapter adapter = assertTyping( AttributeConverterTypeAdapter.class, type ); + assertTyping( SillyStringConverter.class, adapter.getAttributeConverter() ); } finally { emf.close(); @@ -90,14 +86,14 @@ public List getManagedClassNames() { } /** - * Test outcome of applying overrides via orm.xml, specifically at the entity level + * Test outcome of applying overrides via orm.xml, specifically at the attribute level */ @Test - public void testDefinitionAtEntityLevel() { + public void testDefinitionAtAttributeLevel() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override public List getManagedClassNames() { - return Arrays.asList( Super.class.getName(), Sub.class.getName() ); + return Arrays.asList( TheEntity.class.getName() ); } @Override @@ -107,13 +103,11 @@ public List getMappingFileNames() { }; final Map settings = new HashMap(); -// settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); - EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); final SessionFactoryImplementor sfi = emf.unwrap( SessionFactoryImplementor.class ); try { - final EntityPersister ep = sfi.getEntityPersister( Sub.class.getName() ); + final EntityPersister ep = sfi.getEntityPersister( TheEntity.class.getName() ); Type type = ep.getPropertyType( "it" ); assertTyping( StringType.class, type ); @@ -127,11 +121,11 @@ public List getMappingFileNames() { * Test outcome of applying overrides via orm.xml, specifically at the entity level */ @Test - public void testDefinitionAtAttributeLevel() { + public void testDefinitionAtEntityLevel() { final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { @Override public List getManagedClassNames() { - return Arrays.asList( Super.class.getName(), Sub.class.getName() ); + return Arrays.asList( TheEntity2.class.getName() ); } @Override @@ -141,13 +135,11 @@ public List getMappingFileNames() { }; final Map settings = new HashMap(); -// settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); - EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); final SessionFactoryImplementor sfi = emf.unwrap( SessionFactoryImplementor.class ); try { - final EntityPersister ep = sfi.getEntityPersister( Sub.class.getName() ); + final EntityPersister ep = sfi.getEntityPersister( TheEntity2.class.getName() ); Type type = ep.getPropertyType( "it" ); assertTyping( StringType.class, type ); @@ -157,18 +149,19 @@ public List getMappingFileNames() { } } - @MappedSuperclass - public static class Super { + @Entity(name="TheEntity") + public static class TheEntity { @Id public Integer id; @Convert(converter = SillyStringConverter.class) public String it; } - @Entity(name = "Sub") - // the xml disabled conversion on the Sub#it attribute - // Essentially the same test as org.hibernate.jpa.test.convert.SimpleOverriddenConverterTest, but through XML - //@Convert( attributeName = "it", disableConversion = true ) - public static class Sub extends Super { + @Entity(name="TheEntity2") + @Convert( attributeName = "it", converter = SillyStringConverter.class ) + public static class TheEntity2 { + @Id + public Integer id; + public String it; } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/XmlWithExplicitConvertAnnotationsTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/XmlWithExplicitConvertAnnotationsTest.java new file mode 100644 index 000000000000..c72e69f94fb0 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/XmlWithExplicitConvertAnnotationsTest.java @@ -0,0 +1,162 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.convert; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.AttributeConverter; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; + +/** + * Jira HHH-8812 claims that explicit {@link javax.persistence.Convert} annotations are not processed when a orm.xml + * file is used - specifically that the mixed case is not handled properly. + * + * @author Steve Ebersole + */ +@TestForIssue( jiraKey = "HHH-8812" ) +public class XmlWithExplicitConvertAnnotationsTest extends BaseUnitTestCase { + + // NOTE : essentially the same exact test as ExplicitDateConvertersTest, but here we will mix annotations and xml + + static int callsToConverter = 0; + + public static class LongToDateConverter implements AttributeConverter { + @Override + public Long convertToDatabaseColumn(Date attribute) { + callsToConverter++; + return attribute.getTime(); + } + + @Override + public Date convertToEntityAttribute(Long dbData) { + callsToConverter++; + return new Date( dbData ); + } + } + + @Entity( name = "Entity1" ) + public static class Entity1 { + @Id + private Integer id; + private String name; + @Convert( converter = LongToDateConverter.class ) + private Date theDate; + + public Entity1() { + } + + public Entity1(Integer id, String name, Date theDate) { + this.id = id; + this.name = name; + this.theDate = theDate; + } + } + + public static class TestEntityListener { + @PrePersist + @PreUpdate + private void listen(Object entity) { + System.out.println( "@PrePersist @PreUpdate listener event fired" ); + } + } + + @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8932" ) + public void testSimpleConvertUsage() throws MalformedURLException { + final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { + @Override + public List getManagedClassNames() { + return Arrays.asList( Entity1.class.getName() ); + } + + @Override + public List getMappingFileNames() { + return Arrays.asList( "org/hibernate/jpa/test/convert/mixed.xml" ); + } + }; + + final Map settings = new HashMap(); + settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); + + EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); + final EntityPersister ep = emf.unwrap( SessionFactoryImplementor.class ).getEntityPersister( Entity1.class.getName() ); + final Type theDatePropertyType = ep.getPropertyType( "theDate" ); + final AttributeConverterTypeAdapter type = assertTyping( AttributeConverterTypeAdapter.class, theDatePropertyType ); + assertTyping( LongToDateConverter.class, type.getAttributeConverter() ); + + try { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist( new Entity1( 1, "1", new Date() ) ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 1, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.find( Entity1.class, 1 ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 2, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete Entity1" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } + finally { + emf.close(); + } + } + +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/Animal.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/Animal.java new file mode 100644 index 000000000000..c88776a3683c --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/Animal.java @@ -0,0 +1,54 @@ +package org.hibernate.jpa.test.criteria; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +/** + * Animal + * + */ +@Entity +@Table( name = "ANIMAL" ) +public class Animal { + private Long id; + private Animal mother; + private Animal father; + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne + public Animal getMother() { + return mother; + } + + public void setMother(Animal mother) { + this.mother = mother; + } + + @ManyToOne + public Animal getFather() { + return father; + } + + public void setFather(Animal father) { + this.father = father; + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/CriteriaCompilingTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/CriteriaCompilingTest.java index 1dfddc7fa722..b8130b02e2da 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/CriteriaCompilingTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/CriteriaCompilingTest.java @@ -36,10 +36,12 @@ import javax.persistence.criteria.Root; import javax.persistence.metamodel.EntityType; -import org.junit.Assert; -import org.junit.Test; - -import org.hibernate.dialect.DB2Dialect; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.jpa.test.callbacks.RemoteControl; +import org.hibernate.jpa.test.callbacks.Television; +import org.hibernate.jpa.test.callbacks.VideoSystem; +import org.hibernate.jpa.test.inheritance.Fruit; +import org.hibernate.jpa.test.inheritance.Strawberry; import org.hibernate.jpa.test.metamodel.Address; import org.hibernate.jpa.test.metamodel.Alias; import org.hibernate.jpa.test.metamodel.Country; @@ -52,15 +54,10 @@ import org.hibernate.jpa.test.metamodel.Product; import org.hibernate.jpa.test.metamodel.ShelfLife; import org.hibernate.jpa.test.metamodel.Spouse; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.jpa.test.callbacks.RemoteControl; -import org.hibernate.jpa.test.callbacks.Television; -import org.hibernate.jpa.test.callbacks.VideoSystem; -import org.hibernate.jpa.test.inheritance.Fruit; -import org.hibernate.jpa.test.inheritance.Strawberry; -import org.hibernate.testing.FailureExpected; -import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.junit.Assert; +import org.junit.Test; /** * @author Steve Ebersole @@ -194,7 +191,8 @@ public void testSimpleFetchCriteria() { } @Test - public void testSerialization() { + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8995" ) + public void testSerialization() throws Exception { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); @@ -212,24 +210,18 @@ public void testSerialization() { } @SuppressWarnings( {"unchecked"}) - private T serializeDeserialize(T object) { - T serializedObject = null; - try { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - ObjectOutput out = new ObjectOutputStream( stream ); - out.writeObject( object ); - out.close(); - byte[] serialized = stream.toByteArray(); - stream.close(); - ByteArrayInputStream byteIn = new ByteArrayInputStream( serialized ); - ObjectInputStream in = new ObjectInputStream( byteIn ); - serializedObject = (T) in.readObject(); - in.close(); - byteIn.close(); - } - catch (Exception e) { - Assert.fail( "Unable to serialize / deserialize the object: " + e.getMessage() ); - } + private T serializeDeserialize(T object) throws Exception { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream( stream ); + out.writeObject( object ); + out.close(); + byte[] serialized = stream.toByteArray(); + stream.close(); + ByteArrayInputStream byteIn = new ByteArrayInputStream( serialized ); + ObjectInputStream in = new ObjectInputStream( byteIn ); + T serializedObject = (T) in.readObject(); + in.close(); + byteIn.close(); return serializedObject; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/Human.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/Human.java new file mode 100644 index 000000000000..b81336591238 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/Human.java @@ -0,0 +1,12 @@ +package org.hibernate.jpa.test.criteria; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * Human + */ +@Entity +@Table(name = "HUMAN") +public class Human extends Animal { +} \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/QueryBuilderTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/QueryBuilderTest.java index d4200b4b2bad..cd8467abb266 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/QueryBuilderTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/QueryBuilderTest.java @@ -23,19 +23,22 @@ */ package org.hibernate.jpa.test.criteria; +import static org.junit.Assert.assertEquals; + import java.util.ArrayList; -import java.util.Collection; import java.util.List; + import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import javax.persistence.metamodel.EntityType; -import org.junit.Test; - +import org.hibernate.dialect.H2Dialect; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; import org.hibernate.jpa.criteria.predicate.ComparisonPredicate; +import org.hibernate.jpa.internal.metamodel.MetamodelImpl; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.metamodel.Address; import org.hibernate.jpa.test.metamodel.Alias; import org.hibernate.jpa.test.metamodel.Country; @@ -44,15 +47,14 @@ import org.hibernate.jpa.test.metamodel.Customer_; import org.hibernate.jpa.test.metamodel.Info; import org.hibernate.jpa.test.metamodel.LineItem; -import org.hibernate.jpa.internal.metamodel.MetamodelImpl; import org.hibernate.jpa.test.metamodel.Order; import org.hibernate.jpa.test.metamodel.Phone; import org.hibernate.jpa.test.metamodel.Product; import org.hibernate.jpa.test.metamodel.ShelfLife; import org.hibernate.jpa.test.metamodel.Spouse; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; /** * @author Steve Ebersole @@ -125,7 +127,7 @@ public void testEqualityComparisonEntityConversion() { Phone phone3 = new Phone( "3", "555", "0003", address ); Phone phone4 = new Phone( "4", "555", "0004" ); - Collection phones = new ArrayList( 3 ); + List phones = new ArrayList( 3 ); phones.add( phone1 ); phones.add( phone2 ); phones.add( phone3 ); @@ -214,6 +216,28 @@ public void testConstructor() { em.close(); } + @Test + @TestForIssue(jiraKey = "HHH-8699") + // For now, restrict to H2. Selecting w/ predicate functions cause issues for too many dialects. + @RequiresDialect(value = H2Dialect.class, jiraKey = "HHH-9092") + public void testMultiselectWithPredicates() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilderImpl cb = (CriteriaBuilderImpl) em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery( Customer.class ); + Root r = cq.from( Customer.class ); + cq.multiselect( + r.get( Customer_.id ), r.get( Customer_.name ), + cb.concat( "Hello ", r.get( Customer_.name ) ), cb.isNotNull( r.get( Customer_.age ) ) + ); + TypedQuery tq = em.createQuery( cq ); + tq.getResultList(); + + em.getTransaction().commit(); + em.close(); + } + @Test public void testDateTimeFunctions() { EntityManager em = getOrCreateEntityManager(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/TreatKeywordTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/TreatKeywordTest.java index b1033b5c16de..0e7dfcf8fce0 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/TreatKeywordTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/TreatKeywordTest.java @@ -23,20 +23,19 @@ */ package org.hibernate.jpa.test.criteria; -import javax.persistence.Entity; +import java.util.List; import javax.persistence.EntityManager; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.Table; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; +import javax.persistence.metamodel.EntityType; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.metamodel.Thing; import org.hibernate.jpa.test.metamodel.ThingWithQuantity; import org.hibernate.jpa.test.metamodel.ThingWithQuantity_; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.junit.Assert; import org.junit.Test; /** @@ -83,52 +82,53 @@ public void basicTest2() { em.close(); } - @Entity - @Table( name = "ANIMAL" ) - public static class Animal { - private Long id; - private Animal mother; - private Animal father; - - @Id - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @ManyToOne - public Animal getMother() { - return mother; - } - - public void setMother(Animal mother) { - this.mother = mother; - } - - @ManyToOne - public Animal getFather() { - return father; - } - - public void setFather(Animal father) { - this.father = father; - } - } + @Test + public void treatPathClassTest() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + Animal animal = new Animal(); + animal.setId(100L); + animal.setName("2"); + em.persist(animal); + Human human = new Human(); + human.setId(200L); + human.setName("2"); + em.persist(human); + em.getTransaction().commit(); - @Entity - @Table( name = "HUMAN" ) - public static class Human extends Animal { - private String name; + CriteriaBuilder builder = em.getCriteriaBuilder(); + CriteriaQuery criteria = builder.createQuery( String.class ); + Root root = criteria.from( Animal.class ); + EntityType Animal_ = em.getMetamodel().entity(Animal.class); + criteria.select(root.get(Animal_.getSingularAttribute("name", String.class))); - public String getName() { - return name; - } + criteria.where(builder.like(builder.treat(root, Human.class).get(org.hibernate.jpa.test.criteria.Human_.name), "2%")); + List animalList = em.createQuery( criteria ).getResultList(); + Assert.assertEquals("treat(Animal as Human) was ignored",1, animalList.size()); - public void setName(String name) { - this.name = name; - } + em.close(); } + + @Test + public void treatPathClassTestHqlControl() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + Animal animal = new Animal(); + animal.setId(100L); + animal.setName("2"); + em.persist(animal); + Human human = new Human(); + human.setId(200L); + human.setName("2"); + em.persist(human); + em.getTransaction().commit(); + + List animalList = em.createQuery( "select a.name from Animal a where treat (a as Human).name like '2%'" ).getResultList(); + Assert.assertEquals("treat(Animal as Human) was ignored",1, animalList.size()); + + em.close(); + } + + + } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/BasicCriteriaUsageTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/BasicCriteriaUsageTest.java index 45fa02ce854f..1d812466bd82 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/BasicCriteriaUsageTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/BasicCriteriaUsageTest.java @@ -126,4 +126,59 @@ public void testFunctionCriteria() { em.getTransaction().commit(); em.close(); } + + @Test + @TestForIssue( jiraKey = "HHH-8914" ) + public void testDoubleNegation() { + Wall wall1 = new Wall(); + wall1.setColor( "yellow" ); + Wall wall2 = new Wall(); + wall2.setColor( null ); + + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + em.persist( wall1 ); + em.persist( wall2 ); + em.getTransaction().commit(); + em.clear(); + + em.getTransaction().begin(); + + // Although the examples are simplified and the usages appear pointless, + // double negatives can occur in some dynamic applications (regardless + // if it results from bad design or not). Ensure we handle them as expected. + + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery( Wall.class ); + Root root = query.from( Wall.class ); + query.select( root ).where( + cb.not( + cb.isNotNull( root.get( "color" ) ) ) ); + Wall result = em.createQuery( query ).getSingleResult(); + assertNotNull( result ); + assertEquals( null, result.getColor() ); + + query = cb.createQuery( Wall.class ); + root = query.from( Wall.class ); + query.select( root ).where( + cb.not( + cb.not( + cb.isNull( root.get( "color" ) ) ) ) ); + result = em.createQuery( query ).getSingleResult(); + assertNotNull( result ); + assertEquals( null, result.getColor() ); + + query = cb.createQuery( Wall.class ); + root = query.from( Wall.class ); + query.select( root ).where( + cb.not( + cb.not( + cb.isNotNull( root.get( "color" ) ) ) ) ); + result = em.createQuery( query ).getSingleResult(); + assertNotNull( result ); + assertEquals( "yellow", result.getColor() ); + + em.getTransaction().commit(); + em.close(); + } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/ListIndexTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/ListIndexTest.java new file mode 100644 index 000000000000..12f8f78c3429 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/basic/ListIndexTest.java @@ -0,0 +1,99 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.criteria.basic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.ListJoin; +import javax.persistence.criteria.Root; + +import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest; +import org.hibernate.jpa.test.metamodel.Address; +import org.hibernate.jpa.test.metamodel.Address_; +import org.hibernate.jpa.test.metamodel.Phone; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +/** + * Tests usage of {@link ListJoin#index()} + * + * @author Brett Meyer + */ +public class ListIndexTest extends AbstractMetamodelSpecificTest { + + @Test + @TestForIssue(jiraKey = "HHH-8404") + public void testListIndex() { + EntityManager em = getOrCreateEntityManager(); + + em.getTransaction().begin(); + + Address address1 = new Address(); + address1.setId( "a1" ); + Phone phone1 = new Phone(); + phone1.setId( "p1" ); + phone1.setAddress( address1 ); + Phone phone2 = new Phone(); + phone2.setId( "p2" ); + + phone2.setAddress( address1 ); + address1.getPhones().add( phone1 ); + address1.getPhones().add( phone2 ); + + Address address2 = new Address(); + address2.setId( "a2" ); + Phone phone3 = new Phone(); + phone3.setId( "p3" ); + + phone3.setAddress( address2 ); + address2.getPhones().add( phone3 ); + + em.persist( phone1 ); + em.persist( phone2 ); + em.persist( phone3 ); + em.persist( address1 ); + em.persist( address2 ); + em.getTransaction().commit(); + em.clear(); + + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery
    criteria = cb.createQuery( Address.class ); + Root
    addressRoot = criteria.from( Address.class ); + ListJoin phones = addressRoot.join( Address_.phones ); + criteria.where( cb.gt( phones.index(), 0 ) ); + List
    results = em.createQuery( criteria ).getResultList(); + + assertNotNull( results ); + // Ensure that the "index(phones) > 0" condition was included on the inner join, meaning only address1 + // (> 1 phone) was returned. + assertEquals( 1, results.size() ); + assertEquals( address1.getId(), results.get( 0 ).getId() ); + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/components/ComponentCriteriaTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/components/ComponentCriteriaTest.java index 791ce87ad7b2..e1650910e644 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/components/ComponentCriteriaTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/components/ComponentCriteriaTest.java @@ -43,7 +43,7 @@ public class ComponentCriteriaTest extends BaseEntityManagerFunctionalTestCase { @Override public Class[] getAnnotatedClasses() { - return new Class[] { Client.class }; + return new Class[] { Client.class, Name.class }; } @Test diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/idclass/IdClassPredicateTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/idclass/IdClassPredicateTest.java index 40dd547c286b..17ad0e23419a 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/idclass/IdClassPredicateTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/idclass/IdClassPredicateTest.java @@ -32,16 +32,18 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import junit.framework.Assert; +import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.After; import org.junit.Before; import org.junit.Test; - -import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest; +import junit.framework.Assert; /** * @author Erich Heard */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055" ) public class IdClassPredicateTest extends AbstractMetamodelSpecificTest { @Override diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/simplecase/BasicSimpleCaseTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/simplecase/BasicSimpleCaseTest.java new file mode 100644 index 000000000000..5a40eed3e9ac --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/simplecase/BasicSimpleCaseTest.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.criteria.simplecase; + +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Root; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Test; + +import static javax.persistence.criteria.CriteriaBuilder.SimpleCase; + +/** + * Mote that these are simply performing syntax checking (can the criteria query + * be properly compiled and executed) + * + * @author Steve Ebersole + */ +public class BasicSimpleCaseTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {Customer.class}; + } + + @Test + public void testCaseInOrderBy() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder builder = em.getCriteriaBuilder(); + + CriteriaQuery query = builder.createQuery( Customer.class ); + Root root = query.from( Customer.class ); + query.select( root ); + + Path emailPath = root.get( "email" ); + SimpleCase orderCase = builder.selectCase( emailPath ); + orderCase = orderCase.when( "test@test.com", 1 ); + orderCase = orderCase.when( "test2@test.com", 2 ); + + query.orderBy( builder.asc( orderCase.otherwise( 0 ) ) ); + + em.createQuery( query ); + + } + + @Test + public void testCaseInOrderBy2() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder builder = em.getCriteriaBuilder(); + + CriteriaQuery query = builder.createQuery( Customer.class ); + Root root = query.from( Customer.class ); + query.select( root ); + + Path emailPath = root.get( "email" ); + SimpleCase orderCase = builder.selectCase( emailPath ); + orderCase = orderCase.when( "test@test.com", "a" ); + orderCase = orderCase.when( "test2@test.com", "b" ); + + query.orderBy( builder.asc( orderCase.otherwise( "c" ) ) ); + + em.createQuery( query ); + + } + + @Entity(name = "Customer") + @Table(name = "customer") + public static class Customer { + private Integer id; + private String email; + + @Id + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/ConfigurationObjectSettingTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/ConfigurationObjectSettingTest.java index 5442b34ac54c..9938aef06297 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/ConfigurationObjectSettingTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/ConfigurationObjectSettingTest.java @@ -137,21 +137,4 @@ public ValidationMode getValidationMode() { assertEquals( ValidationMode.NONE, builder.getConfigurationValues().get( AvailableSettings.VALIDATION_MODE ) ); } } - - @Test - public void testContainerBootstrapValidationFactory() { - final Object token = new Object(); - PersistenceUnitInfoAdapter adapter = new PersistenceUnitInfoAdapter(); - try { - Bootstrap.getEntityManagerFactoryBuilder( - adapter, - Collections.singletonMap( AvailableSettings.VALIDATION_FACTORY, token ) - ); - fail( "Was expecting error as token did not implement ValidatorFactory" ); - } - catch ( HibernateException e ) { - // probably the condition we want but unfortunately the exception is not specific - // and the pertinent info is in a cause - } - } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java index 787ba76fbf9a..b0002ad44d19 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java @@ -55,8 +55,8 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; import org.hibernate.metadata.ClassMetadata; -import org.hibernate.metamodel.binding.EntityBinding; -import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.internal.PersisterClassResolverInitiator; @@ -118,14 +118,13 @@ public Class getCollectionPersisterClass(PluralAt } public static class GoofyProvider implements EntityPersister { - - @SuppressWarnings( {"UnusedParameters"}) + @SuppressWarnings({"UnusedParameters", "UnusedDeclaration"}) public GoofyProvider( - org.hibernate.mapping.PersistentClass persistentClass, - org.hibernate.cache.spi.access.EntityRegionAccessStrategy strategy, - NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - SessionFactoryImplementor sf, - Mapping mapping) { + org.hibernate.metamodel.spi.binding.EntityBinding entityBinding, + org.hibernate.cache.spi.access.EntityRegionAccessStrategy entityRegionAccessStrategy, + org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, + org.hibernate.engine.spi.SessionFactoryImplementor sf, + org.hibernate.engine.spi.Mapping mapping) { throw new GoofyException(); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/Race.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/Race.java index 26b99d842ac2..afef791457ee 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/Race.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/Race.java @@ -15,9 +15,13 @@ */ @Entity public class Race { - @Id @GeneratedValue public Integer id; - @OrderColumn( name="index_" ) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @org.hibernate.annotations.Cascade( { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN }) + @Id @GeneratedValue + public Integer id; + + @OrderColumn( name="index_" ) + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + @org.hibernate.annotations.Cascade( { org.hibernate.annotations.CascadeType.ALL }) public List competitors = new ArrayList(); + public String name; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Company.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Company.java new file mode 100644 index 000000000000..3ab98c0c9b7e --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Company.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.jpa.test.graphs; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; + + +/** + * @author Brett Meyer + */ +@Entity +public class Company { + @Id @GeneratedValue + public long id; + + @OneToMany + public Set employees = new HashSet(); + + @OneToOne(fetch = FetchType.LAZY) + public Location location; + + @ElementCollection + public Set markets = new HashSet(); + + @ElementCollection(fetch = FetchType.EAGER) + public Set phoneNumbers = new HashSet(); +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Employee.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Employee.java new file mode 100644 index 000000000000..65929d36a321 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Employee.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.jpa.test.graphs; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.ManyToMany; + + +/** + * @author Brett Meyer + */ +@Entity +@Inheritance( strategy = InheritanceType.TABLE_PER_CLASS ) +public class Employee { + @Id @GeneratedValue + public long id; + + @ManyToMany + public Set managers = new HashSet(); + + @ManyToMany + public Set friends = new HashSet(); +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphLoadPlanBuilderTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphLoadPlanBuilderTest.java index 595ee8c47448..0e8097786e75 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphLoadPlanBuilderTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphLoadPlanBuilderTest.java @@ -63,7 +63,7 @@ public class EntityGraphLoadPlanBuilderTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Cat.class, Person.class, Country.class, Dog.class, ExpressCompany.class }; + return new Class[] { Cat.class, Person.class, Country.class, Dog.class, ExpressCompany.class, Address.class }; } @Entity diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphTest.java new file mode 100644 index 000000000000..a3161994e675 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphTest.java @@ -0,0 +1,265 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.graphs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.HashSet; + +import javax.persistence.Entity; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Subgraph; + +import org.hibernate.Hibernate; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +/** + * @author Christian Bauer + * @author Brett Meyer + */ +public class EntityGraphTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Foo.class, Bar.class, Baz.class, + Company.class, Employee.class, Manager.class, Location.class }; + } + + @Test + @TestForIssue(jiraKey = "HHH-8857") + public void loadMultipleAssociations() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + Bar bar = new Bar(); + em.persist( bar ); + + Baz baz = new Baz(); + em.persist( baz ); + + Foo foo = new Foo(); + foo.bar = bar; + foo.baz = baz; + em.persist( foo ); + + em.getTransaction().commit(); + em.clear(); + + em.getTransaction().begin(); + + EntityGraph fooGraph = em.createEntityGraph( Foo.class ); + fooGraph.addAttributeNodes( "bar", "baz" ); + + Map properties = new HashMap(); + properties.put( "javax.persistence.loadgraph", fooGraph ); + + Foo result = em.find( Foo.class, foo.id, properties ); + + assertTrue( Hibernate.isInitialized( result ) ); + assertTrue( Hibernate.isInitialized( result.bar ) ); + assertTrue( Hibernate.isInitialized( result.baz ) ); + + em.getTransaction().commit(); + em.close(); + } + + @Test + public void loadCollection() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + Bar bar = new Bar(); + em.persist( bar ); + + Foo foo = new Foo(); + foo.bar = bar; + bar.foos.add(foo); + em.persist( foo ); + + em.getTransaction().commit(); + em.clear(); + + em.getTransaction().begin(); + + EntityGraph barGraph = em.createEntityGraph( Bar.class ); + barGraph.addAttributeNodes("foos"); + + Map properties = new HashMap(); + properties.put( "javax.persistence.loadgraph", barGraph); + + Bar result = em.find( Bar.class, bar.id, properties ); + + assertTrue( Hibernate.isInitialized( result ) ); + assertTrue( Hibernate.isInitialized( result.foos ) ); + + em.getTransaction().commit(); + em.close(); + } + + @Test + public void loadInverseCollection() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + Bar bar = new Bar(); + em.persist( bar ); + Baz baz = new Baz(); + em.persist( baz ); + + Foo foo = new Foo(); + foo.bar = bar; + foo.baz = baz; + bar.foos.add(foo); + baz.foos.add(foo); + em.persist( foo ); + + em.getTransaction().commit(); + em.clear(); + + em.getTransaction().begin(); + + EntityGraph fooGraph = em.createEntityGraph( Foo.class ); + fooGraph.addAttributeNodes("bar"); + fooGraph.addAttributeNodes("baz"); + Subgraph barGraph = fooGraph.addSubgraph("bar", Bar.class); + barGraph.addAttributeNodes("foos"); + + Map properties = new HashMap(); + properties.put( "javax.persistence.loadgraph", fooGraph ); + + Foo result = em.find( Foo.class, foo.id, properties ); + + assertTrue( Hibernate.isInitialized( result ) ); + assertTrue( Hibernate.isInitialized( result.bar ) ); + assertTrue( Hibernate.isInitialized( result.bar.foos) ); + assertTrue( Hibernate.isInitialized( result.baz ) ); + // sanity check -- ensure the only bi-directional fetch was the one identified by the graph + assertFalse( Hibernate.isInitialized( result.baz.foos) ); + + em.getTransaction().commit(); + em.close(); + } + + /** + * JPA 2.1 spec: "Add a node to the graph that corresponds to a managed type with inheritance. This allows for + * multiple subclass subgraphs to be defined for this node of the entity graph. Subclass subgraphs will + * automatically include the specified attributes of superclass subgraphs." + */ + @Test + @TestForIssue(jiraKey = "HHH-8640") + public void inheritanceTest() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + Manager manager = new Manager(); + em.persist( manager ); + Employee employee = new Employee(); + employee.friends.add( manager ); + employee.managers.add( manager ); + em.persist( employee ); + Company company = new Company(); + company.employees.add( employee ); + company.employees.add( manager ); + em.persist( company ); + + em.getTransaction().commit(); + em.clear(); + + em.getTransaction().begin(); + + EntityGraph entityGraph = em.createEntityGraph( Company.class ); + Subgraph subgraph = entityGraph.addSubgraph( "employees" ); + subgraph.addAttributeNodes( "managers" ); + subgraph.addAttributeNodes( "friends" ); + Subgraph subSubgraph = subgraph.addSubgraph( "managers", Manager.class ); + subSubgraph.addAttributeNodes( "managers" ); + subSubgraph.addAttributeNodes( "friends" ); + + Map properties = new HashMap(); + properties.put( "javax.persistence.loadgraph", entityGraph ); + + Company result = em.find( Company.class, company.id, properties ); + + assertTrue( Hibernate.isInitialized( result ) ); + assertTrue( Hibernate.isInitialized( result.employees ) ); + assertEquals( result.employees.size(), 2 ); + for (Employee resultEmployee : result.employees) { + assertTrue( Hibernate.isInitialized( resultEmployee.managers ) ); + assertTrue( Hibernate.isInitialized( resultEmployee.friends ) ); + } + + em.getTransaction().commit(); + em.close(); + } + + @Entity + public static class Foo { + + @Id + @GeneratedValue + public Integer id; + + @ManyToOne(fetch = FetchType.LAZY) + public Bar bar; + + @ManyToOne(fetch = FetchType.LAZY) + public Baz baz; + } + + @Entity + public static class Bar { + + @Id + @GeneratedValue + public Integer id; + + @OneToMany(mappedBy = "bar") + public Set foos = new HashSet(); + } + + @Entity + public static class Baz { + + @Id + @GeneratedValue + public Integer id; + + @OneToMany(mappedBy = "bar") + public Set foos = new HashSet(); + + } + +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Location.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Location.java new file mode 100644 index 000000000000..4543e605b232 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Location.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.jpa.test.graphs; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author Brett Meyer + */ +@Entity +public class Location { + @Id @GeneratedValue + public long id; + + public String address; + + public int zip; +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Manager.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Manager.java new file mode 100644 index 000000000000..4b8fc3c28413 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Manager.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.jpa.test.graphs; + +import javax.persistence.Entity; + + +/** + * @author Brett Meyer + */ +@Entity +public class Manager extends Employee { + +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Market.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Market.java new file mode 100644 index 000000000000..7073ee35e82e --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/Market.java @@ -0,0 +1,29 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.jpa.test.graphs; + + +/** + * @author Brett Meyer + */ +public enum Market { + SERVICES, TECHNOLOGY, INDUSTRIAL; +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java index ece15e61d451..e590bc8774c3 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java @@ -27,6 +27,7 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; import static junit.framework.Assert.assertNotNull; @@ -36,6 +37,7 @@ */ public abstract class AbstractNamedEntityGraphTest extends BaseEntityManagerFunctionalTestCase { @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8933" ) public void testIt() { EntityGraph graph = getOrCreateEntityManager().getEntityGraph( "Person" ); assertNotNull( graph ); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java index 9e6b3fb4ad3d..fe152322af0b 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java @@ -33,6 +33,8 @@ import java.util.List; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + import static junit.framework.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -46,6 +48,7 @@ protected Class[] getAnnotatedClasses() { } @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8933" ) public void testIt() { EntityGraph graph = getOrCreateEntityManager().getEntityGraph( "abc" ); assertNotNull( graph ); @@ -54,6 +57,7 @@ public void testIt() { } @Test + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-8933" ) public void testAttributeNodesAreAvailable() { EntityManager em = getOrCreateEntityManager(); EntityGraph graph = em.getEntityGraph( "name_salary_graph" ); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/queryhint/QueryHintEntityGraphTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/queryhint/QueryHintEntityGraphTest.java index fbd368ad9582..8fba61920b61 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/queryhint/QueryHintEntityGraphTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/queryhint/QueryHintEntityGraphTest.java @@ -23,27 +23,21 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.io.Serializable; -import java.util.HashSet; import java.util.Iterator; -import java.util.Set; -import javax.persistence.ElementCollection; -import javax.persistence.Entity; import javax.persistence.EntityGraph; import javax.persistence.EntityManager; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; import javax.persistence.Query; import javax.persistence.Subgraph; import org.hibernate.Hibernate; import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.jpa.test.graphs.Company; +import org.hibernate.jpa.test.graphs.Employee; +import org.hibernate.jpa.test.graphs.Location; +import org.hibernate.jpa.test.graphs.Manager; +import org.hibernate.jpa.test.graphs.Market; import org.junit.Before; import org.junit.Test; @@ -81,10 +75,13 @@ public void testLoadGraph() { entityManager = getOrCreateEntityManager(); entityManager.getTransaction().begin(); - Subgraph subgraph1 = entityGraph.addSubgraph( "employees" ); - subgraph1.addAttributeNodes( "managers" ); - Subgraph subgraph2 = subgraph1.addSubgraph( "managers" ); - subgraph2.addAttributeNodes( "managers" ); + Subgraph subgraph = entityGraph.addSubgraph( "employees" ); + subgraph.addAttributeNodes( "managers" ); + subgraph.addAttributeNodes( "friends" ); + Subgraph subSubgraph = subgraph.addSubgraph( "managers", Manager.class ); + subSubgraph.addAttributeNodes( "managers" ); + subSubgraph.addAttributeNodes( "friends" ); + query = entityManager.createQuery( "from " + Company.class.getName() ); query.setHint( QueryHints.HINT_LOADGRAPH, entityGraph ); company = (Company) query.getSingleResult(); @@ -104,10 +101,14 @@ public void testLoadGraph() { while (employeeItr.hasNext()) { Employee employee = employeeItr.next(); assertTrue( Hibernate.isInitialized( employee.managers ) ); - Iterator managerItr = employee.managers.iterator(); + assertTrue( Hibernate.isInitialized( employee.friends ) ); + // test 1 more level + Iterator managerItr = employee.managers.iterator(); while (managerItr.hasNext()) { foundManager = true; - assertTrue( Hibernate.isInitialized( managerItr.next().managers ) ); + Manager manager = managerItr.next(); + assertTrue( Hibernate.isInitialized( manager.managers ) ); + assertTrue( Hibernate.isInitialized( manager.friends ) ); } } assertTrue(foundManager); @@ -144,16 +145,14 @@ public void createData() { EntityManager entityManager = getOrCreateEntityManager(); entityManager.getTransaction().begin(); - Employee manager1 = new Employee(); + Manager manager1 = new Manager(); entityManager.persist( manager1 ); - Employee manager2 = new Employee(); - manager2.managers = new HashSet(); + Manager manager2 = new Manager(); manager2.managers.add( manager1 ); entityManager.persist( manager2 ); Employee employee = new Employee(); - employee.managers = new HashSet(); employee.managers.add( manager1 ); entityManager.persist( employee ); @@ -163,15 +162,12 @@ public void createData() { entityManager.persist( location ); Company company = new Company(); - company.employees = new HashSet(); company.employees.add( employee ); company.employees.add( manager1 ); company.employees.add( manager2 ); company.location = location; - company.markets = new HashSet(); company.markets.add( Market.SERVICES ); company.markets.add( Market.TECHNOLOGY ); - company.phoneNumbers = new HashSet(); company.phoneNumbers.add( "012-345-6789" ); company.phoneNumbers.add( "987-654-3210" ); entityManager.persist( company ); @@ -182,49 +178,6 @@ public void createData() { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Company.class, Employee.class, Location.class }; - } - - @Entity - private static class Company implements Serializable { - @Id @GeneratedValue - public long id; - - @OneToMany - public Set employees; - - @OneToOne(fetch = FetchType.LAZY) - public Location location; - - @ElementCollection - public Set markets; - - @ElementCollection(fetch = FetchType.EAGER) - public Set phoneNumbers; - } - - @Entity - private static class Employee { - @Id @GeneratedValue - public long id; - - @ManyToMany - public Set managers; - } - - @Entity - private static class Location { - public Location() { } - - @Id @GeneratedValue - public long id; - - public String address; - - public int zip; - } - - private static enum Market { - SERVICES, TECHNOLOGY, INDUSTRIAL; + return new Class[] { Company.class, Employee.class, Manager.class, Location.class }; } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/jee/OrmVersionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/jee/OrmVersionTest.java index 12ef14946575..474ed0c762b4 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/jee/OrmVersionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/jee/OrmVersionTest.java @@ -45,12 +45,14 @@ import org.hibernate.jpa.test.pack.defaultpar.Lighter; import org.hibernate.jpa.test.pack.defaultpar_1_0.Lighter1; +import org.hibernate.testing.junit4.BaseUnitTestCase; + /** * "smoke" tests for JEE bootstrapping of HEM via a {@link PersistenceUnitInfo} * * @author Steve Ebersole */ -public class OrmVersionTest { +public class OrmVersionTest extends BaseUnitTestCase { @Test public void testOrm1() { PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "orm1-test", "1.0" ) @@ -58,7 +60,9 @@ public void testOrm1() { HibernatePersistenceProvider hp = new HibernatePersistenceProvider(); EntityManagerFactory emf = hp.createContainerEntityManagerFactory( pui, Collections.EMPTY_MAP ); emf.getMetamodel().entity( Lighter1.class ); // exception if not entity + emf.close(); } + @Test public void testOrm2() { PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "orm2-test", "2.0" ) @@ -66,7 +70,9 @@ public void testOrm2() { HibernatePersistenceProvider hp = new HibernatePersistenceProvider(); EntityManagerFactory emf = hp.createContainerEntityManagerFactory( pui, Collections.EMPTY_MAP ); emf.getMetamodel().entity( Lighter.class ); // exception if not entity + emf.close(); } + @Test public void testInvalidOrm1() { PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "invalid-orm1-test", "1.0" ) @@ -111,13 +117,13 @@ public List getMappingFileNames() { return mappingFileNames; } - private final List managedClassNames = new ArrayList(); - private PersistenceUnitInfoImpl addMappingFileName(String mappingFileName) { mappingFileNames.add( mappingFileName ); return this; } + private final List managedClassNames = new ArrayList(); + public List getManagedClassNames() { return managedClassNames; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/lock/QueryLockingTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/lock/QueryLockingTest.java old mode 100644 new mode 100755 index 18e2d5d40df5..0b60aa6d5ea8 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/lock/QueryLockingTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/lock/QueryLockingTest.java @@ -23,8 +23,16 @@ */ package org.hibernate.jpa.test.lock; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.List; import java.util.Map; + import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.Id; @@ -32,21 +40,14 @@ import javax.persistence.Query; import javax.persistence.Table; -import org.junit.Test; - import org.hibernate.LockMode; +import org.hibernate.internal.SessionImpl; import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.internal.QueryImpl; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.internal.SessionImpl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; /** * @author Steve Ebersole @@ -89,6 +90,42 @@ public void testOverallLockMode() { em.close(); } + @Test + @TestForIssue( jiraKey = "HHH-8756" ) + public void testNoneLockModeForNonSelectQueryAllowed() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + QueryImpl jpaQuery = em.createQuery( "delete from Lockable l" ).unwrap( QueryImpl.class ); + + org.hibernate.internal.QueryImpl hqlQuery = (org.hibernate.internal.QueryImpl) jpaQuery.getHibernateQuery(); + assertEquals( LockMode.NONE, hqlQuery.getLockOptions().getLockMode() ); + + jpaQuery.setLockMode( LockModeType.NONE ); + + em.getTransaction().commit(); + em.clear(); + + // ensure other modes still throw the exception + em.getTransaction().begin(); + jpaQuery = em.createQuery( "delete from Lockable l" ).unwrap( QueryImpl.class ); + + hqlQuery = (org.hibernate.internal.QueryImpl) jpaQuery.getHibernateQuery(); + assertEquals( LockMode.NONE, hqlQuery.getLockOptions().getLockMode() ); + + try { + // Throws IllegalStateException + jpaQuery.setLockMode( LockModeType.PESSIMISTIC_WRITE ); + fail( "IllegalStateException should have been thrown." ); + } + catch (IllegalStateException e) { + // expected + } + finally { + em.getTransaction().rollback(); + em.close(); + } + } + @Test public void testNativeSql() { EntityManager em = getOrCreateEntityManager(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java index f700de9e3626..a7acd0dca723 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java @@ -23,7 +23,6 @@ */ package org.hibernate.jpa.test.metadata; -import java.util.Collections; import java.util.Set; import javax.persistence.EntityManagerFactory; import javax.persistence.metamodel.Attribute; @@ -40,13 +39,15 @@ import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.Type; -import org.junit.Test; - -import org.hibernate.cfg.Configuration; -import org.hibernate.jpa.internal.metamodel.MetamodelImpl; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.mapping.MappedSuperclass; +import org.hibernate.jpa.internal.metamodel.builder.JpaMetaModelPopulationSetting; +import org.hibernate.jpa.internal.metamodel.builder.MetamodelBuilder; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -59,6 +60,7 @@ /** * @author Emmanuel Bernard */ +@FailureExpectedWithNewMetamodel( jiraKey="HHH-8935" ) public class MetadataTest extends BaseEntityManagerFunctionalTestCase { @Test public void testBaseOfService() throws Exception { @@ -105,12 +107,13 @@ private void checkNonExistentAttributeAccess(ManagedType managedType) { @Test @SuppressWarnings({ "unchecked" }) public void testBuildingMetamodelWithParameterizedCollection() { - Configuration cfg = new Configuration( ); -// configure( cfg ); - cfg.addAnnotatedClass( WithGenericCollection.class ); - cfg.buildMappings(); - SessionFactoryImplementor sfi = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry() ); - MetamodelImpl.buildMetamodel( cfg.getClassMappings(), Collections.emptySet(), sfi, true ); + MetadataSources sources = new MetadataSources(); + sources.addAnnotatedClass( WithGenericCollection.class ); + Metadata metadata = sources.buildMetadata( serviceRegistry() ); + SessionFactoryImplementor sfi = (SessionFactoryImplementor) metadata.buildSessionFactory(); + + MetamodelBuilder.oneShot( sfi, metadata, JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED ); + sfi.close(); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/StaticMetadataTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/StaticMetadataTest.java index bc4260833966..00a415e16c6b 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/StaticMetadataTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metadata/StaticMetadataTest.java @@ -34,6 +34,8 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -42,6 +44,7 @@ /** * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel( jiraKey="HHH-8935" ) public class StaticMetadataTest extends BaseEntityManagerFunctionalTestCase { @Test public void testInjections() throws Exception { diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/attribute/MappedSuperclassWithAttributesTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/attribute/MappedSuperclassWithAttributesTest.java index d10aea068647..adff6091fbd2 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/attribute/MappedSuperclassWithAttributesTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/attribute/MappedSuperclassWithAttributesTest.java @@ -23,18 +23,15 @@ */ package org.hibernate.jpa.test.metagen.mappedsuperclass.attribute; -import javax.persistence.EntityManagerFactory; import java.util.Arrays; +import javax.persistence.EntityManagerFactory; -import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; -import org.hibernate.jpa.test.metagen.mappedsuperclass.attribute.AbstractNameable_; -import org.hibernate.jpa.test.metagen.mappedsuperclass.attribute.Product_; import org.hibernate.jpa.AvailableSettings; - -import org.junit.Test; +import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertNotNull; @@ -45,6 +42,10 @@ public class MappedSuperclassWithAttributesTest extends BaseUnitTestCase { @Test public void testStaticMetamodel() { + + // spent too much time digging into this. problem is ultimately that metamodel binding + // is not handling MappedSuperclass well + EntityManagerFactory emf = TestingEntityManagerFactoryGenerator.generateEntityManagerFactory( AvailableSettings.LOADED_CLASSES, Arrays.asList( Product.class ) diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embedded/MappedSuperclassWithEmbeddedTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embedded/MappedSuperclassWithEmbeddedTest.java index 1cd2b2bbbea7..736c64f77331 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embedded/MappedSuperclassWithEmbeddedTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embedded/MappedSuperclassWithEmbeddedTest.java @@ -23,16 +23,15 @@ */ package org.hibernate.jpa.test.metagen.mappedsuperclass.embedded; -import javax.persistence.EntityManagerFactory; import java.util.Arrays; +import javax.persistence.EntityManagerFactory; -import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; import org.hibernate.jpa.AvailableSettings; - -import org.junit.Test; +import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertNotNull; @@ -43,9 +42,13 @@ public class MappedSuperclassWithEmbeddedTest extends BaseUnitTestCase { @Test @TestForIssue( jiraKey = "HHH-5024" ) public void testStaticMetamodel() { + + // spent too much time digging into this. problem is ultimately that metamodel binding + // is not handling MappedSuperclass well + EntityManagerFactory emf = TestingEntityManagerFactoryGenerator.generateEntityManagerFactory( AvailableSettings.LOADED_CLASSES, - Arrays.asList( Company.class ) + Arrays.asList( Company.class, Address.class ) ); assertNotNull( "'Company_.id' should not be null)", Company_.id ); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embeddedid/MappedSuperclassWithEmbeddedIdTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embeddedid/MappedSuperclassWithEmbeddedIdTest.java index 399b25ed14e3..b106f44d4049 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embeddedid/MappedSuperclassWithEmbeddedIdTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/embeddedid/MappedSuperclassWithEmbeddedIdTest.java @@ -23,16 +23,15 @@ */ package org.hibernate.jpa.test.metagen.mappedsuperclass.embeddedid; -import javax.persistence.EntityManagerFactory; import java.util.Arrays; +import javax.persistence.EntityManagerFactory; -import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; import org.hibernate.jpa.AvailableSettings; - -import org.junit.Test; +import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertNotNull; @@ -45,7 +44,7 @@ public class MappedSuperclassWithEmbeddedIdTest extends BaseUnitTestCase { public void testStaticMetamodel() { EntityManagerFactory emf = TestingEntityManagerFactoryGenerator.generateEntityManagerFactory( AvailableSettings.LOADED_CLASSES, - Arrays.asList( Product.class ) + Arrays.asList( AbstractProduct.class, ProductId.class, Product.class ) ); assertNotNull( "'Product_.description' should not be null)", Product_.description ); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/idclass/MappedSuperclassWithEntityWithIdClassTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/idclass/MappedSuperclassWithEntityWithIdClassTest.java index 47bffab5e9ed..633acb27cbb5 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/idclass/MappedSuperclassWithEntityWithIdClassTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metagen/mappedsuperclass/idclass/MappedSuperclassWithEntityWithIdClassTest.java @@ -23,16 +23,16 @@ */ package org.hibernate.jpa.test.metagen.mappedsuperclass.idclass; -import javax.persistence.EntityManagerFactory; import java.util.Arrays; +import javax.persistence.EntityManagerFactory; -import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; import org.hibernate.jpa.AvailableSettings; +import org.hibernate.jpa.test.TestingEntityManagerFactoryGenerator; -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; import static org.junit.Assert.assertNotNull; @@ -40,13 +40,14 @@ * @author Alexis Bataille * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055" ) public class MappedSuperclassWithEntityWithIdClassTest extends BaseUnitTestCase { @Test @TestForIssue( jiraKey = "HHH-5024" ) public void testStaticMetamodel() { EntityManagerFactory emf = TestingEntityManagerFactoryGenerator.generateEntityManagerFactory( AvailableSettings.LOADED_CLASSES, - Arrays.asList( ProductAttribute.class ) + Arrays.asList( ProductAttribute.class, ProductAttributeId.class ) ); assertNotNull( "'ProductAttribute_.value' should not be null)", ProductAttribute_.value ); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Address.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Address.java index 0df6dae18d58..ce9799f02a7c 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Address.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Address.java @@ -22,12 +22,14 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.jpa.test.metamodel; -import java.util.Collection; +import java.util.List; + import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; import javax.persistence.Table; /** @@ -43,7 +45,7 @@ public class Address implements java.io.Serializable { private String city; private String state; private String zip; - private Collection phones = new java.util.ArrayList(); + private List phones = new java.util.ArrayList(); public Address() { } @@ -57,7 +59,7 @@ public Address(String id, String street, String city, String state, String zip) } public Address(String id, String street, String city, String state, String zip, - Collection phones) { + List phones) { this.id = id; this.street = street; this.city = city; @@ -113,11 +115,12 @@ public void setZip(String zip) { } @OneToMany(cascade = CascadeType.ALL, mappedBy = "address") - public Collection getPhones() { + @OrderColumn + public List getPhones() { return phones; } - public void setPhones(Collection phones) { + public void setPhones(List phones) { this.phones = phones; } } \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Customer.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Customer.java index 81b1047614e3..907434ce34b1 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Customer.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/Customer.java @@ -62,6 +62,12 @@ public Customer(String id, String name) { this.name = name; } + // Used by test case for HHH-8699. + public Customer(String id, String name, String greeting, Boolean something) { + this.id = id; + this.name = name; + } + public Customer(String id, String name, Country country) { this.id = id; this.name = name; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MappedSuperclassTypeTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MappedSuperclassTypeTest.java index 24d3aab00431..bc6db7e47dde 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MappedSuperclassTypeTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MappedSuperclassTypeTest.java @@ -29,9 +29,9 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; +import org.junit.Test; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; @@ -40,6 +40,10 @@ * @author Steve Ebersole */ public class MappedSuperclassTypeTest extends BaseEntityManagerFunctionalTestCase { + + // spent too much time digging into this. problem is ultimately that metamodel binding + // is not handling MappedSuperclass well + @Override public Class[] getAnnotatedClasses() { return new Class[] { SomeMappedSuperclassSubclass.class }; @@ -56,6 +60,7 @@ public void ensureMappedSuperclassTypeReturnedAsManagedType() { @Test @TestForIssue( jiraKey = "HHH-8533" ) @SuppressWarnings("unchecked") + @FailureExpectedWithNewMetamodel( jiraKey = "HHH-9058", message = "Declared versus non-declared" ) public void testAttributeAccess() { final EntityType entityType = entityManagerFactory().getMetamodel().entity( SomeMappedSuperclassSubclass.class ); final IdentifiableType mappedSuperclassType = (IdentifiableType) entityType.getSupertype(); diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MixedIdAndIdClassHandling.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MixedIdAndIdClassHandling.java index bd7787e288b7..1b78384a9a53 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MixedIdAndIdClassHandling.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/MixedIdAndIdClassHandling.java @@ -33,9 +33,9 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.junit.Test; - +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -47,11 +47,12 @@ * * @author Steve Ebersole */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055" ) public class MixedIdAndIdClassHandling extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { FullTimeEmployee.class }; + return new Class[] { FullTimeEmployee.class, Employee.class, EmployeeId.class }; } @Test @@ -65,6 +66,7 @@ public void testAccess() { catch (IllegalArgumentException expected) { } + assertNotNull( entityType.getSupertype() ); assertNotNull( entityType.getSupertype().getIdClassAttributes() ); assertEquals( 1, entityType.getSupertype().getIdClassAttributes().size() ); @@ -76,8 +78,7 @@ public void testAccess() { @MappedSuperclass @IdClass( EmployeeId.class ) public static abstract class Employee { - @Id - private String id; + @Id private String id; private String name; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/pack/defaultpar_1_0/ApplicationServer1.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/pack/defaultpar_1_0/ApplicationServer1.java index 1fb14f8c0518..e75ce47d573b 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/pack/defaultpar_1_0/ApplicationServer1.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/pack/defaultpar_1_0/ApplicationServer1.java @@ -1,5 +1,6 @@ //$Id$ package org.hibernate.jpa.test.pack.defaultpar_1_0; +import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @@ -31,6 +32,7 @@ public void setName(String name) { this.name = name; } + @Embedded public Version1 getVersion() { return version; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/AnnotationTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/AnnotationTest.java index d9bdde87eb73..f233eed992f3 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/AnnotationTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/AnnotationTest.java @@ -1,8 +1,11 @@ package org.hibernate.jpa.test.procedure; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Strong Liu */ +@FailureExpectedWithNewMetamodel public class AnnotationTest extends AbstractStoredProcedureTest { @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/JpaTckUsageTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/JpaTckUsageTest.java index e734c7988724..5bdeef1a068e 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/JpaTckUsageTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/JpaTckUsageTest.java @@ -23,8 +23,6 @@ */ package org.hibernate.jpa.test.procedure; -import javax.persistence.EntityManager; -import javax.persistence.StoredProcedureQuery; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -35,6 +33,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.persistence.EntityManager; +import javax.persistence.StoredProcedureQuery; import org.hibernate.dialect.DerbyTenSevenDialect; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -45,13 +45,13 @@ import org.hibernate.jpa.internal.EntityManagerFactoryImpl; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.hibernate.testing.FailureExpected; -import org.hibernate.testing.junit4.BaseUnitTestCase; - import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -179,9 +179,13 @@ public void testSettingInParamDefinedOnNamedStoredProcedureQuery() { try { StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" ); query.setParameter( 1, 1 ); + em.getTransaction().commit(); + } + catch (RuntimeException e) { + em.getTransaction().rollback(); + throw e; } finally { - em.getTransaction().commit(); em.close(); } } @@ -189,31 +193,47 @@ public void testSettingInParamDefinedOnNamedStoredProcedureQuery() { @Test public void testSettingNonExistingParams() { EntityManager em = entityManagerFactory.createEntityManager(); - em.getTransaction().begin(); try { // non-existing positional param + em.getTransaction().begin(); + StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" ); try { - StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" ); query.setParameter( 99, 1 ); fail( "Expecting an exception" ); } catch (IllegalArgumentException expected) { // this is the expected condition } + finally { + if ( em.getTransaction().getRollbackOnly() ) { + em.getTransaction().rollback(); + } + else { + em.getTransaction().commit(); + } + } // non-existing named param + em.getTransaction().begin(); + query = em.createNamedStoredProcedureQuery( "positional-param" ); try { - StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" ); query.setParameter( "does-not-exist", 1 ); fail( "Expecting an exception" ); } catch (IllegalArgumentException expected) { // this is the expected condition } + finally { + if ( em.getTransaction().getRollbackOnly() ) { + em.getTransaction().rollback(); + } + else { + em.getTransaction().commit(); + } + } } finally { - em.getTransaction().commit(); em.close(); } } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/OrmTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/OrmTest.java index 0c12e35d553d..e443c4b546a9 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/OrmTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/procedure/OrmTest.java @@ -1,8 +1,11 @@ package org.hibernate.jpa.test.procedure; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Strong Liu */ +@FailureExpectedWithNewMetamodel public class OrmTest extends AbstractStoredProcedureTest{ @Override public String[] getEjb3DD() { diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ConstructorResultNativeQueryTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ConstructorResultNativeQueryTest.java index 59e651827f25..a7ab1b9ba61f 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ConstructorResultNativeQueryTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ConstructorResultNativeQueryTest.java @@ -23,6 +23,8 @@ */ package org.hibernate.jpa.test.query; +import java.util.Date; +import java.util.List; import javax.persistence.Column; import javax.persistence.ColumnResult; import javax.persistence.ConstructorResult; @@ -33,19 +35,14 @@ import javax.persistence.NamedNativeQuery; import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMappings; -import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; -import java.util.Date; -import java.util.List; - import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; -import org.hibernate.testing.junit4.BaseUnitTestCase; - import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; import static org.junit.Assert.assertEquals; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java index 304410c8c4fd..e76f5675ddae 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java @@ -25,7 +25,6 @@ import java.net.URL; import java.util.Map; - import javax.persistence.EntityManagerFactory; import org.hibernate.dialect.H2Dialect; @@ -34,6 +33,8 @@ import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.junit.Assert; @@ -46,6 +47,7 @@ * @author Steve Ebersole */ @RequiresDialect( H2Dialect.class ) +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9061" ) public class JpaSchemaGeneratorTest extends BaseEntityManagerFunctionalTestCase { private static final String LOAD_SQL = "org/hibernate/jpa/test/schemagen/load-script-source.sql"; private static final String CREATE_SQL = "org/hibernate/jpa/test/schemagen/create-script-source.sql"; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/GetIdentifierTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/GetIdentifierTest.java index b86979fbc340..a51024bec3e6 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/GetIdentifierTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/GetIdentifierTest.java @@ -118,6 +118,7 @@ public Class[] getAnnotatedClasses() { return new Class[] { Book.class, Umbrella.class, + Umbrella.PK.class, Sickness.class, Author.class, Article.class diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/Umbrella.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/Umbrella.java index 298da5dfe04d..57a9fa67747e 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/Umbrella.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/util/Umbrella.java @@ -1,6 +1,7 @@ package org.hibernate.jpa.test.util; import java.io.Serializable; import javax.persistence.Column; +import javax.persistence.Embeddable; import javax.persistence.EmbeddedId; import javax.persistence.Entity; @@ -31,6 +32,7 @@ public void setSize(int size) { this.size = size; } + @Embeddable public static class PK implements Serializable { private String model; private String brand; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/xml/XmlTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/xml/XmlTest.java index 754adaa3f1bc..f7a23768ac82 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/xml/XmlTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/xml/XmlTest.java @@ -39,6 +39,10 @@ * @author Emmanuel Bernard */ public class XmlTest extends BaseEntityManagerFunctionalTestCase { + + // failures from org.hibernate.tuple.PropertyFactory.buildEntityBasedAttribute again + // where attribute is an association (ManyToOne), Type resolves to null + @Test public void testXmlMappingCorrectness() throws Exception { EntityManager em = getOrCreateEntityManager(); diff --git a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/mixed.xml b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/mixed.xml new file mode 100644 index 000000000000..20d892656800 --- /dev/null +++ b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/mixed.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override.xml b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override.xml index bcf5979fc0d6..d7835bc82182 100644 --- a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override.xml +++ b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override.xml @@ -4,8 +4,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm/orm_2_1.xsd" version="2.1"> + + + org.hibernate.jpa.test.convert - - + + + + + + + \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override2.xml b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override2.xml index bf93796dbfc5..44b32b5f8717 100644 --- a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override2.xml +++ b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/convert/simple-override2.xml @@ -27,14 +27,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm/orm_2_1.xsd" version="2.1"> + + org.hibernate.jpa.test.convert - - + + \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-1.xml b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-1.xml index 753675b166b8..e466d325394c 100644 --- a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-1.xml +++ b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-1.xml @@ -52,4 +52,5 @@ + \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-2.xml b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-2.xml index 8f845be6158d..a89b1f7c67d1 100644 --- a/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-2.xml +++ b/hibernate-entitymanager/src/test/resources/org/hibernate/jpa/test/jee/valid-orm-2.xml @@ -54,4 +54,6 @@ + + \ No newline at end of file diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedEntitiesRevisionEntity.java b/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedEntitiesRevisionEntity.java index 09748c06b0d3..23893cab057f 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedEntitiesRevisionEntity.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedEntitiesRevisionEntity.java @@ -25,11 +25,11 @@ import java.util.HashSet; import java.util.Set; +import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.FetchType; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.MappedSuperclass; import org.hibernate.annotations.Fetch; @@ -45,7 +45,7 @@ @MappedSuperclass public class DefaultTrackingModifiedEntitiesRevisionEntity extends DefaultRevisionEntity { @ElementCollection(fetch = FetchType.EAGER) - @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) + @CollectionTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) @Column(name = "ENTITYNAME") @Fetch(FetchMode.JOIN) @ModifiedEntityNames diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AnnotationProxyBuilder.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AnnotationProxyBuilder.java new file mode 100644 index 000000000000..6c9622a69607 --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AnnotationProxyBuilder.java @@ -0,0 +1,124 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.envers.configuration.internal; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import javassist.util.proxy.MethodHandler; +import javassist.util.proxy.ProxyFactory; +import javassist.util.proxy.ProxyObject; +import org.jboss.jandex.AnnotationInstance; + +import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class AnnotationProxyBuilder { + private final Map proxyObjectMap = new HashMap(); + private final Map proxyFactoryMap = new HashMap(); + + public T getAnnotationProxy( + final AnnotationInstance annotationInstance, + final Class annotationClass, + final ClassLoaderService classLoaderService) { + T annotationProxy = (T) proxyObjectMap.get( annotationInstance ); + if ( annotationProxy == null ) { + annotationProxy = buildAnnotationProxy( annotationInstance, annotationClass, classLoaderService ); + proxyObjectMap.put( annotationInstance, annotationProxy ); + } + return annotationProxy; + } + + private T buildAnnotationProxy( + final AnnotationInstance annotationInstance, + final Class annotationClass, + final ClassLoaderService classLoaderService) { + try { + final Class annotation = annotationClass.getClassLoader().loadClass( annotationClass.getName() ); + final Class proxyClass = getProxyFactory( annotation ).createClass(); + final ProxyObject proxyObject = (ProxyObject) proxyClass.newInstance(); + proxyObject.setHandler( new MethodHandler() { + @Override + public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { + String executedMethodName = thisMethod.getName(); + if ( "toString".equals( executedMethodName ) ) { + return proxyClass.getName() + "@" + System.identityHashCode( self ); + } + final Class returnType = thisMethod.getReturnType(); + if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) { + final AnnotationInstance[] returnValues = JandexHelper.getValue( + annotationInstance, + executedMethodName, + AnnotationInstance[].class, + classLoaderService + ); + return buildAnnotationProxyArray( + returnValues, + returnType.getComponentType(), + classLoaderService + ); + } + return JandexHelper.getValue( + annotationInstance, + executedMethodName, + thisMethod.getReturnType(), + classLoaderService + ); + } + } ); + return (T) proxyObject; + } + catch ( Exception e ) { + throw new HibernateException( e ); + } + } + + @SuppressWarnings( {"unchecked"}) + private T[] buildAnnotationProxyArray( + final AnnotationInstance[] annotationInstances, + final Class annotationClass, + final ClassLoaderService classLoaderService) { + final T[] annotationProxyArray = (T[]) Array.newInstance( annotationClass, annotationInstances.length ); + for ( int i = 0 ; i < annotationInstances.length ; i++ ) { + annotationProxyArray[i] = buildAnnotationProxy( annotationInstances[i], annotationClass, classLoaderService ); + } + return annotationProxyArray; + } + + private ProxyFactory getProxyFactory(final Class annotation) { + ProxyFactory proxyFactory = proxyFactoryMap.get( annotation ); + if ( proxyFactory == null ) { + proxyFactory = new ProxyFactory(); + proxyFactoryMap.put( annotation, proxyFactory ); + } + proxyFactory.setInterfaces( new Class[] { annotation } ); + return proxyFactory; + } +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AuditEntitiesConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AuditEntitiesConfiguration.java index ae0a63010a97..4db299091b69 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AuditEntitiesConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/AuditEntitiesConfiguration.java @@ -25,11 +25,12 @@ import java.util.HashMap; import java.util.Map; -import java.util.Properties; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.envers.configuration.EnversSettings; import org.hibernate.envers.strategy.DefaultAuditStrategy; -import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.service.ServiceRegistry; /** * Configuration of versions entities - names of fields, entities and tables created to store versioning information. @@ -62,36 +63,48 @@ public class AuditEntitiesConfiguration { private final String embeddableSetOrdinalPropertyName; - public AuditEntitiesConfiguration(Properties properties, String revisionInfoEntityName) { + public AuditEntitiesConfiguration(ServiceRegistry serviceRegistry, String revisionInfoEntityName) { this.revisionInfoEntityName = revisionInfoEntityName; - auditTablePrefix = ConfigurationHelper.getString( EnversSettings.AUDIT_TABLE_PREFIX, properties, "" ); - auditTableSuffix = ConfigurationHelper.getString( EnversSettings.AUDIT_TABLE_SUFFIX, properties, "_AUD" ); + final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); - auditStrategyName = ConfigurationHelper.getString( - EnversSettings.AUDIT_STRATEGY, properties, DefaultAuditStrategy.class.getName() + auditTablePrefix = configurationService.getSetting( + EnversSettings.AUDIT_TABLE_PREFIX, StandardConverters.STRING, "" + ); + auditTableSuffix = configurationService.getSetting( + EnversSettings.AUDIT_TABLE_SUFFIX, StandardConverters.STRING, "_AUD" + ); + + auditStrategyName = configurationService.getSetting( + EnversSettings.AUDIT_STRATEGY, StandardConverters.STRING, DefaultAuditStrategy.class.getName() ); originalIdPropName = "originalId"; - revisionFieldName = ConfigurationHelper.getString( EnversSettings.REVISION_FIELD_NAME, properties, "REV" ); + revisionFieldName = configurationService.getSetting( + EnversSettings.REVISION_FIELD_NAME, StandardConverters.STRING, "REV" + ); - revisionTypePropName = ConfigurationHelper.getString( - EnversSettings.REVISION_TYPE_FIELD_NAME, properties, "REVTYPE" + revisionTypePropName = configurationService.getSetting( + EnversSettings.REVISION_TYPE_FIELD_NAME, StandardConverters.STRING, "REVTYPE" ); revisionTypePropType = "byte"; - revisionEndFieldName = ConfigurationHelper.getString( - EnversSettings.AUDIT_STRATEGY_VALIDITY_END_REV_FIELD_NAME, properties, "REVEND" + revisionEndFieldName = configurationService.getSetting( + EnversSettings.AUDIT_STRATEGY_VALIDITY_END_REV_FIELD_NAME, StandardConverters.STRING, "REVEND" ); - revisionEndTimestampEnabled = ConfigurationHelper.getBoolean( - EnversSettings.AUDIT_STRATEGY_VALIDITY_STORE_REVEND_TIMESTAMP, properties, false + revisionEndTimestampEnabled = configurationService.getSetting( + EnversSettings.AUDIT_STRATEGY_VALIDITY_STORE_REVEND_TIMESTAMP, + StandardConverters.BOOLEAN, + false ); if ( revisionEndTimestampEnabled ) { - revisionEndTimestampFieldName = ConfigurationHelper.getString( - EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_FIELD_NAME, properties, "REVEND_TSTMP" + revisionEndTimestampFieldName = configurationService.getSetting( + EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_FIELD_NAME, + StandardConverters.STRING, + "REVEND_TSTMP" ); } else { @@ -103,8 +116,8 @@ public AuditEntitiesConfiguration(Properties properties, String revisionInfoEnti revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id"; revisionPropBasePath = originalIdPropName + "." + revisionFieldName + "."; - embeddableSetOrdinalPropertyName = ConfigurationHelper.getString( - EnversSettings.EMBEDDABLE_SET_ORDINAL_FIELD_NAME, properties, "SETORDINAL" + embeddableSetOrdinalPropertyName = configurationService.getSetting( + EnversSettings.EMBEDDABLE_SET_ORDINAL_FIELD_NAME, StandardConverters.STRING, "SETORDINAL" ); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/ClassesAuditingData.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/ClassesAuditingData.java index a3a868a74b23..7ee9e0788e77 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/ClassesAuditingData.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/ClassesAuditingData.java @@ -33,12 +33,12 @@ import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData; import org.hibernate.envers.internal.EnversMessageLogger; import org.hibernate.envers.internal.tools.MappingTools; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.jboss.logging.Logger; /** - * A helper class holding auditing meta-data for all persistent classes. + * A helper class holding auditing meta-data for all entity bindings. * * @author Adam Warski (adam at warski dot org) */ @@ -49,24 +49,25 @@ public class ClassesAuditingData { ); private final Map entityNameToAuditingData = new HashMap(); - private final Map persistentClassToAuditingData = new LinkedHashMap(); + private final Map entityBindingToAuditingData = + new LinkedHashMap(); /** * Stores information about auditing meta-data for the given class. * - * @param pc Persistent class. + * @param entityBinding The entity binding. * @param cad Auditing meta-data for the given class. */ - public void addClassAuditingData(PersistentClass pc, ClassAuditingData cad) { - entityNameToAuditingData.put( pc.getEntityName(), cad ); - persistentClassToAuditingData.put( pc, cad ); + public void addClassAuditingData(EntityBinding entityBinding, ClassAuditingData cad) { + entityNameToAuditingData.put( entityBinding.getEntityName(), cad ); + entityBindingToAuditingData.put( entityBinding, cad ); } /** * @return A collection of all auditing meta-data for persistent classes. */ - public Collection> getAllClassAuditedData() { - return persistentClassToAuditingData.entrySet(); + public Collection> getAllEntityBindingAuditedData() { + return entityBindingToAuditingData.entrySet(); } /** @@ -85,27 +86,27 @@ public ClassAuditingData getClassAuditingData(String entityName) { * */ public void updateCalculatedFields() { - for ( Map.Entry classAuditingDataEntry : persistentClassToAuditingData.entrySet() ) { - final PersistentClass pc = classAuditingDataEntry.getKey(); + for ( Map.Entry classAuditingDataEntry : entityBindingToAuditingData.entrySet() ) { + final EntityBinding entityBinding = classAuditingDataEntry.getKey(); final ClassAuditingData classAuditingData = classAuditingDataEntry.getValue(); for ( String propertyName : classAuditingData.getPropertyNames() ) { final PropertyAuditingData propertyAuditingData = classAuditingData.getPropertyAuditingData( propertyName ); // If a property had the @AuditMappedBy annotation, setting the referenced fields to be always insertable. if ( propertyAuditingData.getAuditMappedBy() != null ) { final String referencedEntityName = MappingTools.getReferencedEntityName( - pc.getProperty( propertyName ).getValue() + entityBinding.locateAttributeBinding( propertyName ) ); final ClassAuditingData referencedClassAuditingData = entityNameToAuditingData.get( referencedEntityName ); forcePropertyInsertable( referencedClassAuditingData, propertyAuditingData.getAuditMappedBy(), - pc.getEntityName(), referencedEntityName + entityBinding.getEntityName(), referencedEntityName ); forcePropertyInsertable( referencedClassAuditingData, propertyAuditingData.getPositionMappedBy(), - pc.getEntityName(), referencedEntityName + entityBinding.getEntityName(), referencedEntityName ); } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntitiesConfigurator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntitiesConfigurator.java index 2884f40a1be0..6c0d29ab57e6 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntitiesConfigurator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntitiesConfigurator.java @@ -28,23 +28,22 @@ import java.io.PrintWriter; import java.io.Writer; import java.util.HashMap; -import java.util.Iterator; +import java.util.List; import java.util.Map; import org.hibernate.MappingException; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.Configuration; import org.hibernate.envers.configuration.internal.metadata.AuditEntityNameRegister; import org.hibernate.envers.configuration.internal.metadata.AuditMetadataGenerator; import org.hibernate.envers.configuration.internal.metadata.EntityXmlMappingData; import org.hibernate.envers.configuration.internal.metadata.reader.AnnotationsMetadataReader; import org.hibernate.envers.configuration.internal.metadata.reader.ClassAuditingData; +import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.envers.internal.EnversMessageLogger; import org.hibernate.envers.internal.entities.EntitiesConfigurations; import org.hibernate.envers.internal.tools.StringTools; import org.hibernate.envers.internal.tools.graph.GraphTopologicalSort; import org.hibernate.envers.strategy.AuditStrategy; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.dom4j.Document; import org.dom4j.DocumentException; @@ -52,80 +51,84 @@ import org.dom4j.io.DOMWriter; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; +import org.jboss.logging.Logger; /** * @author Adam Warski (adam at warski dot org) */ public class EntitiesConfigurator { + private static final EnversMessageLogger LOG = Logger.getMessageLogger( + EnversMessageLogger.class, + EntitiesConfigurator.class.getName() + ); + + public EntitiesConfigurations configure( - Configuration cfg, ReflectionManager reflectionManager, - GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg, - AuditStrategy auditStrategy, ClassLoaderService classLoaderService, - Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) { + AuditConfiguration.AuditConfigurationContext context, + AuditStrategy auditStrategy, + Document revisionInfoXmlMapping, + Element revisionInfoRelationMapping) { // Creating a name register to capture all audit entity names created. final AuditEntityNameRegister auditEntityNameRegister = new AuditEntityNameRegister(); final DOMWriter writer = new DOMWriter(); - // Sorting the persistent class topologically - superclass always before subclass - final Iterator classes = GraphTopologicalSort.sort( new PersistentClassGraphDefiner( cfg ) ) - .iterator(); + // Sorting the entity bindings topologically - superclass always before subclass + final List entityBindings = + GraphTopologicalSort.sort( new EntityBindingGraphDefiner( context.getMetadata() ) ); final ClassesAuditingData classesAuditingData = new ClassesAuditingData(); - final Map xmlMappings = new HashMap(); + final Map xmlMappings = new HashMap(); // Reading metadata from annotations - while ( classes.hasNext() ) { - final PersistentClass pc = classes.next(); + final AnnotationsMetadataReader annotationsMetadataReader = new AnnotationsMetadataReader( context ); + for ( EntityBinding entityBinding : entityBindings ) { // Collecting information from annotations on the persistent class pc - final AnnotationsMetadataReader annotationsMetadataReader = - new AnnotationsMetadataReader( globalCfg, reflectionManager, pc ); - final ClassAuditingData auditData = annotationsMetadataReader.getAuditData(); + final ClassAuditingData auditData = annotationsMetadataReader.getAuditData( entityBinding ); - classesAuditingData.addClassAuditingData( pc, auditData ); + classesAuditingData.addClassAuditingData( entityBinding, auditData ); } // Now that all information is read we can update the calculated fields. classesAuditingData.updateCalculatedFields(); final AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator( - cfg, globalCfg, verEntCfg, auditStrategy, - classLoaderService, revisionInfoRelationMapping, auditEntityNameRegister + context, auditStrategy, revisionInfoRelationMapping, auditEntityNameRegister ); // First pass - for ( Map.Entry pcDatasEntry : classesAuditingData.getAllClassAuditedData() ) { - final PersistentClass pc = pcDatasEntry.getKey(); + for ( Map.Entry pcDatasEntry : classesAuditingData.getAllEntityBindingAuditedData() ) { + final EntityBinding entityBinding = pcDatasEntry.getKey(); final ClassAuditingData auditData = pcDatasEntry.getValue(); final EntityXmlMappingData xmlMappingData = new EntityXmlMappingData(); if ( auditData.isAudited() ) { if ( !StringTools.isEmpty( auditData.getAuditTable().value() ) ) { - verEntCfg.addCustomAuditTableName( pc.getEntityName(), auditData.getAuditTable().value() ); + context.getAuditEntitiesConfiguration().addCustomAuditTableName( entityBinding.getEntityName(), auditData.getAuditTable().value() ); } - auditMetaGen.generateFirstPass( pc, auditData, xmlMappingData, true ); + auditMetaGen.generateFirstPass( entityBinding, auditData, xmlMappingData, true ); } else { - auditMetaGen.generateFirstPass( pc, auditData, xmlMappingData, false ); + auditMetaGen.generateFirstPass( entityBinding, auditData, xmlMappingData, false ); } - xmlMappings.put( pc, xmlMappingData ); + xmlMappings.put( entityBinding, xmlMappingData ); } // Second pass - for ( Map.Entry pcDatasEntry : classesAuditingData.getAllClassAuditedData() ) { + for ( Map.Entry pcDatasEntry : classesAuditingData.getAllEntityBindingAuditedData() ) { final EntityXmlMappingData xmlMappingData = xmlMappings.get( pcDatasEntry.getKey() ); if ( pcDatasEntry.getValue().isAudited() ) { auditMetaGen.generateSecondPass( pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData ); try { - cfg.addDocument( writer.write( xmlMappingData.getMainXmlMapping() ) ); - //writeDocument(xmlMappingData.getMainXmlMapping()); + logDocument( xmlMappingData.getMainXmlMapping() ); + context.addDocument( writer.write( xmlMappingData.getMainXmlMapping() ) ); for ( Document additionalMapping : xmlMappingData.getAdditionalXmlMappings() ) { - cfg.addDocument( writer.write( additionalMapping ) ); - //writeDocument(additionalMapping); + logDocument( additionalMapping ); + context.addDocument( writer.write( additionalMapping ) ); } } catch (DocumentException e) { @@ -138,8 +141,8 @@ public EntitiesConfigurations configure( if ( auditMetaGen.getEntitiesConfigurations().size() > 0 ) { try { if ( revisionInfoXmlMapping != null ) { - //writeDocument(revisionInfoXmlMapping); - cfg.addDocument( writer.write( revisionInfoXmlMapping ) ); + logDocument( revisionInfoXmlMapping ); + context.addDocument( writer.write( revisionInfoXmlMapping ) ); } } catch (DocumentException e) { @@ -153,8 +156,10 @@ public EntitiesConfigurations configure( ); } - @SuppressWarnings({"UnusedDeclaration"}) - private void writeDocument(Document e) { + private void logDocument(Document e) { + if ( !LOG.isDebugEnabled() ) { + return; + } final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final Writer w = new PrintWriter( baos ); @@ -167,8 +172,8 @@ private void writeDocument(Document e) { e1.printStackTrace(); } - System.out.println( "-----------" ); - System.out.println( baos.toString() ); - System.out.println( "-----------" ); + LOG.debug( "-----------" ); + LOG.debug( baos.toString() ); + LOG.debug( "-----------" ); } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntityBindingGraphDefiner.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntityBindingGraphDefiner.java new file mode 100644 index 000000000000..c838aba19f35 --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/EntityBindingGraphDefiner.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.envers.configuration.internal; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.hibernate.envers.internal.tools.Tools; +import org.hibernate.envers.internal.tools.graph.GraphDefiner; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +/** + * Defines a graph, where the vertexes are all persistent classes, and there is an edge from + * p.c. A to p.c. B iff A is a superclass of B. + * + * @author Adam Warski (adam at warski dot org) + */ +public class EntityBindingGraphDefiner implements GraphDefiner { + private Metadata metadata; + + public EntityBindingGraphDefiner(Metadata metadata) { + this.metadata = metadata; + } + + @Override + public String getRepresentation(EntityBinding pc) { + return pc.getEntityName(); + } + + @Override + public EntityBinding getValue(String entityName) { + return metadata.getEntityBinding( entityName ); + } + + @SuppressWarnings({"unchecked"}) + private void addNeighbours(List neighbours, Iterator subclassIterator) { + while ( subclassIterator.hasNext() ) { + final EntityBinding subclass = subclassIterator.next(); + neighbours.add( subclass ); + addNeighbours( neighbours, subclass.getDirectSubEntityBindings().iterator() ); + } + } + + @Override + @SuppressWarnings({"unchecked"}) + public List getNeighbours(EntityBinding entityBinding) { + final List neighbours = new ArrayList(); + + addNeighbours( neighbours, entityBinding.getDirectSubEntityBindings().iterator() ); + + return neighbours; + } + + @Override + @SuppressWarnings({"unchecked"}) + public List getValues() { + return Tools.iteratorToList( metadata.getEntityBindings().iterator() ); + } +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/GlobalConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/GlobalConfiguration.java index 61516f9b7174..059b7ab7128d 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/GlobalConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/GlobalConfiguration.java @@ -23,17 +23,17 @@ */ package org.hibernate.envers.configuration.internal; -import java.util.Properties; import org.hibernate.MappingException; +import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.cfg.Environment; import org.hibernate.dialect.HSQLDialect; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.envers.RevisionListener; import org.hibernate.envers.configuration.EnversSettings; -import org.hibernate.envers.internal.tools.ReflectionTools; -import org.hibernate.internal.util.config.ConfigurationHelper; /** * @author Adam Warski (adam at warski dot org) @@ -89,46 +89,64 @@ Which operator to use in correlated subqueries (when we want a property to be eq */ private final String correlatedSubqueryOperator; - public GlobalConfiguration(Properties properties, ClassLoaderService classLoaderService) { - generateRevisionsForCollections = ConfigurationHelper.getBoolean( - EnversSettings.REVISION_ON_COLLECTION_CHANGE, properties, true + public GlobalConfiguration(StandardServiceRegistry serviceRegistry) { + + final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); + + generateRevisionsForCollections = configurationService.getSetting( + EnversSettings.REVISION_ON_COLLECTION_CHANGE, StandardConverters.BOOLEAN, true ); - doNotAuditOptimisticLockingField = ConfigurationHelper.getBoolean( - EnversSettings.DO_NOT_AUDIT_OPTIMISTIC_LOCKING_FIELD, properties, true + doNotAuditOptimisticLockingField = configurationService.getSetting( + EnversSettings.DO_NOT_AUDIT_OPTIMISTIC_LOCKING_FIELD, StandardConverters.BOOLEAN, true ); - storeDataAtDelete = ConfigurationHelper.getBoolean( EnversSettings.STORE_DATA_AT_DELETE, properties, false ); + storeDataAtDelete = configurationService.getSetting( + EnversSettings.STORE_DATA_AT_DELETE, StandardConverters.BOOLEAN, false + ); - defaultSchemaName = properties.getProperty( EnversSettings.DEFAULT_SCHEMA, null ); - defaultCatalogName = properties.getProperty( EnversSettings.DEFAULT_CATALOG, null ); + defaultSchemaName = configurationService.getSetting( + EnversSettings.DEFAULT_SCHEMA, StandardConverters.STRING + ); + defaultCatalogName = configurationService.getSetting( + EnversSettings.DEFAULT_CATALOG, StandardConverters.STRING + ); - correlatedSubqueryOperator = HSQLDialect.class.getName() - .equals( properties.get( Environment.DIALECT ) ) ? "in" : "="; + // TODO: is this really needed??? Should be available in dialect... + final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class ); + correlatedSubqueryOperator = HSQLDialect.class.equals( jdbcEnvironment.getDialect().getClass() ) ? "in" : "="; - trackEntitiesChangedInRevision = ConfigurationHelper.getBoolean( - EnversSettings.TRACK_ENTITIES_CHANGED_IN_REVISION, properties, false + trackEntitiesChangedInRevision = configurationService.getSetting( + EnversSettings.TRACK_ENTITIES_CHANGED_IN_REVISION, StandardConverters.BOOLEAN, false ); - - cascadeDeleteRevision = ConfigurationHelper.getBoolean( - "org.hibernate.envers.cascade_delete_revision", properties, false ); - useRevisionEntityWithNativeId = ConfigurationHelper.getBoolean( - EnversSettings.USE_REVISION_ENTITY_WITH_NATIVE_ID, properties, true + // TODO: shouldn't there be an Envers setting for "org.hibernate.envers.cascade_delete_revision"? + cascadeDeleteRevision = configurationService.getSetting( + "org.hibernate.envers.cascade_delete_revision", StandardConverters.BOOLEAN, false ); - hasGlobalSettingForWithModifiedFlag = properties.get( EnversSettings.GLOBAL_WITH_MODIFIED_FLAG ) != null; - globalWithModifiedFlag = ConfigurationHelper.getBoolean( - EnversSettings.GLOBAL_WITH_MODIFIED_FLAG, properties, false + useRevisionEntityWithNativeId = configurationService.getSetting( + EnversSettings.USE_REVISION_ENTITY_WITH_NATIVE_ID, StandardConverters.BOOLEAN, true ); - modifiedFlagSuffix = ConfigurationHelper.getString( - EnversSettings.MODIFIED_FLAG_SUFFIX, properties, "_MOD" + + hasGlobalSettingForWithModifiedFlag = null != configurationService.getSetting( + EnversSettings.GLOBAL_WITH_MODIFIED_FLAG, StandardConverters.BOOLEAN + ); + globalWithModifiedFlag = configurationService.getSetting( + EnversSettings.GLOBAL_WITH_MODIFIED_FLAG, StandardConverters.BOOLEAN, false + ); + modifiedFlagSuffix = configurationService.getSetting( + EnversSettings.MODIFIED_FLAG_SUFFIX, StandardConverters.STRING, "_MOD" ); - final String revisionListenerClassName = properties.getProperty( EnversSettings.REVISION_LISTENER, null ); + final String revisionListenerClassName = configurationService.getSetting( + EnversSettings.REVISION_LISTENER, + StandardConverters.STRING + ); if ( revisionListenerClassName != null ) { try { - revisionListenerClass = ReflectionTools.loadClass( revisionListenerClassName, classLoaderService ); + revisionListenerClass = + serviceRegistry.getService( ClassLoaderService.class ).classForName( revisionListenerClassName ); } catch (ClassLoadingException e) { throw new MappingException( @@ -141,8 +159,8 @@ public GlobalConfiguration(Properties properties, ClassLoaderService classLoader revisionListenerClass = null; } - allowIdentifierReuse = ConfigurationHelper.getBoolean( - EnversSettings.ALLOW_IDENTIFIER_REUSE, properties, false + allowIdentifierReuse = configurationService.getSetting( + EnversSettings.ALLOW_IDENTIFIER_REUSE, StandardConverters.BOOLEAN, false ); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/PersistentClassGraphDefiner.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/PersistentClassGraphDefiner.java deleted file mode 100644 index c26a22474a9b..000000000000 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/PersistentClassGraphDefiner.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.envers.configuration.internal; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.hibernate.cfg.Configuration; -import org.hibernate.envers.internal.tools.Tools; -import org.hibernate.envers.internal.tools.graph.GraphDefiner; -import org.hibernate.mapping.PersistentClass; - -/** - * Defines a graph, where the vertexes are all persistent classes, and there is an edge from - * p.c. A to p.c. B iff A is a superclass of B. - * - * @author Adam Warski (adam at warski dot org) - */ -public class PersistentClassGraphDefiner implements GraphDefiner { - private Configuration cfg; - - public PersistentClassGraphDefiner(Configuration cfg) { - this.cfg = cfg; - } - - @Override - public String getRepresentation(PersistentClass pc) { - return pc.getEntityName(); - } - - @Override - public PersistentClass getValue(String entityName) { - return cfg.getClassMapping( entityName ); - } - - @SuppressWarnings({"unchecked"}) - private void addNeighbours(List neighbours, Iterator subclassIterator) { - while ( subclassIterator.hasNext() ) { - final PersistentClass subclass = subclassIterator.next(); - neighbours.add( subclass ); - addNeighbours( neighbours, (Iterator) subclass.getSubclassIterator() ); - } - } - - @Override - @SuppressWarnings({"unchecked"}) - public List getNeighbours(PersistentClass pc) { - final List neighbours = new ArrayList(); - - addNeighbours( neighbours, (Iterator) pc.getSubclassIterator() ); - - return neighbours; - } - - @Override - @SuppressWarnings({"unchecked"}) - public List getValues() { - return Tools.iteratorToList( cfg.getClassMappings() ); - } -} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java index 57831e7f3d9f..854e852d6882 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/RevisionInfoConfiguration.java @@ -23,28 +23,20 @@ */ package org.hibernate.envers.configuration.internal; -import java.util.Date; -import java.util.Iterator; -import java.util.Set; -import javax.persistence.Column; +import java.sql.Date; +import java.util.Collection; import org.hibernate.MappingException; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.annotations.common.reflection.XClass; -import org.hibernate.annotations.common.reflection.XProperty; -import org.hibernate.cfg.Configuration; -import org.hibernate.envers.Audited; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.envers.DefaultRevisionEntity; import org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity; -import org.hibernate.envers.ModifiedEntityNames; import org.hibernate.envers.RevisionEntity; import org.hibernate.envers.RevisionListener; -import org.hibernate.envers.RevisionNumber; -import org.hibernate.envers.RevisionTimestamp; import org.hibernate.envers.configuration.internal.metadata.AuditTableData; import org.hibernate.envers.configuration.internal.metadata.MetadataTools; import org.hibernate.envers.enhanced.SequenceIdRevisionEntity; import org.hibernate.envers.enhanced.SequenceIdTrackingModifiedEntitiesRevisionEntity; +import org.hibernate.envers.event.spi.EnversDotNames; import org.hibernate.envers.internal.entities.PropertyData; import org.hibernate.envers.internal.revisioninfo.DefaultRevisionInfoGenerator; import org.hibernate.envers.internal.revisioninfo.DefaultTrackingModifiedEntitiesRevisionInfoGenerator; @@ -53,14 +45,31 @@ import org.hibernate.envers.internal.revisioninfo.RevisionInfoNumberReader; import org.hibernate.envers.internal.revisioninfo.RevisionInfoQueryCreator; import org.hibernate.envers.internal.tools.MutableBoolean; +import org.hibernate.envers.internal.tools.Tools; import org.hibernate.internal.util.xml.XMLHelper; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.SetBinding; +import org.hibernate.type.IntegerType; import org.hibernate.type.LongType; import org.hibernate.type.Type; import org.dom4j.Document; import org.dom4j.Element; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.MethodInfo; + +import static org.hibernate.metamodel.spi.AdditionalJaxbRootProducer.AdditionalJaxbRootProducerContext; + /** * @author Adam Warski (adam at warski dot org) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) @@ -109,9 +118,9 @@ private Document generateDefaultRevisionInfoXmlMapping() { classMapping, revisionInfoIdData.getName(), revisionPropType, - globalCfg.isUseRevisionEntityWithNativeId() + globalCfg.isUseRevisionEntityWithNativeId(), + "REV" ); - MetadataTools.addColumn( idProperty, "REV", null, null, null, null, null, null, false ); final Element timestampProperty = MetadataTools.addProperty( classMapping, @@ -178,8 +187,9 @@ private void generateEntityNamesTrackingTableMapping( private Element generateRevisionInfoRelationMapping() { final Document document = XMLHelper.getDocumentFactory().createDocument(); final Element revRelMapping = document.addElement( "key-many-to-one" ); - revRelMapping.addAttribute( "type", revisionPropType ); - revRelMapping.addAttribute( "class", revisionInfoEntityName ); + // TODO: this does not belong here; does it belong somewhere else???? + //revRelMapping.addAttribute( "type", revisionPropType ); + revRelMapping.addAttribute( "entity-name", revisionInfoEntityName ); if ( revisionPropSqlType != null ) { // Putting a fake name to make Hibernate happy. It will be replaced later anyway. @@ -189,97 +199,161 @@ private Element generateRevisionInfoRelationMapping() { return revRelMapping; } - private void searchForRevisionInfoCfgInProperties( - XClass clazz, - ReflectionManager reflectionManager, - MutableBoolean revisionNumberFound, - MutableBoolean revisionTimestampFound, - MutableBoolean modifiedEntityNamesFound, - String accessType) { - for ( XProperty property : clazz.getDeclaredProperties( accessType ) ) { - final RevisionNumber revisionNumber = property.getAnnotation( RevisionNumber.class ); - final RevisionTimestamp revisionTimestamp = property.getAnnotation( RevisionTimestamp.class ); - final ModifiedEntityNames modifiedEntityNames = property.getAnnotation( ModifiedEntityNames.class ); - - if ( revisionNumber != null ) { + private void searchForRevisionNumberCfg( + ClassInfo revisionInfoEntityClassInfo, + EntityBinding revisionInfoEntityBinding, + AdditionalJaxbRootProducerContext context, + MutableBoolean revisionNumberFound) { + for ( AnnotationInstance annotation : context.getJandexIndex().getAnnotations( EnversDotNames.REVISION_NUMBER ) ) { + final AnnotationTarget annotationTarget = annotation.target(); + if ( !( annotationTarget instanceof FieldInfo || annotationTarget instanceof MethodInfo ) ) { + throw new MappingException( "@RevisionNumber is applicable only to fields or properties." ); + } + if ( Tools.isFieldOrPropertyOfClass( + annotationTarget, + revisionInfoEntityClassInfo, + context.getJandexIndex() ) ) { if ( revisionNumberFound.isSet() ) { - throw new MappingException( "Only one property may be annotated with @RevisionNumber!" ); + throw new MappingException( "Only one property may be annotated with @RevisionNumber." ); } - final XClass revisionNumberClass = property.getType(); - if ( reflectionManager.equals( revisionNumberClass, Integer.class ) || - reflectionManager.equals( revisionNumberClass, Integer.TYPE ) ) { - revisionInfoIdData = new PropertyData( property.getName(), property.getName(), accessType, null ); - revisionNumberFound.set(); + final String revisionNumberProperty = JandexHelper.getPropertyName( annotationTarget ); + final AttributeBinding revisionNumberAttribute = revisionInfoEntityBinding.locateAttributeBinding( + revisionNumberProperty + ); + HibernateTypeDescriptor revisionNumberType = revisionNumberAttribute.getHibernateTypeDescriptor(); + // TODO: Check whether it is required to verify HibernateTypeDescriptor#getJavaTypeName()? + if ( revisionNumberType.getResolvedTypeMapping() instanceof IntegerType ) { + revisionPropType = "integer"; } - else if ( reflectionManager.equals( revisionNumberClass, Long.class ) || - reflectionManager.equals( revisionNumberClass, Long.TYPE ) ) { - revisionInfoIdData = new PropertyData( property.getName(), property.getName(), accessType, null ); - revisionNumberFound.set(); - - // The default is integer + else if ( revisionNumberType.getResolvedTypeMapping() instanceof LongType ) { + // The default is integer. revisionPropType = "long"; } else { throw new MappingException( - "The field annotated with @RevisionNumber must be of type " + - "int, Integer, long or Long" + "Field annotated with @RevisionNumber must be of type int, Integer, long or Long." ); } + revisionInfoIdData = new PropertyData( + revisionNumberProperty, + revisionNumberProperty, + revisionNumberAttribute.getPropertyAccessorName(), + null + ); + revisionNumberFound.set(); + + // Getting the @Column definition of the revision number property, to later use that info to // generate the same mapping for the relation from an audit table's revision number to the // revision entity revision number. - final Column revisionPropColumn = property.getAnnotation( Column.class ); - if ( revisionPropColumn != null ) { - revisionPropSqlType = revisionPropColumn.columnDefinition(); + final AnnotationInstance jpaColumnAnnotation = JandexHelper.getSingleAnnotation( + JandexHelper.getMemberAnnotations( + revisionInfoEntityClassInfo, + revisionNumberProperty, + context.getServiceRegistry() + ), + JPADotNames.COLUMN + ); + if ( jpaColumnAnnotation != null ) { + final ClassLoaderService classLoaderService = + context.getServiceRegistry().getService( ClassLoaderService.class ); + revisionPropSqlType = JandexHelper.getValue( + jpaColumnAnnotation, + "columnDefinition", + String.class, + classLoaderService + ); } } + } + } - if ( revisionTimestamp != null ) { + private void searchForRevisionTimestampCfg( + ClassInfo revisionInfoEntityClassInfo, + EntityBinding revisionInfoEntityBinding, + AdditionalJaxbRootProducerContext context, + MutableBoolean revisionTimestampFound) { + final IndexView jandexIndex = context.getJandexIndex(); + for ( AnnotationInstance annotation : jandexIndex.getAnnotations( EnversDotNames.REVISION_TIMESTAMP ) ) { + AnnotationTarget annotationTarget = annotation.target(); + if ( !( annotationTarget instanceof FieldInfo || annotationTarget instanceof MethodInfo ) ) { + throw new MappingException( "@RevisionTimestamp is applicable only to fields or properties." ); + } + if ( Tools.isFieldOrPropertyOfClass( annotationTarget, revisionInfoEntityClassInfo, jandexIndex ) ) { if ( revisionTimestampFound.isSet() ) { - throw new MappingException( "Only one property may be annotated with @RevisionTimestamp!" ); + throw new MappingException( "Only one property may be annotated with @RevisionTimestamp." ); } - final XClass revisionTimestampClass = property.getType(); - if ( reflectionManager.equals( revisionTimestampClass, Long.class ) || - reflectionManager.equals( revisionTimestampClass, Long.TYPE ) || - reflectionManager.equals( revisionTimestampClass, Date.class ) || - reflectionManager.equals( revisionTimestampClass, java.sql.Date.class ) ) { + final String revisionTimestampProperty = JandexHelper.getPropertyName( annotationTarget ); + final AttributeBinding revisionTimestampAttribute = revisionInfoEntityBinding.locateAttributeBinding( + revisionTimestampProperty + ); + HibernateTypeDescriptor revisionTimestampType = revisionTimestampAttribute.getHibernateTypeDescriptor(); + final String revisionTimestampClassName = revisionTimestampType.getJavaTypeDescriptor().getName().toString(); + if ( Long.TYPE.getName().equals( revisionTimestampClassName ) || + java.util.Date.class.getName().equals( revisionTimestampClassName ) || + Date.class.getName().equals( revisionTimestampClassName) ) { revisionInfoTimestampData = new PropertyData( - property.getName(), - property.getName(), - accessType, + revisionTimestampProperty, + revisionTimestampProperty, + revisionTimestampAttribute.getPropertyAccessorName(), null ); revisionTimestampFound.set(); } else { throw new MappingException( - "The field annotated with @RevisionTimestamp must be of type " + - "long, Long, java.util.Date or java.sql.Date" + "Field annotated with @RevisionTimestamp must be of type long, Long, java.util.Date or java.sql.Date." ); } } + } + } - if ( modifiedEntityNames != null ) { + private void searchForModifiedEntityNamesCfg( + ClassInfo revisionInfoEntityClassInfo, + EntityBinding revisionInfoEntityBinding, + AdditionalJaxbRootProducerContext context, + MutableBoolean modifiedEntityNamesFound) { + final IndexView jandexIndex = context.getJandexIndex(); + for ( AnnotationInstance annotation : jandexIndex.getAnnotations( EnversDotNames.MODIFIED_ENTITY_NAMES ) ) { + AnnotationTarget annotationTarget = annotation.target(); + if ( !( annotationTarget instanceof FieldInfo || annotationTarget instanceof MethodInfo ) ) { + throw new MappingException( "@ModifiedEntityNames is applicable only to fields or properties." ); + } + if ( Tools.isFieldOrPropertyOfClass( annotationTarget, revisionInfoEntityClassInfo, jandexIndex ) ) { if ( modifiedEntityNamesFound.isSet() ) { - throw new MappingException( "Only one property may be annotated with @ModifiedEntityNames!" ); + throw new MappingException( "Only one property may be annotated with @ModifiedEntityNames." ); } - final XClass modifiedEntityNamesClass = property.getType(); - if ( reflectionManager.equals( modifiedEntityNamesClass, Set.class ) && - reflectionManager.equals( property.getElementClass(), String.class ) ) { - modifiedEntityNamesData = new PropertyData( - property.getName(), - property.getName(), - accessType, - null - ); - modifiedEntityNamesFound.set(); + + final String modifiedEntityNamesProperty = JandexHelper.getPropertyName( annotationTarget ); + final AttributeBinding modifiedEntityNamesAttribute = revisionInfoEntityBinding.locateAttributeBinding( + modifiedEntityNamesProperty + ); + + if ( modifiedEntityNamesAttribute instanceof SetBinding ) { + final SetBinding collectionBinding = (SetBinding) modifiedEntityNamesAttribute; + final String elementType = + collectionBinding + .getPluralAttributeElementBinding() + .getHibernateTypeDescriptor() + .getJavaTypeDescriptor().getName().toString(); + if ( String.class.getName().equals( elementType ) ) { + modifiedEntityNamesData = new PropertyData( + modifiedEntityNamesProperty, + modifiedEntityNamesProperty, + modifiedEntityNamesAttribute.getPropertyAccessorName(), + null + ); + modifiedEntityNamesFound.set(); + } } - else { + + if ( !modifiedEntityNamesFound.isSet() ) { throw new MappingException( - "The field annotated with @ModifiedEntityNames must be of Set type." + "Field annotated with @ModifiedEntityNames must be of Set type." ); } } @@ -287,135 +361,136 @@ else if ( reflectionManager.equals( revisionNumberClass, Long.class ) || } private void searchForRevisionInfoCfg( - XClass clazz, ReflectionManager reflectionManager, - MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound, + ClassInfo revisionInfoEntityClassInfo, + EntityBinding revisionInfoEntityBinding, + AdditionalJaxbRootProducerContext context, + MutableBoolean revisionNumberFound, + MutableBoolean revisionTimestampFound, MutableBoolean modifiedEntityNamesFound) { - final XClass superclazz = clazz.getSuperclass(); - if ( !"java.lang.Object".equals( superclazz.getName() ) ) { - searchForRevisionInfoCfg( - superclazz, - reflectionManager, - revisionNumberFound, - revisionTimestampFound, - modifiedEntityNamesFound - ); - } - - searchForRevisionInfoCfgInProperties( - clazz, reflectionManager, revisionNumberFound, revisionTimestampFound, - modifiedEntityNamesFound, "field" + searchForRevisionNumberCfg( revisionInfoEntityClassInfo, revisionInfoEntityBinding, context, revisionNumberFound ); + searchForRevisionTimestampCfg( + revisionInfoEntityClassInfo, + revisionInfoEntityBinding, + context, + revisionTimestampFound ); - searchForRevisionInfoCfgInProperties( - clazz, reflectionManager, revisionNumberFound, revisionTimestampFound, - modifiedEntityNamesFound, "property" + searchForModifiedEntityNamesCfg( + revisionInfoEntityClassInfo, + revisionInfoEntityBinding, + context, + modifiedEntityNamesFound ); } - public RevisionInfoConfigurationResult configure(Configuration cfg, ReflectionManager reflectionManager) { + public RevisionInfoConfigurationResult configure( + InFlightMetadataCollector metadataCollector, + AdditionalJaxbRootProducerContext context) { + + final ClassLoaderService classLoaderService = context.getServiceRegistry().getService( ClassLoaderService.class ); + boolean revisionEntityFound = false; RevisionInfoGenerator revisionInfoGenerator = null; - Class revisionInfoClass = null; - - final Iterator classes = cfg.getClassMappings(); - while ( classes.hasNext() ) { - PersistentClass pc = classes.next(); - XClass clazz; - try { - clazz = reflectionManager.classForName( pc.getClassName(), this.getClass() ); - } - catch (ClassNotFoundException e) { - throw new MappingException( e ); - } + Class revisionInfoEntityClass = null; - final RevisionEntity revisionEntity = clazz.getAnnotation( RevisionEntity.class ); - if ( revisionEntity != null ) { - if ( revisionEntityFound ) { - throw new MappingException( "Only one entity may be annotated with @RevisionEntity!" ); - } + // Locate @RevisionEntity provided by user and validate its mapping. + Collection revisionEntityAnnotations = context.getJandexIndex().getAnnotations( + EnversDotNames.REVISION_ENTITY + ); + if ( revisionEntityAnnotations.size() > 1 ) { + throw new MappingException( "Only one entity may be annotated with @RevisionEntity." ); + } + if ( revisionEntityAnnotations.size() == 1 ) { + final AnnotationInstance revisionEntityAnnotation = revisionEntityAnnotations.iterator().next(); + final ClassInfo revisionInfoEntityClassInfo = (ClassInfo) revisionEntityAnnotation.target(); - // Checking if custom revision entity isn't audited - if ( clazz.getAnnotation( Audited.class ) != null ) { - throw new MappingException( "An entity annotated with @RevisionEntity cannot be audited!" ); - } + // TODO: Get rid of revisionInfoEntityClass (don't want to load the class). + revisionInfoEntityClass = classLoaderService.classForName( revisionInfoEntityClassInfo.name().toString() ); - revisionEntityFound = true; + // TODO: get entity name from @Entity + revisionInfoEntityName = revisionInfoEntityClass.getName(); - final MutableBoolean revisionNumberFound = new MutableBoolean(); - final MutableBoolean revisionTimestampFound = new MutableBoolean(); - final MutableBoolean modifiedEntityNamesFound = new MutableBoolean(); + final EntityBinding revisionInfoEntityBinding = metadataCollector.getEntityBinding( + revisionInfoEntityName + ); - searchForRevisionInfoCfg( - clazz, - reflectionManager, - revisionNumberFound, - revisionTimestampFound, - modifiedEntityNamesFound - ); + if ( revisionInfoEntityClassInfo.annotations().containsKey( EnversDotNames.AUDITED ) ) { + throw new MappingException( "An entity annotated with @RevisionEntity cannot be audited." ); + } - if ( !revisionNumberFound.isSet() ) { - throw new MappingException( - "An entity annotated with @RevisionEntity must have a field annotated " + - "with @RevisionNumber!" - ); - } + MutableBoolean revisionNumberFound = new MutableBoolean(); + MutableBoolean revisionTimestampFound = new MutableBoolean(); + MutableBoolean modifiedEntityNamesFound = new MutableBoolean(); - if ( !revisionTimestampFound.isSet() ) { - throw new MappingException( - "An entity annotated with @RevisionEntity must have a field annotated " + - "with @RevisionTimestamp!" - ); - } + searchForRevisionInfoCfg( + revisionInfoEntityClassInfo, + revisionInfoEntityBinding, + context, + revisionNumberFound, + revisionTimestampFound, + modifiedEntityNamesFound + ); - revisionInfoEntityName = pc.getEntityName(); - revisionInfoClass = pc.getMappedClass(); - final Class revisionListenerClass = getRevisionListenerClass( revisionEntity.value() ); - revisionInfoTimestampType = pc.getProperty( revisionInfoTimestampData.getName() ).getType(); - if ( globalCfg.isTrackEntitiesChangedInRevision() - || (globalCfg.isUseRevisionEntityWithNativeId() && DefaultTrackingModifiedEntitiesRevisionEntity.class - .isAssignableFrom( revisionInfoClass )) - || (!globalCfg.isUseRevisionEntityWithNativeId() && SequenceIdTrackingModifiedEntitiesRevisionEntity.class - .isAssignableFrom( revisionInfoClass )) - || modifiedEntityNamesFound.isSet() ) { - // If tracking modified entities parameter is enabled, custom revision info entity is a subtype - // of DefaultTrackingModifiedEntitiesRevisionEntity class, or @ModifiedEntityNames annotation is used. - revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator( - revisionInfoEntityName, - revisionInfoClass, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(), - modifiedEntityNamesData - ); - globalCfg.setTrackEntitiesChangedInRevision( true ); - } - else { - revisionInfoGenerator = new DefaultRevisionInfoGenerator( - revisionInfoEntityName, revisionInfoClass, - revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate() - ); - } + if ( !revisionNumberFound.isSet() ) { + throw new MappingException( + "An entity annotated with @RevisionEntity must have a field annotated with @RevisionNumber!" + ); + } + + if ( !revisionTimestampFound.isSet() ) { + throw new MappingException( + "An entity annotated with @RevisionEntity must have a field annotated with @RevisionTimestamp!" + ); + } + + Class revisionListenerClass = getRevisionListenerClass( + classLoaderService, + revisionEntityAnnotation + ); + revisionInfoTimestampType = + revisionInfoEntityBinding.locateAttributeBinding( revisionInfoTimestampData.getName() ) + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + if ( globalCfg.isTrackEntitiesChangedInRevision() + || ( globalCfg.isUseRevisionEntityWithNativeId() && DefaultTrackingModifiedEntitiesRevisionEntity.class.isAssignableFrom( revisionInfoEntityClass ) ) + || ( !globalCfg.isUseRevisionEntityWithNativeId() && SequenceIdTrackingModifiedEntitiesRevisionEntity.class.isAssignableFrom( revisionInfoEntityClass ) ) + || modifiedEntityNamesFound.isSet() ) { + // If tracking modified entities parameter is enabled, custom revision info entity is a subtype + // of DefaultTrackingModifiedEntitiesRevisionEntity class, or @ModifiedEntityNames annotation is used. + revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator( + revisionInfoEntityBinding.getEntity().getName(), revisionInfoEntityClass, + revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(), modifiedEntityNamesData + ); + globalCfg.setTrackEntitiesChangedInRevision( true ); + } + else { + revisionInfoGenerator = new DefaultRevisionInfoGenerator( + revisionInfoEntityBinding.getEntity().getName(), revisionInfoEntityClass, + revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate() + ); } } // In case of a custom revision info generator, the mapping will be null. Document revisionInfoXmlMapping = null; - final Class revisionListenerClass = getRevisionListenerClass( RevisionListener.class ); - if ( revisionInfoGenerator == null ) { + final Class revisionListenerClass = getRevisionListenerClass( classLoaderService, null ); if ( globalCfg.isTrackEntitiesChangedInRevision() ) { - revisionInfoClass = globalCfg.isUseRevisionEntityWithNativeId() ? - DefaultTrackingModifiedEntitiesRevisionEntity.class - : + revisionInfoEntityClass = globalCfg.isUseRevisionEntityWithNativeId() ? + DefaultTrackingModifiedEntitiesRevisionEntity.class : SequenceIdTrackingModifiedEntitiesRevisionEntity.class; - revisionInfoEntityName = revisionInfoClass.getName(); + revisionInfoEntityName = revisionInfoEntityClass.getName(); revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator( - revisionInfoEntityName, revisionInfoClass, + revisionInfoEntityName, revisionInfoEntityClass, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(), modifiedEntityNamesData ); } else { - revisionInfoClass = globalCfg.isUseRevisionEntityWithNativeId() ? DefaultRevisionEntity.class - : SequenceIdRevisionEntity.class; + revisionInfoEntityClass = globalCfg.isUseRevisionEntityWithNativeId() ? + DefaultRevisionEntity.class : + SequenceIdRevisionEntity.class; revisionInfoGenerator = new DefaultRevisionInfoGenerator( - revisionInfoEntityName, revisionInfoClass, + revisionInfoEntityName, revisionInfoEntityClass, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate() ); } @@ -429,13 +504,13 @@ revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate() revisionInfoTimestampData.getName(), isTimestampAsDate() ), generateRevisionInfoRelationMapping(), - new RevisionInfoNumberReader( revisionInfoClass, revisionInfoIdData ), + new RevisionInfoNumberReader( revisionInfoEntityClass, revisionInfoIdData ), globalCfg.isTrackEntitiesChangedInRevision() ? new ModifiedEntityNamesReader( - revisionInfoClass, + revisionInfoEntityClass, modifiedEntityNamesData ) : null, - revisionInfoEntityName, revisionInfoClass, revisionInfoTimestampData + revisionInfoEntityName, revisionInfoEntityClass, revisionInfoTimestampData ); } @@ -445,15 +520,21 @@ private boolean isTimestampAsDate() { } /** - * @param defaultListener Revision listener that shall be applied if {@code org.hibernate.envers.revision_listener} - * parameter has not been set. - * + * Method takes into consideration {@code org.hibernate.envers.revision_listener} parameter and custom + * {@link RevisionEntity} annotation. + * @param classLoaderService Class loading service. + * @param revisionEntityAnnotation User defined @RevisionEntity annotation, or {@code null} if none. * @return Revision listener. */ - private Class getRevisionListenerClass(Class defaultListener) { + private Class getRevisionListenerClass(ClassLoaderService classLoaderService, + AnnotationInstance revisionEntityAnnotation) { if ( globalCfg.getRevisionListenerClass() != null ) { return globalCfg.getRevisionListenerClass(); } - return defaultListener; + if ( revisionEntityAnnotation != null && revisionEntityAnnotation.value() != null ) { + // User provided revision listener implementation in @RevisionEntity mapping. + return classLoaderService.classForName( revisionEntityAnnotation.value().asString() ); + } + return RevisionListener.class; } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java index adb256a6d0f6..0aa65111327b 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java @@ -23,18 +23,17 @@ */ package org.hibernate.envers.configuration.internal.metadata; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.hibernate.MappingException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.Configuration; import org.hibernate.envers.RelationTargetAuditMode; -import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration; -import org.hibernate.envers.configuration.internal.GlobalConfiguration; import org.hibernate.envers.configuration.internal.metadata.reader.ClassAuditingData; import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData; +import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.envers.internal.EnversMessageLogger; import org.hibernate.envers.internal.entities.EntityConfiguration; import org.hibernate.envers.internal.entities.IdMappingData; @@ -46,13 +45,16 @@ import org.hibernate.envers.internal.tools.Triple; import org.hibernate.envers.strategy.AuditStrategy; import org.hibernate.envers.strategy.ValidityAuditStrategy; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.OneToOne; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.OneToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.type.CollectionType; import org.hibernate.type.ComponentType; import org.hibernate.type.ManyToOneType; @@ -78,12 +80,8 @@ public final class AuditMetadataGenerator { EnversMessageLogger.class, AuditMetadataGenerator.class.getName() ); - - private final Configuration cfg; - private final GlobalConfiguration globalCfg; - private final AuditEntitiesConfiguration verEntCfg; + private final AuditConfiguration.AuditConfigurationContext context; private final AuditStrategy auditStrategy; - private final ClassLoaderService classLoaderService; private final Element revisionInfoRelationMapping; /* @@ -102,32 +100,31 @@ public final class AuditMetadataGenerator { private final AuditEntityNameRegister auditEntityNameRegister; + // TODO: add support for secondary tables. // Map entity name -> (join descriptor -> element describing the "versioned" join) - private final Map> entitiesJoins; + //private final Map> entitiesJoins; public AuditMetadataGenerator( - Configuration cfg, GlobalConfiguration globalCfg, - AuditEntitiesConfiguration verEntCfg, - AuditStrategy auditStrategy, ClassLoaderService classLoaderService, + AuditConfiguration.AuditConfigurationContext context, + AuditStrategy auditStrategy, Element revisionInfoRelationMapping, AuditEntityNameRegister auditEntityNameRegister) { - this.cfg = cfg; - this.globalCfg = globalCfg; - this.verEntCfg = verEntCfg; + this.context = context; this.auditStrategy = auditStrategy; - this.classLoaderService = classLoaderService; this.revisionInfoRelationMapping = revisionInfoRelationMapping; this.basicMetadataGenerator = new BasicMetadataGenerator(); - this.componentMetadataGenerator = new ComponentMetadataGenerator( this ); - this.idMetadataGenerator = new IdMetadataGenerator( this ); + this.componentMetadataGenerator = new ComponentMetadataGenerator( context, this ); + this.idMetadataGenerator = new IdMetadataGenerator( context, this ); this.toOneRelationMetadataGenerator = new ToOneRelationMetadataGenerator( this ); this.auditEntityNameRegister = auditEntityNameRegister; entitiesConfigurations = new HashMap(); notAuditedEntitiesConfigurations = new HashMap(); - entitiesJoins = new HashMap>(); + + // TODO: add support for secondary tables. + //entitiesJoins = new HashMap>(); } /** @@ -138,12 +135,12 @@ public AuditMetadataGenerator( */ private Element cloneAndSetupRevisionInfoRelationMapping() { final Element revMapping = (Element) revisionInfoRelationMapping.clone(); - revMapping.addAttribute( "name", verEntCfg.getRevisionFieldName() ); - if ( globalCfg.isCascadeDeleteRevision() ) { + revMapping.addAttribute( "name", context.getAuditEntitiesConfiguration().getRevisionFieldName() ); + if ( context.getGlobalConfiguration().isCascadeDeleteRevision() ) { revMapping.addAttribute( "on-delete", "cascade" ); } - MetadataTools.addOrModifyColumn( revMapping, verEntCfg.getRevisionFieldName() ); + MetadataTools.addOrModifyColumn( revMapping, context.getAuditEntitiesConfiguration().getRevisionFieldName() ); return revMapping; } @@ -152,13 +149,13 @@ void addRevisionInfoRelation(Element anyMapping) { anyMapping.add( cloneAndSetupRevisionInfoRelationMapping() ); } - void addRevisionType(Element anyMapping, Element anyMappingEnd) { + void addRevisionType(Element anyMapping, Element anyMappingEnd, boolean key) { final Element revTypeProperty = MetadataTools.addProperty( anyMapping, - verEntCfg.getRevisionTypePropName(), - verEntCfg.getRevisionTypePropType(), + context.getAuditEntitiesConfiguration().getRevisionTypePropName(), + context.getAuditEntitiesConfiguration().getRevisionTypePropType(), true, - false + key ); revTypeProperty.addAttribute( "type", "org.hibernate.envers.internal.entities.RevisionTypeType" ); @@ -171,17 +168,17 @@ private void addEndRevision(Element anyMapping) { if ( auditStrategy instanceof ValidityAuditStrategy ) { final Element endRevMapping = (Element) revisionInfoRelationMapping.clone(); endRevMapping.setName( "many-to-one" ); - endRevMapping.addAttribute( "name", verEntCfg.getRevisionEndFieldName() ); - MetadataTools.addOrModifyColumn( endRevMapping, verEntCfg.getRevisionEndFieldName() ); + endRevMapping.addAttribute( "name", context.getAuditEntitiesConfiguration().getRevisionEndFieldName() ); + MetadataTools.addOrModifyColumn( endRevMapping, context.getAuditEntitiesConfiguration().getRevisionEndFieldName() ); anyMapping.add( endRevMapping ); - if ( verEntCfg.isRevisionEndTimestampEnabled() ) { + if ( context.getAuditEntitiesConfiguration().isRevisionEndTimestampEnabled() ) { // add a column for the timestamp of the end revision final String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName(); final Element timestampProperty = MetadataTools.addProperty( anyMapping, - verEntCfg.getRevisionEndTimestampFieldName(), + context.getAuditEntitiesConfiguration().getRevisionEndTimestampFieldName(), revisionInfoTimestampSqlType, true, true, @@ -189,7 +186,7 @@ private void addEndRevision(Element anyMapping) { ); MetadataTools.addColumn( timestampProperty, - verEntCfg.getRevisionEndTimestampFieldName(), + context.getAuditEntitiesConfiguration().getRevisionEndTimestampFieldName(), null, null, null, @@ -203,20 +200,33 @@ private void addEndRevision(Element anyMapping) { private void addValueInFirstPass( Element parent, - Value value, + AttributeBinding attributeBinding, CompositeMapperBuilder currentMapper, String entityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData, - boolean insertable, boolean processModifiedFlag) { - final Type type = value.getType(); + final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + + final List values; + final boolean isInsertable; + if ( attributeBinding.getAttribute().isSingular() ) { + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + values = singularAttributeBinding.getValues(); + isInsertable = singularAttributeBinding.isIncludedInInsert(); + } + else { + values = null; + isInsertable = false; + } + final boolean isBasic = basicMetadataGenerator.addBasic( parent, propertyAuditingData, - value, + attributeBinding.getHibernateTypeDescriptor(), + values, + isInsertable, currentMapper, - insertable, false ); @@ -225,8 +235,13 @@ private void addValueInFirstPass( } else if ( type instanceof ComponentType ) { componentMetadataGenerator.addComponent( - parent, propertyAuditingData, value, currentMapper, - entityName, xmlMappingData, true + parent, + propertyAuditingData, + (EmbeddedAttributeBinding) attributeBinding, + currentMapper, + entityName, + xmlMappingData, + true ); } else { @@ -247,20 +262,19 @@ private boolean processedInSecondPass(Type type) { private void addValueInSecondPass( Element parent, - Value value, + AttributeBinding attributeBinding, CompositeMapperBuilder currentMapper, String entityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData, - boolean insertable, boolean processModifiedFlag) { - final Type type = value.getType(); + final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); if ( type instanceof ComponentType ) { componentMetadataGenerator.addComponent( parent, propertyAuditingData, - value, + (EmbeddedAttributeBinding) attributeBinding, currentMapper, entityName, xmlMappingData, @@ -273,18 +287,17 @@ else if ( type instanceof ManyToOneType ) { toOneRelationMetadataGenerator.addToOne( parent, propertyAuditingData, - value, + (ManyToOneAttributeBinding) attributeBinding, currentMapper, - entityName, - insertable + entityName ); } else if ( type instanceof OneToOneType ) { - final OneToOne oneToOne = (OneToOne) value; - if ( oneToOne.getReferencedPropertyName() != null ) { + final OneToOneAttributeBinding oneToOneAttributeBinding = (OneToOneAttributeBinding) attributeBinding; + if ( oneToOneAttributeBinding.getReferencedAttributeBinding().getAttribute().getName() != null ) { toOneRelationMetadataGenerator.addOneToOneNotOwning( propertyAuditingData, - value, + oneToOneAttributeBinding, currentMapper, entityName ); @@ -293,17 +306,17 @@ else if ( type instanceof OneToOneType ) { // @OneToOne relation marked with @PrimaryKeyJoinColumn toOneRelationMetadataGenerator.addOneToOnePrimaryKeyJoinColumn( propertyAuditingData, - value, + oneToOneAttributeBinding, currentMapper, - entityName, - insertable + entityName ); } } else if ( type instanceof CollectionType ) { final CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator( + context, this, - (Collection) value, + (PluralAttributeBinding) attributeBinding, currentMapper, entityName, xmlMappingData, @@ -325,50 +338,53 @@ private void addModifiedFlagIfNeeded( MetadataTools.addModifiedFlagProperty( parent, propertyAuditingData.getName(), - globalCfg.getModifiedFlagSuffix() + context.getGlobalConfiguration().getModifiedFlagSuffix() ); } } void addValue( - Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName, - EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData, - boolean insertable, boolean firstPass, boolean processModifiedFlag) { + Element parent, + AttributeBinding attributeBinding, + CompositeMapperBuilder currentMapper, + String entityName, + EntityXmlMappingData xmlMappingData, + PropertyAuditingData propertyAuditingData, + boolean firstPass, + boolean processModifiedFlag) { if ( firstPass ) { addValueInFirstPass( - parent, value, currentMapper, entityName, - xmlMappingData, propertyAuditingData, insertable, processModifiedFlag + parent, attributeBinding, currentMapper, entityName, + xmlMappingData, propertyAuditingData, processModifiedFlag ); } else { addValueInSecondPass( - parent, value, currentMapper, entityName, - xmlMappingData, propertyAuditingData, insertable, processModifiedFlag + parent, attributeBinding, currentMapper, entityName, + xmlMappingData, propertyAuditingData, processModifiedFlag ); } } private void addProperties( Element parent, - Iterator properties, + AttributeBinding[] properties, CompositeMapperBuilder currentMapper, ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData, boolean firstPass) { - while ( properties.hasNext() ) { - final Property property = properties.next(); - final String propertyName = property.getName(); + for ( AttributeBinding property : properties ) { + final String propertyName = property.getAttribute().getName(); final PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData( propertyName ); if ( propertyAuditingData != null ) { addValue( parent, - property.getValue(), + property, currentMapper, entityName, xmlMappingData, propertyAuditingData, - property.isInsertable(), firstPass, true ); @@ -376,10 +392,10 @@ private void addProperties( } } - private boolean checkPropertiesAudited(Iterator properties, ClassAuditingData auditingData) { + private boolean checkPropertiesAudited(Iterator properties, ClassAuditingData auditingData) { while ( properties.hasNext() ) { - final Property property = properties.next(); - final String propertyName = property.getName(); + final AttributeBinding property = properties.next(); + final String propertyName = property.getAttribute().getName(); final PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData( propertyName ); if ( propertyAuditingData == null ) { return false; @@ -389,151 +405,193 @@ private boolean checkPropertiesAudited(Iterator properties, ClassAudit return true; } - protected String getSchema(String schemaFromAnnotation, Table table) { + protected String getSchema(String schemaFromAnnotation, TableSpecification table) { // Get the schema from the annotation ... String schema = schemaFromAnnotation; // ... if empty, try using the default ... if ( StringTools.isEmpty( schema ) ) { - schema = globalCfg.getDefaultSchemaName(); + schema = context.getGlobalConfiguration().getDefaultSchemaName(); // ... if still empty, use the same as the normal table. - if ( StringTools.isEmpty( schema ) ) { - schema = table.getSchema(); + if ( StringTools.isEmpty( schema ) && table.getSchema().getName().getSchema() != null) { + schema = table.getSchema().getName().getSchema().getText(); } } return schema; } - protected String getCatalog(String catalogFromAnnotation, Table table) { + protected String getCatalog(String catalogFromAnnotation, TableSpecification table) { // Get the catalog from the annotation ... String catalog = catalogFromAnnotation; // ... if empty, try using the default ... if ( StringTools.isEmpty( catalog ) ) { - catalog = globalCfg.getDefaultCatalogName(); + catalog = context.getGlobalConfiguration().getDefaultCatalogName(); // ... if still empty, use the same as the normal table. - if ( StringTools.isEmpty( catalog ) ) { - catalog = table.getCatalog(); + if ( StringTools.isEmpty( catalog ) && table.getSchema().getName().getCatalog() != null ) { + catalog = table.getSchema().getName().getCatalog().getText(); } } return catalog; } - @SuppressWarnings({"unchecked"}) - private void createJoins(PersistentClass pc, Element parent, ClassAuditingData auditingData) { - final Iterator joins = pc.getJoinIterator(); - final Map joinElements = new HashMap(); - entitiesJoins.put( pc.getEntityName(), joinElements ); + // TODO: add support for secondary tables +// private void createJoins(EntityBinding entityBinding, Element parent, ClassAuditingData auditingData) { +// final Iterator joins = entityBinding.getSecondaryTables(); +// final Map joinElements = new HashMap(); +// entitiesJoins.put( entityBinding.getEntityName(), joinElements ); - while ( joins.hasNext() ) { - Join join = joins.next(); +// while ( joins.hasNext() ) { +// SecondaryTable join = joins.next(); // Checking if all of the join properties are audited - if ( !checkPropertiesAudited( join.getPropertyIterator(), auditingData ) ) { - continue; - } +// if ( !checkPropertiesAudited( join.getPropertyIterator(), auditingData ) ) { +// continue; +// } // Determining the table name. If there is no entry in the dictionary, just constructing the table name // as if it was an entity (by appending/prepending configured strings). - final String originalTableName = join.getTable().getName(); - String auditTableName = auditingData.getSecondaryTableDictionary().get( originalTableName ); - if ( auditTableName == null ) { - auditTableName = verEntCfg.getAuditEntityName( originalTableName ); - } - - final String schema = getSchema( auditingData.getAuditTable().schema(), join.getTable() ); - final String catalog = getCatalog( auditingData.getAuditTable().catalog(), join.getTable() ); - - final Element joinElement = MetadataTools.createJoin( parent, auditTableName, schema, catalog ); - joinElements.put( join, joinElement ); - - final Element joinKey = joinElement.addElement( "key" ); - MetadataTools.addColumns( joinKey, join.getKey().getColumnIterator() ); - MetadataTools.addColumn( joinKey, verEntCfg.getRevisionFieldName(), null, null, null, null, null, null ); - } - } - - @SuppressWarnings({"unchecked"}) - private void addJoins( - PersistentClass pc, - CompositeMapperBuilder currentMapper, - ClassAuditingData auditingData, - String entityName, - EntityXmlMappingData xmlMappingData, - boolean firstPass) { - final Iterator joins = pc.getJoinIterator(); +// final String originalTableName = join.getSecondaryTableReference().getLogicalName().getText(); +// String auditTableName = auditingData.getSecondaryTableDictionary().get( originalTableName ); +// if ( auditTableName == null ) { +// auditTableName = context.getAuditEntitiesConfiguration().getAuditEntityName( originalTableName ); +// } + +// final String schema = getSchema( auditingData.getAuditTable().schema(), join.getSecondaryTableReference() ); +// final String catalog = getCatalog( auditingData.getAuditTable().catalog(), join.getSecondaryTableReference() ); + +// final Element joinElement = MetadataTools.createJoin( parent, auditTableName, schema, catalog ); +// joinElements.put( join, joinElement ); + +// final Element joinKey = joinElement.addElement( "key" ); +// MetadataTools.addColumns( joinKey, join.getForeignKeyReference().getColumns() ); +// MetadataTools.addColumn( joinKey, context.getAuditEntitiesConfiguration().getRevisionFieldName(), null, null, null, null, null, null ); +// } +// } + +// @SuppressWarnings({"unchecked"}) +// private void createJoins(PersistentClass pc, Element parent, ClassAuditingData auditingData) { +// final Iterator joins = pc.getJoinIterator(); +// final Map joinElements = new HashMap(); +// entitiesJoins.put( pc.getEntityName(), joinElements ); +// +// while ( joins.hasNext() ) { +// Join join = joins.next(); - while ( joins.hasNext() ) { - final Join join = joins.next(); - final Element joinElement = entitiesJoins.get( entityName ).get( join ); + // Checking if all of the join properties are audited +// if ( !checkPropertiesAudited( join.getPropertyIterator(), auditingData ) ) { +// continue; +// } - if ( joinElement != null ) { - addProperties( - joinElement, - join.getPropertyIterator(), - currentMapper, - auditingData, - entityName, - xmlMappingData, - firstPass - ); - } - } - } + // Determining the table name. If there is no entry in the dictionary, just constructing the table name + // as if it was an entity (by appending/prepending configured strings). +// final String originalTableName = join.getTable().getName(); +// String auditTableName = auditingData.getSecondaryTableDictionary().get( originalTableName ); +// if ( auditTableName == null ) { +// auditTableName = verEntCfg.getAuditEntityName( originalTableName ); +// } + +// final String schema = getSchema( auditingData.getAuditTable().schema(), join.getTable() ); +// final String catalog = getCatalog( auditingData.getAuditTable().catalog(), join.getTable() ); + +// final Element joinElement = MetadataTools.createJoin( parent, auditTableName, schema, catalog ); +// joinElements.put( join, joinElement ); + +// final Element joinKey = joinElement.addElement( "key" ); +// MetadataTools.addColumns( joinKey, join.getKey().getColumnIterator() ); +// MetadataTools.addColumn( joinKey, verEntCfg.getRevisionFieldName(), null, null, null, null, null, null ); +// } +// } + +// @SuppressWarnings({"unchecked"}) +// private void addJoins( +// PersistentClass pc, +// CompositeMapperBuilder currentMapper, +// ClassAuditingData auditingData, +// String entityName, +// EntityXmlMappingData xmlMappingData, +// boolean firstPass) { +// final Iterator joins = pc.getJoinIterator(); + +// while ( joins.hasNext() ) { +// final Join join = joins.next(); +// final Element joinElement = entitiesJoins.get( entityName ).get( join ); + +// if ( joinElement != null ) { +// addProperties( +// joinElement, +// join.getPropertyIterator(), +// currentMapper, +// auditingData, +// entityName, +// xmlMappingData, +// firstPass +// ); +// } +// } +// } @SuppressWarnings({"unchecked"}) private Triple generateMappingData( - PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, + EntityBinding entityBinding, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, IdMappingData idMapper) { final Element classMapping = MetadataTools.createEntity( xmlMappingData.getMainXmlMapping(), auditTableData, - pc.getDiscriminatorValue(), - pc.isAbstract() + entityBinding.getDiscriminatorMatchValue(), + entityBinding.isAbstract() ); final ExtendedPropertyMapper propertyMapper = new MultiPropertyMapper(); + // Adding the id mapping + classMapping.add( (Element) idMapper.getXmlMapping().clone() ); + // Checking if there is a discriminator column - if ( pc.getDiscriminator() != null ) { + if ( entityBinding.getHierarchyDetails().getEntityDiscriminator() != null ) { + final EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator(); final Element discriminatorElement = classMapping.addElement( "discriminator" ); // Database column or SQL formula allowed to distinguish entity types - MetadataTools.addColumnsOrFormulas( discriminatorElement, pc.getDiscriminator().getColumnIterator() ); - discriminatorElement.addAttribute( "type", pc.getDiscriminator().getType().getName() ); + MetadataTools.addColumnsOrFormulas( + discriminatorElement, + Collections.singletonList( discriminator.getRelationalValue() ) + ); + discriminatorElement.addAttribute( + "type", + discriminator.getExplicitHibernateTypeDescriptor().getExplicitTypeName() + ); } - // Adding the id mapping - classMapping.add( (Element) idMapper.getXmlMapping().clone() ); - // Adding the "revision type" property - addRevisionType( classMapping, classMapping ); + addRevisionType( classMapping, classMapping, false ); return Triple.make( classMapping, propertyMapper, null ); } private Triple generateInheritanceMappingData( - PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, + EntityBinding entityBinding, + EntityXmlMappingData xmlMappingData, + AuditTableData auditTableData, String inheritanceMappingType) { - final String extendsEntityName = verEntCfg.getAuditEntityName( pc.getSuperclass().getEntityName() ); + final String parentEntityName = entityBinding.getSuperEntityBinding().getEntityName(); + final String extendsEntityName = context.getAuditEntitiesConfiguration().getAuditEntityName( parentEntityName ); final Element classMapping = MetadataTools.createSubclassEntity( xmlMappingData.getMainXmlMapping(), inheritanceMappingType, auditTableData, extendsEntityName, - pc.getDiscriminatorValue(), - pc.isAbstract() + entityBinding.getDiscriminatorMatchValue(), + entityBinding.isAbstract() ); // The id and revision type is already mapped in the parent // Getting the property mapper of the parent - when mapping properties, they need to be included - final String parentEntityName = pc.getSuperclass().getEntityName(); - final EntityConfiguration parentConfiguration = entitiesConfigurations.get( parentEntityName ); if ( parentConfiguration == null ) { throw new MappingException( - "Entity '" + pc.getEntityName() + "' is audited, but its superclass: '" + + "Entity '" + entityBinding.getEntityName() + "' is audited, but its superclass: '" + parentEntityName + "' is not." ); } @@ -549,16 +607,16 @@ private Triple generateInheritanceMappi @SuppressWarnings({"unchecked"}) public void generateFirstPass( - PersistentClass pc, + EntityBinding entityBinding, ClassAuditingData auditingData, EntityXmlMappingData xmlMappingData, boolean isAudited) { - final String schema = getSchema( auditingData.getAuditTable().schema(), pc.getTable() ); - final String catalog = getCatalog( auditingData.getAuditTable().catalog(), pc.getTable() ); + final String schema = getSchema( auditingData.getAuditTable().schema(), entityBinding.getPrimaryTable() ); + final String catalog = getCatalog( auditingData.getAuditTable().catalog(), entityBinding.getPrimaryTable() ); if ( !isAudited ) { - final String entityName = pc.getEntityName(); - final IdMappingData idMapper = idMetadataGenerator.addId( pc, false ); + final String entityName = entityBinding.getEntityName(); + final IdMappingData idMapper = idMetadataGenerator.addId( entityBinding, false ); if ( idMapper == null ) { // Unsupported id mapping, e.g. key-many-to-one. If the entity is used in auditing, an exception @@ -574,7 +632,7 @@ public void generateFirstPass( final String parentEntityName = null; final EntityConfiguration entityCfg = new EntityConfiguration( entityName, - pc.getClassName(), + entityBinding.getEntity().getDescriptor().getName().toString(), idMapper, propertyMapper, parentEntityName @@ -583,11 +641,14 @@ public void generateFirstPass( return; } - final String entityName = pc.getEntityName(); + final String entityName = entityBinding.getEntityName(); LOG.debugf( "Generating first-pass auditing mapping for entity %s", entityName ); - final String auditEntityName = verEntCfg.getAuditEntityName( entityName ); - final String auditTableName = verEntCfg.getAuditTableName( entityName, pc.getTable().getName() ); + final String auditEntityName = context.getAuditEntitiesConfiguration().getAuditEntityName( entityName ); + final String auditTableName = context.getAuditEntitiesConfiguration().getAuditTableName( + entityName, + entityBinding.getPrimaryTableName() + ); // Registering the audit entity name, now that it is known auditEntityNameRegister.register( auditEntityName ); @@ -595,9 +656,9 @@ public void generateFirstPass( final AuditTableData auditTableData = new AuditTableData( auditEntityName, auditTableName, schema, catalog ); // Generating a mapping for the id - final IdMappingData idMapper = idMetadataGenerator.addId( pc, true ); + final IdMappingData idMapper = idMetadataGenerator.addId( entityBinding, true ); - final InheritanceType inheritanceType = InheritanceType.get( pc ); + final InheritanceType inheritanceType = InheritanceType.get( entityBinding ); // These properties will be read from the mapping data final Element classMapping; @@ -609,26 +670,26 @@ public void generateFirstPass( // Reading the mapping data depending on inheritance type (if any) switch ( inheritanceType ) { case NONE: - mappingData = generateMappingData( pc, xmlMappingData, auditTableData, idMapper ); + mappingData = generateMappingData( entityBinding, xmlMappingData, auditTableData, idMapper ); break; case SINGLE: - mappingData = generateInheritanceMappingData( pc, xmlMappingData, auditTableData, "subclass" ); + mappingData = generateInheritanceMappingData( entityBinding, xmlMappingData, auditTableData, "subclass" ); break; case JOINED: - mappingData = generateInheritanceMappingData( pc, xmlMappingData, auditTableData, "joined-subclass" ); + mappingData = generateInheritanceMappingData( entityBinding, xmlMappingData, auditTableData, "joined-subclass" ); // Adding the "key" element with all id columns... final Element keyMapping = mappingData.getFirst().addElement( "key" ); - MetadataTools.addColumns( keyMapping, pc.getTable().getPrimaryKey().columnIterator() ); + MetadataTools.addColumns( keyMapping, entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ); // ... and the revision number column, read from the revision info relation mapping. keyMapping.add( (Element) cloneAndSetupRevisionInfoRelationMapping().element( "column" ).clone() ); break; case TABLE_PER_CLASS: - mappingData = generateInheritanceMappingData( pc, xmlMappingData, auditTableData, "union-subclass" ); + mappingData = generateInheritanceMappingData( entityBinding, xmlMappingData, auditTableData, "union-subclass" ); break; default: @@ -643,32 +704,38 @@ public void generateFirstPass( // Mapping unjoined properties addProperties( - classMapping, pc.getUnjoinedPropertyIterator(), propertyMapper, - auditingData, pc.getEntityName(), xmlMappingData, + classMapping, + entityBinding.getNonIdAttributeBindingClosure(), // TODO: this needs to be corrected to only get non-joined attribute bindings. + //entityBinding.getUnjoinedPropertyIterator(), + propertyMapper, + auditingData, + entityBinding.getEntityName(), + xmlMappingData, true ); + // TODO: add support for joins // Creating and mapping joins (first pass) - createJoins( pc, classMapping, auditingData ); - addJoins( pc, propertyMapper, auditingData, pc.getEntityName(), xmlMappingData, true ); + //createJoins( entityBinding, classMapping, auditingData ); + //addJoins( entityBinding, propertyMapper, auditingData, entityBinding.getEntityName(), xmlMappingData, true ); // Storing the generated configuration final EntityConfiguration entityCfg = new EntityConfiguration( auditEntityName, - pc.getClassName(), + entityBinding.getEntity().getDescriptor().getName().toString(), idMapper, propertyMapper, parentEntityName ); - entitiesConfigurations.put( pc.getEntityName(), entityCfg ); + entitiesConfigurations.put( entityBinding.getEntityName(), entityCfg ); } @SuppressWarnings({"unchecked"}) public void generateSecondPass( - PersistentClass pc, + EntityBinding entityBinding, ClassAuditingData auditingData, EntityXmlMappingData xmlMappingData) { - final String entityName = pc.getEntityName(); + final String entityName = entityBinding.getEntityName(); LOG.debugf( "Generating second-pass auditing mapping for entity %s", entityName ); final CompositeMapperBuilder propertyMapper = entitiesConfigurations.get( entityName ).getPropertyMapper(); @@ -678,7 +745,8 @@ public void generateSecondPass( addProperties( parent, - pc.getUnjoinedPropertyIterator(), + entityBinding.getNonIdAttributeBindingClosure(), // TODO: this needs to be corrected to only get non-joined attribute bindings. + //entityBinding.getUnjoinedPropertyIterator(), propertyMapper, auditingData, entityName, @@ -686,8 +754,9 @@ public void generateSecondPass( false ); + // TODO: add suuport for joins // Mapping joins (second pass) - addJoins( pc, propertyMapper, auditingData, entityName, xmlMappingData, false ); + //addJoins( entityBinding, propertyMapper, auditingData, entityName, xmlMappingData, false ); } public Map getEntitiesConfigurations() { @@ -700,26 +769,10 @@ BasicMetadataGenerator getBasicMetadataGenerator() { return basicMetadataGenerator; } - Configuration getCfg() { - return cfg; - } - - GlobalConfiguration getGlobalCfg() { - return globalCfg; - } - - AuditEntitiesConfiguration getVerEntCfg() { - return verEntCfg; - } - AuditStrategy getAuditStrategy() { return auditStrategy; } - ClassLoaderService getClassLoaderService() { - return classLoaderService; - } - AuditEntityNameRegister getAuditEntityNameRegister() { return auditEntityNameRegister; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/BasicMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/BasicMetadataGenerator.java index 3e6f69e7767a..59443cf578be 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/BasicMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/BasicMetadataGenerator.java @@ -23,16 +23,19 @@ */ package org.hibernate.envers.configuration.internal.metadata; -import java.util.Properties; +import java.util.List; +import java.util.Map; import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData; import org.hibernate.envers.internal.entities.mapper.SimpleMapperBuilder; -import org.hibernate.mapping.SimpleValue; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.type.BasicType; import org.hibernate.type.CustomType; import org.hibernate.type.EnumType; -import org.hibernate.type.SerializableToBlobType; import org.hibernate.type.Type; import org.hibernate.usertype.DynamicParameterizedType; @@ -46,21 +49,23 @@ public final class BasicMetadataGenerator { @SuppressWarnings({"unchecked"}) boolean addBasic( - Element parent, PropertyAuditingData propertyAuditingData, - Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) { - final Type type = value.getType(); - - if ( type instanceof BasicType - || type instanceof SerializableToBlobType - || "org.hibernate.type.PrimitiveByteArrayBlobType".equals( type.getClass().getName() ) ) { + Element parent, + PropertyAuditingData propertyAuditingData, + HibernateTypeDescriptor hibernateTypeDescriptor, + List values, + boolean insertable, + SimpleMapperBuilder mapper, + boolean key) { + if ( hibernateTypeDescriptor.getResolvedTypeMapping() instanceof BasicType + || "org.hibernate.type.PrimitiveByteArrayBlobType".equals( + hibernateTypeDescriptor.getJavaTypeDescriptor() + .getName() + .toString() + ) ) { if ( parent != null ) { - final boolean addNestedType = (value instanceof SimpleValue) - && ((SimpleValue) value).getTypeParameters() != null; + final boolean addNestedType = !hibernateTypeDescriptor.getTypeParameters().isEmpty(); - String typeName = type.getName(); - if ( typeName == null ) { - typeName = type.getClass().getName(); - } + final String typeName = resolveTypeName( hibernateTypeDescriptor ); final Element propMapping = MetadataTools.addProperty( parent, @@ -69,22 +74,22 @@ boolean addBasic( propertyAuditingData.isForceInsertable() || insertable, key ); - MetadataTools.addColumns( propMapping, value.getColumnIterator() ); + MetadataTools.addValuesAsColumns( propMapping, values ); if ( addNestedType ) { - final Properties typeParameters = ((SimpleValue) value).getTypeParameters(); + final Map typeParameters = hibernateTypeDescriptor.getTypeParameters(); final Element typeMapping = propMapping.addElement( "type" ); typeMapping.addAttribute( "name", typeName ); if ( "org.hibernate.type.EnumType".equals( typeName ) ) { // Proper handling of enumeration type - mapEnumerationType( typeMapping, type, typeParameters ); + mapEnumerationType( typeMapping, hibernateTypeDescriptor.getResolvedTypeMapping(), typeParameters ); } else { // By default copying all Hibernate properties for ( Object object : typeParameters.keySet() ) { final String keyType = (String) object; - final String property = typeParameters.getProperty( keyType ); + final String property = typeParameters.get( keyType ); if ( property != null ) { typeMapping.addElement( "param" ).addAttribute( "name", keyType ).setText( property ); @@ -106,11 +111,23 @@ boolean addBasic( return true; } - private void mapEnumerationType(Element parent, Type type, Properties parameters) { - if ( parameters.getProperty( EnumType.ENUM ) != null ) { + private String resolveTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) { + final Type type = hibernateTypeDescriptor.getResolvedTypeMapping(); + String typeName = hibernateTypeDescriptor.getExplicitTypeName(); + if ( typeName == null ) { + typeName = type.getName(); + } + if ( typeName == null ) { + typeName = hibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString(); + } + return typeName; + } + + private void mapEnumerationType(Element parent, Type type, Map parameters) { + if ( parameters.get( EnumType.ENUM ) != null ) { parent.addElement( "param" ) .addAttribute( "name", EnumType.ENUM ) - .setText( parameters.getProperty( EnumType.ENUM ) ); + .setText( parameters.get( EnumType.ENUM ) ); } else { parent.addElement( "param" ).addAttribute( "name", EnumType.ENUM ).setText( @@ -118,9 +135,9 @@ private void mapEnumerationType(Element parent, Type type, Properties parameters .getName() ); } - if ( parameters.getProperty( EnumType.NAMED ) != null ) { + if ( parameters.get( EnumType.NAMED ) != null ) { parent.addElement( "param" ).addAttribute( "name", EnumType.NAMED ).setText( - parameters.getProperty( + parameters.get( EnumType.NAMED ) ); @@ -139,15 +156,15 @@ else if ( parameters.get( DynamicParameterizedType.XPROPERTY ) != null ) { boolean addManyToOne( Element parent, PropertyAuditingData propertyAuditingData, - Value value, + ManyToOneAttributeBinding attributeBinding, SimpleMapperBuilder mapper) { - final Type type = value.getType(); + final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); // A null mapper occurs when adding to composite-id element final Element manyToOneElement = parent.addElement( mapper != null ? "many-to-one" : "key-many-to-one" ); manyToOneElement.addAttribute( "name", propertyAuditingData.getName() ); manyToOneElement.addAttribute( "class", type.getName() ); - MetadataTools.addColumns( manyToOneElement, value.getColumnIterator() ); + MetadataTools.addValuesAsColumns( manyToOneElement, attributeBinding.getValues() ); // A null mapper means that we only want to add xml mappings if ( mapper != null ) { diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/CollectionMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/CollectionMetadataGenerator.java index 0452eae10913..21e144709481 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/CollectionMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/CollectionMetadataGenerator.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -34,14 +33,15 @@ import java.util.TreeSet; import javax.persistence.JoinColumn; +import org.hibernate.AssertionFailure; import org.hibernate.MappingException; -import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.envers.ModificationStore; import org.hibernate.envers.RelationTargetAuditMode; import org.hibernate.envers.configuration.internal.metadata.reader.AuditedPropertiesReader; import org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditedPropertiesReader; import org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditingData; import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData; +import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.envers.internal.EnversMessageLogger; import org.hibernate.envers.internal.entities.EntityConfiguration; import org.hibernate.envers.internal.entities.IdMappingData; @@ -78,17 +78,24 @@ import org.hibernate.envers.internal.tools.ReflectionTools; import org.hibernate.envers.internal.tools.StringTools; import org.hibernate.envers.internal.tools.Tools; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.IndexedCollection; -import org.hibernate.mapping.ManyToOne; -import org.hibernate.mapping.OneToMany; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.PluralAttributeNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.EmbeddableBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor; +import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBindingEmbedded; +import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.type.BagType; import org.hibernate.type.ComponentType; +import org.hibernate.type.EntityType; import org.hibernate.type.ListType; import org.hibernate.type.ManyToOneType; import org.hibernate.type.MapType; @@ -113,9 +120,10 @@ public final class CollectionMetadataGenerator { CollectionMetadataGenerator.class.getName() ); + private final AuditConfiguration.AuditConfigurationContext context; private final AuditMetadataGenerator mainGenerator; private final String propertyName; - private final Collection propertyValue; + private final PluralAttributeBinding pluralAttributeBinding; private final CompositeMapperBuilder currentMapper; private final String referencingEntityName; private final EntityXmlMappingData xmlMappingData; @@ -129,7 +137,7 @@ public final class CollectionMetadataGenerator { /** * @param mainGenerator Main generator, giving access to configuration and the basic mapper. - * @param propertyValue Value of the collection, as mapped by Hibernate. + * @param pluralAttributeBinding Value of the collection, as mapped by Hibernate. * @param currentMapper Mapper, to which the appropriate {@link PropertyMapper} will be added. * @param referencingEntityName Name of the entity that owns this collection. * @param xmlMappingData In case this collection requires a middle table, additional mapping documents will @@ -139,12 +147,15 @@ public final class CollectionMetadataGenerator { * table and the value of the @MapKey annotation, if there was one. */ public CollectionMetadataGenerator( + AuditConfiguration.AuditConfigurationContext context, AuditMetadataGenerator mainGenerator, - Collection propertyValue, CompositeMapperBuilder currentMapper, + PluralAttributeBinding pluralAttributeBinding, + CompositeMapperBuilder currentMapper, String referencingEntityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData) { + this.context = context; this.mainGenerator = mainGenerator; - this.propertyValue = propertyValue; + this.pluralAttributeBinding = pluralAttributeBinding; this.currentMapper = currentMapper; this.referencingEntityName = referencingEntityName; this.xmlMappingData = xmlMappingData; @@ -157,17 +168,24 @@ public CollectionMetadataGenerator( throw new MappingException( "Unable to read auditing configuration for " + referencingEntityName + "!" ); } - referencedEntityName = MappingTools.getReferencedEntityName( propertyValue.getElement() ); + referencedEntityName = MappingTools.getReferencedEntityName( pluralAttributeBinding ); } void addCollection() { - final Type type = propertyValue.getType(); - final Value value = propertyValue.getElement(); + final Type type = pluralAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + final PluralAttributeElementNature elementNature = + pluralAttributeBinding.getPluralAttributeElementBinding().getNature(); final boolean oneToManyAttachedType = type instanceof BagType || type instanceof SetType || type instanceof MapType || type instanceof ListType; - final boolean inverseOneToMany = (value instanceof OneToMany) && (propertyValue.isInverse()); - final boolean owningManyToOneWithJoinTableBidirectional = (value instanceof ManyToOne) && (propertyAuditingData.getRelationMappedBy() != null); - final boolean fakeOneToManyBidirectional = (value instanceof OneToMany) && (propertyAuditingData.getAuditMappedBy() != null); + final boolean inverseOneToMany = + (elementNature == PluralAttributeElementNature.ONE_TO_MANY) && + ( pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ); + final boolean owningManyToOneWithJoinTableBidirectional = + (elementNature == PluralAttributeElementNature.MANY_TO_MANY) && + (propertyAuditingData.getRelationMappedBy() != null); + final boolean fakeOneToManyBidirectional = + (elementNature == PluralAttributeElementNature.ONE_TO_MANY) + && (propertyAuditingData.getAuditMappedBy() != null); if ( oneToManyAttachedType && (inverseOneToMany || fakeOneToManyBidirectional || owningManyToOneWithJoinTableBidirectional) ) { // A one-to-many relation mapped using @ManyToOne and @OneToMany(mappedBy="...") @@ -181,7 +199,7 @@ void addCollection() { private MiddleIdData createMiddleIdData(IdMappingData idMappingData, String prefix, String entityName) { return new MiddleIdData( - mainGenerator.getVerEntCfg(), idMappingData, prefix, entityName, + context.getAuditEntitiesConfiguration(), idMappingData, prefix, entityName, mainGenerator.getEntitiesConfigurations().containsKey( entityName ) ); } @@ -194,7 +212,9 @@ private void addOneToManyAttached(boolean fakeOneToManyBidirectional) { propertyName ); - final String mappedBy = getMappedBy( propertyValue ); + final String mappedBy = getMappedBy( + (PluralAttributeAssociationElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding() + ); final IdMappingData referencedIdMapping = mainGenerator.getReferencedIdMappingData( referencingEntityName, @@ -230,8 +250,8 @@ private void addOneToManyAttached(boolean fakeOneToManyBidirectional) { // Generating the query generator - it should read directly from the related entity. final RelationQueryGenerator queryGenerator = new OneAuditEntityQueryGenerator( - mainGenerator.getGlobalCfg(), - mainGenerator.getVerEntCfg(), + context.getGlobalConfiguration(), + context.getAuditEntitiesConfiguration(), mainGenerator.getAuditStrategy(), referencingIdData, referencedEntityName, @@ -241,7 +261,7 @@ private void addOneToManyAttached(boolean fakeOneToManyBidirectional) { // Creating common mapper data. final CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData( - mainGenerator.getVerEntCfg(), referencedEntityName, + context.getAuditEntitiesConfiguration(), referencedEntityName, propertyAuditingData.getPropertyData(), referencingIdData, queryGenerator ); @@ -327,19 +347,19 @@ private void addRelatedToXmlMapping( } } - private String getMiddleTableName(Collection value, String entityName) { + private String getMiddleTableName(PluralAttributeBinding attributeBinding, String entityName) { // We check how Hibernate maps the collection. - if ( value.getElement() instanceof OneToMany && !value.isInverse() ) { + if ( attributeBinding.getPluralAttributeElementBinding().getNature() == + PluralAttributeElementNature.ONE_TO_MANY && + !attributeBinding.getPluralAttributeKeyBinding().isInverse() ) { // This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a // middle table for mapping this relation. return StringTools.getLastComponent( entityName ) + "_" + StringTools.getLastComponent( - MappingTools.getReferencedEntityName( - value.getElement() - ) + MappingTools.getReferencedEntityName( attributeBinding ) ); } // Hibernate uses a middle table for mapping this relation, so we get it's name directly. - return value.getCollectionTable().getName(); + return attributeBinding.getPluralAttributeKeyBinding().getCollectionTable().getLogicalName().getName(); } @SuppressWarnings({"unchecked"}) @@ -359,9 +379,9 @@ private void addWithMiddleTable() { auditMiddleEntityName = propertyAuditingData.getJoinTable().name(); } else { - final String middleTableName = getMiddleTableName( propertyValue, referencingEntityName ); - auditMiddleTableName = mainGenerator.getVerEntCfg().getAuditTableName( null, middleTableName ); - auditMiddleEntityName = mainGenerator.getVerEntCfg().getAuditEntityName( middleTableName ); + final String middleTableName = getMiddleTableName( pluralAttributeBinding, referencingEntityName ); + auditMiddleTableName = context.getAuditEntitiesConfiguration().getAuditTableName( null, middleTableName ); + auditMiddleEntityName = context.getAuditEntitiesConfiguration().getAuditEntityName( middleTableName ); } LOG.debugf( "Using join table name: %s", auditMiddleTableName ); @@ -369,7 +389,7 @@ private void addWithMiddleTable() { // Generating the XML mapping for the middle entity, only if the relation isn't inverse. // If the relation is inverse, will be later checked by comparing middleEntityXml with null. Element middleEntityXml; - if ( !propertyValue.isInverse() ) { + if ( !pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ) { // Generating a unique middle entity name auditMiddleEntityName = mainGenerator.getAuditEntityNameRegister().createUnique( auditMiddleEntityName ); @@ -379,7 +399,7 @@ private void addWithMiddleTable() { middleEntityXml = createMiddleEntityXml( auditMiddleTableName, auditMiddleEntityName, - propertyValue.getWhere() + pluralAttributeBinding.getWhere() ); } else { @@ -399,11 +419,11 @@ private void addWithMiddleTable() { String referencingPrefixRelated; String referencedPrefix; - if ( propertyValue.isInverse() ) { + if ( pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ) { // If the relation is inverse, then referencedEntityName is not null. mappedBy = getMappedBy( - propertyValue.getCollectionTable(), - mainGenerator.getCfg().getClassMapping( referencedEntityName ) + pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable(), + context.getEntityBinding( referencedEntityName ) ); referencingPrefixRelated = mappedBy + "_"; @@ -427,8 +447,8 @@ private void addWithMiddleTable() { // references some entities (either from the element or index). At the end, this will be used to build // a query generator to read the raw data collection from the middle table. final QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder( - mainGenerator.getGlobalCfg(), - mainGenerator.getVerEntCfg(), + context.getGlobalConfiguration(), + context.getAuditEntitiesConfiguration(), mainGenerator.getAuditStrategy(), referencingIdData, auditMiddleEntityName, @@ -440,7 +460,9 @@ private void addWithMiddleTable() { // Adding related-entity (in this case: the referencing's entity id) id mapping to the xml. addRelatedToXmlMapping( middleEntityXml, referencingPrefixRelated, - MetadataTools.getColumnNameIterator( propertyValue.getKey().getColumnIterator() ), + MetadataTools.getColumnNameIterator( + pluralAttributeBinding.getPluralAttributeKeyBinding().getValues().iterator() + ), referencingIdMapping ); } @@ -449,11 +471,11 @@ private void addWithMiddleTable() { // Generating the element mapping. // ****** final MiddleComponentData elementComponentData = addValueToMiddleTable( - propertyValue.getElement(), middleEntityXml, queryGeneratorBuilder, referencedPrefix, - propertyAuditingData.getJoinTable().inverseJoinColumns() + propertyAuditingData.getJoinTable().inverseJoinColumns(), + false ); // ****** @@ -469,7 +491,7 @@ private void addWithMiddleTable() { // Creating common data final CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData( - mainGenerator.getVerEntCfg(), + context.getAuditEntitiesConfiguration(), auditMiddleEntityName, propertyAuditingData.getPropertyData(), referencingIdData, @@ -486,17 +508,18 @@ private void addWithMiddleTable() { } private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) { - if ( propertyValue instanceof IndexedCollection ) { - final IndexedCollection indexedValue = (IndexedCollection) propertyValue; + if ( pluralAttributeBinding.getAttribute().getPluralAttributeNature().isIndexed() ) { + final PluralAttributeIndexBinding indexBinding = + ( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding(); final String mapKey = propertyAuditingData.getMapKey(); if ( mapKey == null ) { // This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity. return addValueToMiddleTable( - indexedValue.getIndex(), middleEntityXml, queryGeneratorBuilder, "mapkey", - null + null, + true ); } else { @@ -507,7 +530,7 @@ private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuil // The key of the map is the id of the entity. return new MiddleComponentData( new MiddleMapKeyIdComponentMapper( - mainGenerator.getVerEntCfg(), + context.getAuditEntitiesConfiguration(), referencedIdMapping.getIdMapper() ), currentIndex @@ -531,29 +554,46 @@ private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuil } } + private PluralAttributeIndexBinding getPluralAttributeIndexBinding() { + if ( !pluralAttributeBinding.getAttribute().getPluralAttributeNature().isIndexed() ) { + throw new AssertionFailure( "This method is only valid for an indexed plural attribute binding." ); + } + return ( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding(); + } + /** - * @param value Value, which should be mapped to the middle-table, either as a relation to another entity, - * or as a simple value. * @param xmlMapping If not null, xml mapping for this value is added to this element. * @param queryGeneratorBuilder In case value is a relation to another entity, information about it * should be added to the given. * @param prefix Prefix for proeprty names of related entities identifiers. * @param joinColumns Names of columns to use in the xml mapping, if this array isn't null and has any elements. + * @param isIndex true, if the value is for the collection index; false, if the value is for the collection element. * * @return Data for mapping this component. */ @SuppressWarnings({"unchecked"}) private MiddleComponentData addValueToMiddleTable( - Value value, Element xmlMapping, QueryGeneratorBuilder queryGeneratorBuilder, String prefix, - JoinColumn[] joinColumns) { - final Type type = value.getType(); - if ( type instanceof ManyToOneType ) { + JoinColumn[] joinColumns, + boolean isIndex) { + + final HibernateTypeDescriptor hibernateTypeDescriptor; + final List values; + if ( isIndex ) { + hibernateTypeDescriptor = getPluralAttributeIndexBinding().getHibernateTypeDescriptor(); + values = getPluralAttributeIndexBinding().getValues(); + } + else { + hibernateTypeDescriptor = pluralAttributeBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor(); + values = pluralAttributeBinding.getPluralAttributeElementBinding().getRelationalValueContainer().values(); + + } + if ( hibernateTypeDescriptor.getResolvedTypeMapping() instanceof ManyToOneType ) { final String prefixRelated = prefix + "_"; - final String referencedEntityName = MappingTools.getReferencedEntityName( value ); + final String referencedEntityName = MappingTools.getReferencedEntityName( pluralAttributeBinding ); final IdMappingData referencedIdMapping = mainGenerator.getReferencedIdMappingData( referencingEntityName, @@ -569,7 +609,7 @@ private MiddleComponentData addValueToMiddleTable( xmlMapping, prefixRelated, joinColumns != null && joinColumns.length > 0 ? MetadataTools.getColumnNameIterator( joinColumns ) - : MetadataTools.getColumnNameIterator( value.getColumnIterator() ), + : MetadataTools.getColumnNameIterator( values.iterator() ), referencedIdMapping ); } @@ -588,12 +628,20 @@ private MiddleComponentData addValueToMiddleTable( queryGeneratorBuilder.getCurrentIndex() ); } - else if ( type instanceof ComponentType ) { + else if ( hibernateTypeDescriptor.getResolvedTypeMapping() instanceof ComponentType ) { + final EmbeddableBinding embeddableBinding; + if ( isIndex ) { + embeddableBinding = + ( ( CompositePluralAttributeIndexBinding ) getPluralAttributeIndexBinding() ).getCompositeAttributeBindingContainer(); + } + else { + embeddableBinding = + ( (PluralAttributeElementBindingEmbedded) pluralAttributeBinding.getPluralAttributeElementBinding() ).getEmbeddableBinding(); + } // Collection of embeddable elements. - final Component component = (Component) value; final Class componentClass = ReflectionTools.loadClass( - component.getComponentClassName(), - mainGenerator.getClassLoaderService() + hibernateTypeDescriptor.getJavaTypeDescriptor().getName().toString(), + context.getClassLoaderService() ); final MiddleEmbeddableComponentMapper componentMapper = new MiddleEmbeddableComponentMapper( new MultiPropertyMapper(), @@ -602,12 +650,15 @@ else if ( type instanceof ComponentType ) { final Element parentXmlMapping = xmlMapping.getParent(); final ComponentAuditingData auditData = new ComponentAuditingData(); - final ReflectionManager reflectionManager = mainGenerator.getCfg().getReflectionManager(); new ComponentAuditedPropertiesReader( - ModificationStore.FULL, - new AuditedPropertiesReader.ComponentPropertiesSource( reflectionManager, component ), - auditData, mainGenerator.getGlobalCfg(), reflectionManager, "" + context, + auditData, + new AuditedPropertiesReader.ComponentPropertiesSource( + context.getClassInfo( embeddableBinding.getAttributeContainer() ), + embeddableBinding + ), + "" ).read(); // Emulating first pass. @@ -615,12 +666,11 @@ else if ( type instanceof ComponentType ) { final PropertyAuditingData nestedAuditingData = auditData.getPropertyAuditingData( auditedPropertyName ); mainGenerator.addValue( parentXmlMapping, - component.getProperty( auditedPropertyName ).getValue(), + embeddableBinding.locateAttributeBinding( auditedPropertyName ), componentMapper, prefix, xmlMappingData, nestedAuditingData, true, - true, true ); } @@ -630,12 +680,11 @@ else if ( type instanceof ComponentType ) { final PropertyAuditingData nestedAuditingData = auditData.getPropertyAuditingData( auditedPropertyName ); mainGenerator.addValue( parentXmlMapping, - component.getProperty( auditedPropertyName ).getValue(), + embeddableBinding.locateAttributeBinding( auditedPropertyName ), componentMapper, referencingEntityName, xmlMappingData, nestedAuditingData, - true, false, true ); @@ -643,8 +692,8 @@ else if ( type instanceof ComponentType ) { // Add an additional column holding a number to make each entry unique within the set. // Embeddable properties may contain null values, so cannot be stored within composite primary key. - if ( propertyValue.isSet() ) { - final String setOrdinalPropertyName = mainGenerator.getVerEntCfg() + if ( ( pluralAttributeBinding.getAttribute() ).getPluralAttributeNature() == PluralAttributeNature.SET ) { + final String setOrdinalPropertyName = context.getAuditEntitiesConfiguration() .getEmbeddableSetOrdinalPropertyName(); final Element ordinalProperty = MetadataTools.addProperty( xmlMapping, setOrdinalPropertyName, "integer", true, true @@ -669,21 +718,24 @@ else if ( type instanceof ComponentType ) { null, false ), - value, + hibernateTypeDescriptor, + values, + true, // TODO: is this correct for collection element? null, - true, true ); if ( mapped ) { // Simple values are always stored in the first item of the array returned by the query generator. return new MiddleComponentData( - new MiddleSimpleComponentMapper( mainGenerator.getVerEntCfg(), prefix ), + new MiddleSimpleComponentMapper( context.getAuditEntitiesConfiguration(), prefix ), 0 ); } else { - mainGenerator.throwUnsupportedTypeException( type, referencingEntityName, propertyName ); + mainGenerator.throwUnsupportedTypeException( + hibernateTypeDescriptor.getResolvedTypeMapping(), referencingEntityName, propertyName + ); // Impossible to get here. throw new AssertionError(); } @@ -694,7 +746,7 @@ private void addMapper( CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData) { - final Type type = propertyValue.getType(); + final Type type = pluralAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); final boolean embeddableElementType = isEmbeddableElementType(); if ( type instanceof SortedSetType ) { currentMapper.addComposite( @@ -704,7 +756,7 @@ private void addMapper( TreeSet.class, SortedSetProxy.class, elementComponentData, - propertyValue.getComparator(), + pluralAttributeBinding.getComparator(), embeddableElementType, embeddableElementType ) @@ -733,7 +785,7 @@ else if ( type instanceof SortedMapType ) { SortedMapProxy.class, elementComponentData, indexComponentData, - propertyValue.getComparator(), + pluralAttributeBinding.getComparator(), embeddableElementType ) ); @@ -785,7 +837,7 @@ else if ( type instanceof ListType ) { private void storeMiddleEntityRelationInformation(String mappedBy) { // Only if this is a relation (when there is a referenced entity). if ( referencedEntityName != null ) { - if ( propertyValue.isInverse() ) { + if ( pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ) { referencingEntityConfiguration.addToManyMiddleNotOwningRelation( propertyName, mappedBy, @@ -801,11 +853,11 @@ private void storeMiddleEntityRelationInformation(String mappedBy) { private Element createMiddleEntityXml(String auditMiddleTableName, String auditMiddleEntityName, String where) { final String schema = mainGenerator.getSchema( propertyAuditingData.getJoinTable().schema(), - propertyValue.getCollectionTable() + pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable() ); final String catalog = mainGenerator.getCatalog( propertyAuditingData.getJoinTable().catalog(), - propertyValue.getCollectionTable() + pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable() ); final Element middleEntityXml = MetadataTools.createEntity( @@ -819,7 +871,7 @@ private Element createMiddleEntityXml(String auditMiddleTableName, String auditM middleEntityXml.addAttribute( "where", where ); } - middleEntityXmlId.addAttribute( "name", mainGenerator.getVerEntCfg().getOriginalIdPropName() ); + middleEntityXmlId.addAttribute( "name", context.getAuditEntitiesConfiguration().getOriginalIdPropName() ); // Adding the revision number as a foreign key to the revision info entity to the composite id of the // middle table. @@ -828,7 +880,8 @@ private Element createMiddleEntityXml(String auditMiddleTableName, String auditM // Adding the revision type property to the entity xml. mainGenerator.addRevisionType( isEmbeddableElementType() ? middleEntityXmlId : middleEntityXml, - middleEntityXml + middleEntityXml, + isEmbeddableElementType() ); // All other properties should also be part of the primary key of the middle entity. @@ -839,20 +892,15 @@ private Element createMiddleEntityXml(String auditMiddleTableName, String auditM * Checks if the collection element is of {@link ComponentType} type. */ private boolean isEmbeddableElementType() { - return propertyValue.getElement().getType() instanceof ComponentType; + return pluralAttributeBinding.getPluralAttributeElementBinding() + .getHibernateTypeDescriptor().getResolvedTypeMapping().isComponentType(); } - private String getMappedBy(Collection collectionValue) { - PersistentClass referencedClass = null; - if ( collectionValue.getElement() instanceof OneToMany ) { - final OneToMany oneToManyValue = (OneToMany) collectionValue.getElement(); - referencedClass = oneToManyValue.getAssociatedClass(); - } - else if ( collectionValue.getElement() instanceof ManyToOne ) { - // Case for bi-directional relation with @JoinTable on the owning @ManyToOne side. - final ManyToOne manyToOneValue = (ManyToOne) collectionValue.getElement(); - referencedClass = manyToOneValue.getMappings().getClass( manyToOneValue.getReferencedEntityName() ); - } + private String getMappedBy(PluralAttributeAssociationElementBinding elementBinding) { + EntityBinding referencedEntityBinding = null; + final EntityType entityType = + (EntityType) elementBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + referencedEntityBinding = context.getEntityBinding( entityType.getAssociatedEntityName() ); // If there's an @AuditMappedBy specified, returning it directly. final String auditMappedBy = propertyAuditingData.getAuditMappedBy(); @@ -861,27 +909,30 @@ else if ( collectionValue.getElement() instanceof ManyToOne ) { } // searching in referenced class - String mappedBy = this.searchMappedBy( referencedClass, collectionValue ); + String mappedBy = this.searchMappedBy( referencedEntityBinding ); if ( mappedBy == null ) { LOG.debugf( "Going to search the mapped by attribute for %s in superclasses of entity: %s", propertyName, - referencedClass.getClassName() + referencedEntityBinding.getEntityName() ); - PersistentClass tempClass = referencedClass; - while ( (mappedBy == null) && (tempClass.getSuperclass() != null) ) { - LOG.debugf( "Searching in superclass: %s", tempClass.getSuperclass().getClassName() ); - mappedBy = this.searchMappedBy( tempClass.getSuperclass(), collectionValue ); - tempClass = tempClass.getSuperclass(); + EntityBinding tempEntityBinding = referencedEntityBinding; + while ( (mappedBy == null) && (tempEntityBinding.getSuperEntityBinding() != null) ) { + LOG.debugf( + "Searching in superclass: %s", + tempEntityBinding.getSuperEntityBinding().getEntity().getDescriptor().getName() + ); + mappedBy = this.searchMappedBy( tempEntityBinding.getSuperEntityBinding() ); + tempEntityBinding = tempEntityBinding.getSuperEntityBinding(); } } if ( mappedBy == null ) { throw new MappingException( "Unable to read the mapped by attribute for " + propertyName + " in " - + referencedClass.getClassName() + "!" + + referencedEntityBinding.getEntity().getDescriptor().getName() + "!" ); } @@ -889,22 +940,30 @@ else if ( collectionValue.getElement() instanceof ManyToOne ) { } @SuppressWarnings({"unchecked"}) - private String searchMappedBy(PersistentClass referencedClass, Collection collectionValue) { - final Iterator assocClassProps = referencedClass.getPropertyIterator(); - while ( assocClassProps.hasNext() ) { - final Property property = assocClassProps.next(); + private String searchMappedBy(EntityBinding referencedEntityBinding) { + for ( AttributeBinding attributeBinding : referencedEntityBinding.attributeBindings() ) { + if ( !attributeBinding.isAssociation() ) { + continue; + } + final List attributeValues; + if ( attributeBinding.getAttribute().isSingular() ) { + attributeValues = ( (SingularAttributeBinding) attributeBinding ).getValues(); + } + else { + attributeValues = ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding().getRelationalValueContainer().values(); + } if ( Tools.iteratorsContentEqual( - property.getValue().getColumnIterator(), - collectionValue.getKey().getColumnIterator() + attributeValues.iterator(), + pluralAttributeBinding.getPluralAttributeKeyBinding().getValues().iterator() ) ) { - return property.getName(); + return attributeBinding.getAttribute().getName(); } } return null; } - private String getMappedBy(Table collectionTable, PersistentClass referencedClass) { + private String getMappedBy(TableSpecification collectionTable, EntityBinding referencedClass) { // If there's an @AuditMappedBy specified, returning it directly. final String auditMappedBy = propertyAuditingData.getAuditMappedBy(); if ( auditMappedBy != null ) { @@ -919,21 +978,24 @@ private String getMappedBy(Table collectionTable, PersistentClass referencedClas LOG.debugf( "Going to search the mapped by attribute for %s in superclasses of entity: %s", propertyName, - referencedClass.getClassName() + referencedClass.getEntity().getDescriptor().getName() ); - PersistentClass tempClass = referencedClass; - while ( (mappedBy == null) && (tempClass.getSuperclass() != null) ) { - LOG.debugf( "Searching in superclass: %s", tempClass.getSuperclass().getClassName() ); - mappedBy = this.searchMappedBy( tempClass.getSuperclass(), collectionTable ); - tempClass = tempClass.getSuperclass(); + EntityBinding tempClass = referencedClass; + while ( (mappedBy == null) && (tempClass.getSuperEntityBinding() != null) ) { + LOG.debugf( + "Searching in superclass: %s", + tempClass.getSuperEntityBinding().getEntity().getDescriptor().getName() + ); + mappedBy = this.searchMappedBy( tempClass.getSuperEntityBinding(), collectionTable ); + tempClass = tempClass.getSuperEntityBinding(); } } if ( mappedBy == null ) { throw new MappingException( "Unable to read the mapped by attribute for " + propertyName + " in " - + referencedClass.getClassName() + "!" + + referencedClass.getEntity().getDescriptor().getName() + "!" ); } @@ -941,15 +1003,14 @@ private String getMappedBy(Table collectionTable, PersistentClass referencedClas } @SuppressWarnings({"unchecked"}) - private String searchMappedBy(PersistentClass referencedClass, Table collectionTable) { - final Iterator properties = referencedClass.getPropertyIterator(); - while ( properties.hasNext() ) { - final Property property = properties.next(); - if ( property.getValue() instanceof Collection ) { + private String searchMappedBy(EntityBinding referencedClass, TableSpecification collectionTable) { + for ( AttributeBinding attributeBinding : referencedClass.attributeBindings() ) { + if ( !attributeBinding.getAttribute().isSingular() ) { // The equality is intentional. We want to find a collection property with the same collection table. //noinspection ObjectEquality - if ( ((Collection) property.getValue()).getCollectionTable() == collectionTable ) { - return property.getName(); + if ( ((PluralAttributeBinding) attributeBinding ).getPluralAttributeKeyBinding().getCollectionTable() == + collectionTable ) { + return attributeBinding.getAttribute().getName(); } } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ComponentMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ComponentMetadataGenerator.java index 5dad4f4a0dc8..8299a8be1b83 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ComponentMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ComponentMetadataGenerator.java @@ -23,16 +23,15 @@ */ package org.hibernate.envers.configuration.internal.metadata; -import java.util.Iterator; import java.util.Map; +import org.hibernate.EntityMode; import org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditingData; import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData; +import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.envers.internal.entities.mapper.CompositeMapperBuilder; -import org.hibernate.envers.internal.tools.ReflectionTools; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; import org.dom4j.Element; @@ -43,29 +42,29 @@ * @author Lukasz Zuchowski (author at zuchos dot com) */ public final class ComponentMetadataGenerator { - private final AuditMetadataGenerator mainGenerator; + private final AuditConfiguration.AuditConfigurationContext context; - ComponentMetadataGenerator(AuditMetadataGenerator auditMetadataGenerator) { + private final AuditMetadataGenerator mainGenerator; + + ComponentMetadataGenerator(AuditConfiguration.AuditConfigurationContext context, AuditMetadataGenerator auditMetadataGenerator) { + this.context = context; mainGenerator = auditMetadataGenerator; } @SuppressWarnings({"unchecked"}) public void addComponent( Element parent, PropertyAuditingData propertyAuditingData, - Value value, CompositeMapperBuilder mapper, String entityName, + EmbeddedAttributeBinding embeddedAttributeBinding, CompositeMapperBuilder mapper, String entityName, EntityXmlMappingData xmlMappingData, boolean firstPass) { - final Component propComponent = (Component) value; final Class componentClass; - if (propComponent.isDynamic()) { - componentClass = ReflectionTools.loadClass( - Map.class.getCanonicalName(), - mainGenerator.getClassLoaderService()); - + final EntityMode entityMode = embeddedAttributeBinding.getEmbeddableBinding().seekEntityBinding().getHierarchyDetails().getEntityMode(); + if ( entityMode == EntityMode.MAP ) { + componentClass = context.getClassLoaderService().classForName( Map.class.getCanonicalName() ); } else { - componentClass = ReflectionTools.loadClass( - propComponent.getComponentClassName(), - mainGenerator.getClassLoaderService() + // TODO: get rid of classloading. + componentClass = context.getClassLoaderService().classForName( + embeddedAttributeBinding.getHibernateTypeDescriptor().getJavaTypeDescriptor().getName().toString() ); } final CompositeMapperBuilder componentMapper = mapper.addComponent( @@ -77,18 +76,16 @@ public void addComponent( final ComponentAuditingData componentAuditingData = (ComponentAuditingData) propertyAuditingData; // Adding all properties of the component - final Iterator properties = (Iterator) propComponent.getPropertyIterator(); - while (properties.hasNext()) { - final Property property = properties.next(); + for ( AttributeBinding attributeBinding : embeddedAttributeBinding.getEmbeddableBinding().attributeBindings() ) { final PropertyAuditingData componentPropertyAuditingData = - componentAuditingData.getPropertyAuditingData(property.getName()); + componentAuditingData.getPropertyAuditingData( attributeBinding.getAttribute().getName() ); // Checking if that property is audited if (componentPropertyAuditingData != null) { mainGenerator.addValue( - parent, property.getValue(), componentMapper, entityName, xmlMappingData, - componentPropertyAuditingData, property.isInsertable(), firstPass, false + parent, attributeBinding, componentMapper, entityName, xmlMappingData, + componentPropertyAuditingData, firstPass, false ); } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/IdMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/IdMetadataGenerator.java index 0135dbcc0ba5..10e9a4778c6f 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/IdMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/IdMetadataGenerator.java @@ -23,12 +23,11 @@ */ package org.hibernate.envers.configuration.internal.metadata; -import java.util.Iterator; - import org.hibernate.MappingException; import org.hibernate.envers.ModificationStore; import org.hibernate.envers.RelationTargetAuditMode; import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData; +import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.envers.internal.entities.IdMappingData; import org.hibernate.envers.internal.entities.PropertyData; import org.hibernate.envers.internal.entities.mapper.SimpleMapperBuilder; @@ -36,10 +35,13 @@ import org.hibernate.envers.internal.entities.mapper.id.MultipleIdMapper; import org.hibernate.envers.internal.entities.mapper.id.SimpleIdMapperBuilder; import org.hibernate.envers.internal.entities.mapper.id.SingleIdMapper; -import org.hibernate.envers.internal.tools.ReflectionTools; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; +import org.hibernate.id.EntityIdentifierNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityIdentifier; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.type.ManyToOneType; import org.hibernate.type.Type; @@ -52,53 +54,57 @@ * @author Adam Warski (adam at warski dot org) */ public final class IdMetadataGenerator { + private final AuditConfiguration.AuditConfigurationContext context; private final AuditMetadataGenerator mainGenerator; - IdMetadataGenerator(AuditMetadataGenerator auditMetadataGenerator) { + IdMetadataGenerator(AuditConfiguration.AuditConfigurationContext context, AuditMetadataGenerator auditMetadataGenerator) { + this.context = context; mainGenerator = auditMetadataGenerator; } @SuppressWarnings({"unchecked"}) private boolean addIdProperties( Element parent, - Iterator properties, + EmbeddedAttributeBinding embeddedAttributeBinding, SimpleMapperBuilder mapper, boolean key, boolean audited) { - while ( properties.hasNext() ) { - final Property property = properties.next(); - final Type propertyType = property.getType(); - if ( !"_identifierMapper".equals( property.getName() ) ) { - boolean added = false; - if ( propertyType instanceof ManyToOneType ) { - added = mainGenerator.getBasicMetadataGenerator().addManyToOne( - parent, - getIdPersistentPropertyAuditingData( property ), - property.getValue(), - mapper - ); + //if ( embeddedAttributeBinding.getAttribute().isSynthetic() ) { + // return true; + //} + for ( AttributeBinding attributeBinding : embeddedAttributeBinding.getEmbeddableBinding().attributeBindings() ) { + final Type propertyType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + final boolean added; + if ( propertyType instanceof ManyToOneType ) { + added = mainGenerator.getBasicMetadataGenerator().addManyToOne( + parent, + getIdPersistentPropertyAuditingData( attributeBinding ), + (ManyToOneAttributeBinding) attributeBinding, + mapper + ); + } + else { + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + // Last but one parameter: ids are always insertable + added = mainGenerator.getBasicMetadataGenerator().addBasic( + parent, + getIdPersistentPropertyAuditingData( singularAttributeBinding ), + singularAttributeBinding.getHibernateTypeDescriptor(), + singularAttributeBinding.getValues(), + singularAttributeBinding.isIncludedInInsert(), + mapper, + key + ); + } + if ( !added ) { + // If the entity is audited, and a non-supported id component is used, throwing an exception. + // If the entity is not audited, then we simply don't support this entity, even in + // target relation mode not audited. + if ( audited ) { + throw new MappingException( "Type not supported: " + propertyType.getClass().getName() ); } else { - // Last but one parameter: ids are always insertable - added = mainGenerator.getBasicMetadataGenerator().addBasic( - parent, - getIdPersistentPropertyAuditingData( property ), - property.getValue(), - mapper, - true, - key - ); - } - if ( !added ) { - // If the entity is audited, and a non-supported id component is used, throwing an exception. - // If the entity is not audited, then we simply don't support this entity, even in - // target relation mode not audited. - if ( audited ) { - throw new MappingException( "Type not supported: " + propertyType.getClass().getName() ); - } - else { - return false; - } + return false; } } } @@ -107,31 +113,30 @@ private boolean addIdProperties( } @SuppressWarnings({"unchecked"}) - IdMappingData addId(PersistentClass pc, boolean audited) { + IdMappingData addId(EntityBinding entityBinding, boolean audited) { // Xml mapping which will be used for relations final Element relIdMapping = new DefaultElement( "properties" ); // Xml mapping which will be used for the primary key of the versions table final Element origIdMapping = new DefaultElement( "composite-id" ); - final Property idProp = pc.getIdentifierProperty(); - final Component idMapper = pc.getIdentifierMapper(); + //final Property idProp = pc.getIdentifierProperty(); + //final Component idMapper = pc.getIdentifierMapper(); // Checking if the id mapping is supported - if ( idMapper == null && idProp == null ) { - return null; - } + //if ( idMapper == null && idProp == null ) { + // return null; + //} + final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier(); SimpleIdMapperBuilder mapper; - if ( idMapper != null ) { + if ( entityIdentifier.getLookupClassBinding().definedIdClass() ) { // Multiple id - final Class componentClass = ReflectionTools.loadClass( - ( (Component) pc.getIdentifier() ).getComponentClassName(), - mainGenerator.getClassLoaderService() - ); + final Class componentClass = entityIdentifier.getLookupClassBinding().getIdClassType(); + mapper = new MultipleIdMapper( componentClass ); if ( !addIdProperties( relIdMapping, - (Iterator) idMapper.getPropertyIterator(), + (EmbeddedAttributeBinding) entityIdentifier.getAttributeBinding(), mapper, false, audited @@ -142,7 +147,7 @@ IdMappingData addId(PersistentClass pc, boolean audited) { // null mapper - the mapping where already added the first time, now we only want to generate the xml if ( !addIdProperties( origIdMapping, - (Iterator) idMapper.getPropertyIterator(), + (EmbeddedAttributeBinding) entityIdentifier.getAttributeBinding(), null, true, audited @@ -150,17 +155,16 @@ IdMappingData addId(PersistentClass pc, boolean audited) { return null; } } - else if ( idProp.isComposite() ) { - // Embedded id - final Component idComponent = (Component) idProp.getValue(); - final Class embeddableClass = ReflectionTools.loadClass( - idComponent.getComponentClassName(), - mainGenerator.getClassLoaderService() + else if ( entityIdentifier.getNature() == EntityIdentifierNature.AGGREGATED_COMPOSITE ) { + // Embeddable id + // TODO: get rid of classloading. + final Class embeddableClass = context.getClassLoaderService().classForName( + entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor().getJavaTypeDescriptor().getName().toString() ); - mapper = new EmbeddedIdMapper( getIdPropertyData( idProp ), embeddableClass ); + mapper = new EmbeddedIdMapper( getIdPropertyData( entityIdentifier.getAttributeBinding() ), embeddableClass ); if ( !addIdProperties( relIdMapping, - (Iterator) idComponent.getPropertyIterator(), + (EmbeddedAttributeBinding) entityIdentifier.getAttributeBinding(), mapper, false, audited @@ -171,7 +175,7 @@ else if ( idProp.isComposite() ) { // null mapper - the mapping where already added the first time, now we only want to generate the xml if ( !addIdProperties( origIdMapping, - (Iterator) idComponent.getPropertyIterator(), + (EmbeddedAttributeBinding) entityIdentifier.getAttributeBinding(), null, true, audited @@ -186,25 +190,27 @@ else if ( idProp.isComposite() ) { // Last but one parameter: ids are always insertable mainGenerator.getBasicMetadataGenerator().addBasic( relIdMapping, - getIdPersistentPropertyAuditingData( idProp ), - idProp.getValue(), + getIdPersistentPropertyAuditingData( entityIdentifier.getAttributeBinding() ), + entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor(), + entityIdentifier.getAttributeBinding().getValues(), + entityIdentifier.getAttributeBinding().isIncludedInInsert(), mapper, - true, false ); // null mapper - the mapping where already added the first time, now we only want to generate the xml mainGenerator.getBasicMetadataGenerator().addBasic( origIdMapping, - getIdPersistentPropertyAuditingData( idProp ), - idProp.getValue(), + getIdPersistentPropertyAuditingData( entityIdentifier.getAttributeBinding() ), + entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor(), + entityIdentifier.getAttributeBinding().getValues(), + entityIdentifier.getAttributeBinding().isIncludedInInsert(), null, - true, true ); } - origIdMapping.addAttribute( "name", mainGenerator.getVerEntCfg().getOriginalIdPropName() ); + origIdMapping.addAttribute( "name", context.getAuditEntitiesConfiguration().getOriginalIdPropName() ); // Adding a relation to the revision entity (effectively: the "revision number" property) mainGenerator.addRevisionInfoRelation( origIdMapping ); @@ -212,16 +218,18 @@ else if ( idProp.isComposite() ) { return new IdMappingData( mapper, origIdMapping, relIdMapping ); } - private PropertyData getIdPropertyData(Property property) { + private PropertyData getIdPropertyData(SingularAttributeBinding idAttributeBinding) { return new PropertyData( - property.getName(), property.getName(), property.getPropertyAccessorName(), + idAttributeBinding.getAttribute().getName(), + idAttributeBinding.getAttribute().getName(), + idAttributeBinding.getPropertyAccessorName(), ModificationStore.FULL ); } - private PropertyAuditingData getIdPersistentPropertyAuditingData(Property property) { + private PropertyAuditingData getIdPersistentPropertyAuditingData(AttributeBinding property) { return new PropertyAuditingData( - property.getName(), property.getPropertyAccessorName(), + property.getAttribute().getName(), property.getPropertyAccessorName(), ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null, false ); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/InheritanceType.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/InheritanceType.java index e912f525ffc9..5aaaab02e88b 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/InheritanceType.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/InheritanceType.java @@ -24,11 +24,7 @@ package org.hibernate.envers.configuration.internal.metadata; import org.hibernate.MappingException; -import org.hibernate.mapping.JoinedSubclass; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.SingleTableSubclass; -import org.hibernate.mapping.Subclass; -import org.hibernate.mapping.UnionSubclass; +import org.hibernate.metamodel.spi.binding.EntityBinding; /** * @author Adam Warski (adam at warski dot org) @@ -40,30 +36,30 @@ public enum InheritanceType { TABLE_PER_CLASS; /** - * @param pc The class for which to get the inheritance type. + * @param entityBinding The class for which to get the inheritance type. * * @return The inheritance type of this class. NONE, if this class does not inherit from * another persistent class. */ - public static InheritanceType get(PersistentClass pc) { - final PersistentClass superclass = pc.getSuperclass(); - if ( superclass == null ) { + public static InheritanceType get(EntityBinding entityBinding) { + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + if ( superEntityBinding == null ) { return InheritanceType.NONE; } // We assume that every subclass is of the same type. - final Subclass subclass = (Subclass) superclass.getSubclassIterator().next(); + final EntityBinding subEntityBinding = superEntityBinding.getDirectSubEntityBindings().get( 0 ); - if ( subclass instanceof SingleTableSubclass ) { + if ( subEntityBinding.getHierarchyDetails().getInheritanceType() == org.hibernate.metamodel.spi.binding.InheritanceType.SINGLE_TABLE ) { return InheritanceType.SINGLE; } - else if ( subclass instanceof JoinedSubclass ) { + else if ( subEntityBinding.getHierarchyDetails().getInheritanceType() == org.hibernate.metamodel.spi.binding.InheritanceType.JOINED ) { return InheritanceType.JOINED; } - else if ( subclass instanceof UnionSubclass ) { + else if ( subEntityBinding.getHierarchyDetails().getInheritanceType() == org.hibernate.metamodel.spi.binding.InheritanceType.TABLE_PER_CLASS ) { return InheritanceType.TABLE_PER_CLASS; } - throw new MappingException( "Unknown subclass class: " + subclass.getClass() ); + throw new MappingException( "Unknown subclass class: " + subEntityBinding.getClass() ); } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java index 4e74fe43e022..0e2d5453afd0 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java @@ -24,12 +24,14 @@ package org.hibernate.envers.configuration.internal.metadata; import java.util.Iterator; +import java.util.List; import javax.persistence.JoinColumn; +import org.hibernate.AssertionFailure; import org.hibernate.envers.internal.tools.StringTools; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Formula; -import org.hibernate.mapping.Selectable; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.Value; import org.dom4j.Attribute; import org.dom4j.Document; @@ -46,9 +48,11 @@ private MetadataTools() { public static Element addNativelyGeneratedId( Element parent, String name, String type, - boolean useRevisionEntityWithNativeId) { + boolean useRevisionEntityWithNativeId, + String idColumnName) { final Element idMapping = parent.addElement( "id" ); idMapping.addAttribute( "name", name ).addAttribute( "type", type ); + MetadataTools.addColumn( idMapping, idColumnName, null, null, null, null, null, null, false ); final Element generatorMapping = idMapping.addElement( "generator" ); if ( useRevisionEntityWithNativeId ) { @@ -87,9 +91,11 @@ public static Element addProperty( } propMapping.addAttribute( "name", name ); - propMapping.addAttribute( "insert", Boolean.toString( insertable ) ); - propMapping.addAttribute( "update", Boolean.toString( updateable ) ); + if ( !key ) { + propMapping.addAttribute( "insert", Boolean.toString( insertable ) ); + propMapping.addAttribute( "update", Boolean.toString( updateable ) ); + } if ( type != null ) { propMapping.addAttribute( "type", type ); } @@ -151,7 +157,7 @@ public static Element addOrModifyColumn(Element parent, String name) { public static Element addColumn( Element parent, String name, - Integer length, + Long length, Integer scale, Integer precision, String sqlType, @@ -163,7 +169,7 @@ public static Element addColumn( public static Element addColumn( Element parent, String name, - Integer length, + Long length, Integer scale, Integer precision, String sqlType, @@ -215,16 +221,18 @@ private static Element createEntityCommon( classMapping.addAttribute( "discriminator-value", discriminatorValue ); } - if ( !StringTools.isEmpty( auditTableData.getAuditTableName() ) ) { - classMapping.addAttribute( "table", auditTableData.getAuditTableName() ); - } + if ( !"subclass".equals( type ) ) { + if ( !StringTools.isEmpty( auditTableData.getAuditTableName() ) ) { + classMapping.addAttribute( "table", auditTableData.getAuditTableName() ); + } - if ( !StringTools.isEmpty( auditTableData.getSchema() ) ) { - classMapping.addAttribute( "schema", auditTableData.getSchema() ); - } + if ( !StringTools.isEmpty( auditTableData.getSchema() ) ) { + classMapping.addAttribute( "schema", auditTableData.getSchema() ); + } - if ( !StringTools.isEmpty( auditTableData.getCatalog() ) ) { - classMapping.addAttribute( "catalog", auditTableData.getCatalog() ); + if ( !StringTools.isEmpty( auditTableData.getCatalog() ) ) { + classMapping.addAttribute( "catalog", auditTableData.getCatalog() ); + } } if ( isAbstract != null ) { @@ -282,13 +290,18 @@ public static Element createJoin( return joinMapping; } - public static void addColumns(Element anyMapping, Iterator selectables) { - while ( selectables.hasNext() ) { - final Selectable selectable = (Selectable) selectables.next(); - if ( selectable.isFormula() ) { + public static void addColumns(Element anyMapping, List columns) { + for ( Column column : columns ) { + addColumn( anyMapping, column ); + } + } + + public static void addValuesAsColumns(Element anyMapping, List values) { + for ( Value value : values ) { + if ( Value.ValueType.DERIVED_VALUE.equals( value.getValueType() ) ) { throw new FormulaNotSupportedException(); } - addColumn( anyMapping, (Column) selectable ); + addColumn( anyMapping, (Column) value ); } } @@ -303,14 +316,14 @@ public static void addColumns(Element anyMapping, Iterator selectables) { public static void addColumn(Element anyMapping, Column column) { addColumn( anyMapping, - column.getName(), - column.getLength(), - column.getScale(), - column.getPrecision(), + column.getColumnName().getText(), + column.getSize().getLength(), + column.getSize().getScale(), + column.getSize().getPrecision(), column.getSqlType(), - column.getCustomRead(), - column.getCustomWrite(), - column.isQuoted() + column.getReadFragment(), + column.getWriteFragment(), + column.getColumnName().isQuoted() ); } @@ -350,9 +363,11 @@ public static void prefixNamesInPropertyElement( if ( changeToKey ) { property.setName( "key-" + property.getName() ); + // "insert" and "update" attributes are not allowed on key-many-to-one or key-property elements. + property.remove( property.attribute( "insert" ) ); + property.remove( property.attribute( "update" ) ); } - - if ( "property".equals( property.getName() ) ) { + else if ( "property".equals( property.getName() ) ) { final Attribute insert = property.attribute( "insert" ); insert.setText( Boolean.toString( insertable ) ); } @@ -366,25 +381,28 @@ public static void prefixNamesInPropertyElement( * @param element Parent element. * @param formula Formula descriptor. */ - public static void addFormula(Element element, Formula formula) { - element.addElement( "formula" ).setText( formula.getText() ); + public static void addFormula(Element element, DerivedValue formula) { + element.addElement( "formula" ).setText( formula.getExpression() ); } /** * Adds all column or formula elements. * * @param element Parent element. - * @param columnIterator Iterator pointing at {@link org.hibernate.mapping.Column} and/or - * {@link org.hibernate.mapping.Formula} objects. + * @param values List of {@link Column} and/or {@link DerivedValue} objects. */ - public static void addColumnsOrFormulas(Element element, Iterator columnIterator) { - while ( columnIterator.hasNext() ) { - final Object o = columnIterator.next(); - if ( o instanceof Column ) { - addColumn( element, (Column) o ); + public static void addColumnsOrFormulas(Element element, List values) { + for ( Value value : values ) { + if ( value.getValueType() == Value.ValueType.COLUMN ) { + addColumn( element, (Column) value ); + } + else if ( value.getValueType() == Value.ValueType.DERIVED_VALUE ) { + addFormula( element, (DerivedValue) value ); } - else if ( o instanceof Formula ) { - addFormula( element, (Formula) o ); + else { + throw new AssertionFailure( + String.format( "unknown type of value: %s", value.getValueType() ) + ); } } } @@ -395,18 +413,18 @@ else if ( o instanceof Formula ) { public static abstract class ColumnNameIterator implements Iterator { } - public static ColumnNameIterator getColumnNameIterator(final Iterator selectableIterator) { + public static ColumnNameIterator getColumnNameIterator(final Iterator selectableIterator) { return new ColumnNameIterator() { public boolean hasNext() { return selectableIterator.hasNext(); } public String next() { - final Selectable next = selectableIterator.next(); - if ( next.isFormula() ) { + final Value next = selectableIterator.next(); + if ( next.getValueType() == Value.ValueType.DERIVED_VALUE ) { throw new FormulaNotSupportedException(); } - return ((Column) next).getName(); + return ((Column) next).getColumnName().getText(); } public void remove() { diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ToOneRelationMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ToOneRelationMetadataGenerator.java index 9411436a4c19..72d0539537ab 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ToOneRelationMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/ToOneRelationMetadataGenerator.java @@ -34,9 +34,8 @@ import org.hibernate.envers.internal.entities.mapper.relation.OneToOnePrimaryKeyJoinColumnMapper; import org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper; import org.hibernate.envers.internal.tools.MappingTools; -import org.hibernate.mapping.OneToOne; -import org.hibernate.mapping.ToOne; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.spi.binding.OneToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; import org.dom4j.Element; @@ -57,11 +56,10 @@ public final class ToOneRelationMetadataGenerator { void addToOne( Element parent, PropertyAuditingData propertyAuditingData, - Value value, + SingularAssociationAttributeBinding attributeBinding, CompositeMapperBuilder mapper, - String entityName, - boolean insertable) { - final String referencedEntityName = ((ToOne) value).getReferencedEntityName(); + String entityName) { + final String referencedEntityName = attributeBinding.getReferencedEntityName(); final IdMappingData idMapping = mainGenerator.getReferencedIdMappingData( entityName, @@ -76,9 +74,10 @@ void addToOne( final IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties( lastPropertyPrefix ); // Storing information about this relation + boolean insertable = attributeBinding.isIncludedInInsert(); mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneRelation( propertyAuditingData.getName(), referencedEntityName, relMapper, - insertable, MappingTools.ignoreNotFound( value ) + insertable, MappingTools.ignoreNotFound( attributeBinding ) ); // If the property isn't insertable, checking if this is not a "fake" bidirectional many-to-one relationship, @@ -104,7 +103,7 @@ void addToOne( MetadataTools.prefixNamesInPropertyElement( properties, lastPropertyPrefix, - MetadataTools.getColumnNameIterator( value.getColumnIterator() ), + MetadataTools.getColumnNameIterator( attributeBinding.getValues().iterator() ), false, insertable ); @@ -127,11 +126,11 @@ void addToOne( @SuppressWarnings({"unchecked"}) void addOneToOneNotOwning( PropertyAuditingData propertyAuditingData, - Value value, + OneToOneAttributeBinding attributeBinding, CompositeMapperBuilder mapper, String entityName) { - final OneToOne propertyValue = (OneToOne) value; - final String owningReferencePropertyName = propertyValue.getReferencedPropertyName(); + final String owningReferencePropertyName = + attributeBinding.getReferencedAttributeBinding().getAttribute().getName(); final EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get( entityName ); if ( configuration == null ) { @@ -145,7 +144,7 @@ void addOneToOneNotOwning( } final String lastPropertyPrefix = MappingTools.createToOneRelationPrefix( owningReferencePropertyName ); - final String referencedEntityName = propertyValue.getReferencedEntityName(); + final String referencedEntityName = attributeBinding.getReferencedEntityName(); // Generating the id mapper for the relation final IdMapper ownedIdMapper = ownedIdMapping.getIdMapper().prefixMappedProperties( lastPropertyPrefix ); @@ -153,7 +152,7 @@ void addOneToOneNotOwning( // Storing information about this relation mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneNotOwningRelation( propertyAuditingData.getName(), owningReferencePropertyName, referencedEntityName, - ownedIdMapper, MappingTools.ignoreNotFound( value ) + ownedIdMapper, MappingTools.ignoreNotFound( attributeBinding ) ); // Adding mapper for the id @@ -167,11 +166,10 @@ void addOneToOneNotOwning( @SuppressWarnings({"unchecked"}) void addOneToOnePrimaryKeyJoinColumn( PropertyAuditingData propertyAuditingData, - Value value, + OneToOneAttributeBinding attributeBinding, CompositeMapperBuilder mapper, - String entityName, - boolean insertable) { - final String referencedEntityName = ((ToOne) value).getReferencedEntityName(); + String entityName) { + final String referencedEntityName = attributeBinding.getReferencedEntityName(); final IdMappingData idMapping = mainGenerator.getReferencedIdMappingData( entityName, @@ -187,8 +185,8 @@ void addOneToOnePrimaryKeyJoinColumn( // Storing information about this relation mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneRelation( - propertyAuditingData.getName(), referencedEntityName, relMapper, insertable, - MappingTools.ignoreNotFound( value ) + propertyAuditingData.getName(), referencedEntityName, relMapper, attributeBinding.isIncludedInInsert(), + MappingTools.ignoreNotFound( attributeBinding ) ); // Adding mapper for the id diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AnnotationsMetadataReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AnnotationsMetadataReader.java index 88f21f9f4430..402171a7689f 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AnnotationsMetadataReader.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AnnotationsMetadataReader.java @@ -24,19 +24,18 @@ package org.hibernate.envers.configuration.internal.metadata.reader; import java.lang.annotation.Annotation; -import java.util.Iterator; -import org.hibernate.MappingException; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.annotations.common.reflection.XClass; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; + import org.hibernate.envers.AuditTable; -import org.hibernate.envers.Audited; import org.hibernate.envers.ModificationStore; -import org.hibernate.envers.SecondaryAuditTable; -import org.hibernate.envers.SecondaryAuditTables; -import org.hibernate.envers.configuration.internal.GlobalConfiguration; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; +import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.envers.event.spi.EnversDotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; /** * A helper class to read versioning meta-data from annotations on a persistent class. @@ -45,140 +44,155 @@ * @author Sebastian Komander */ public final class AnnotationsMetadataReader { - private final GlobalConfiguration globalCfg; - private final ReflectionManager reflectionManager; - private final PersistentClass pc; - - /** - * This object is filled with information read from annotations and returned by the getVersioningData - * method. - */ - private final ClassAuditingData auditData; - - public AnnotationsMetadataReader( - GlobalConfiguration globalCfg, ReflectionManager reflectionManager, - PersistentClass pc) { - this.globalCfg = globalCfg; - this.reflectionManager = reflectionManager; - this.pc = pc; - - auditData = new ClassAuditingData(); - } - private ModificationStore getDefaultAudited(XClass clazz) { - final Audited defaultAudited = clazz.getAnnotation( Audited.class ); + private static final AuditTable DEFAULT_AUDIT_TABLE = new AuditTable() { + public String value() { + return ""; + } - if ( defaultAudited != null ) { - return defaultAudited.modStore(); + public String schema() { + return ""; } - else { - return null; + + public String catalog() { + return ""; } + + public Class annotationType() { + return this.getClass(); + } + }; + + private final AuditConfiguration.AuditConfigurationContext context; + + public AnnotationsMetadataReader(AuditConfiguration.AuditConfigurationContext context) { + this.context = context; } - private void addAuditTable(XClass clazz) { - final AuditTable auditTable = clazz.getAnnotation( AuditTable.class ); + private ModificationStore getDefaultAudited(ClassInfo classInfo) { + final AnnotationInstance audited = JandexHelper.getSingleAnnotation( + classInfo.annotations(), + EnversDotNames.AUDITED, + classInfo + ); + if ( audited != null ) { + return JandexHelper.getValue( audited, "modStore", ModificationStore.class, context.getClassLoaderService() ); + } + return null; + } + + private void addAuditTable(ClassInfo classInfo, ClassAuditingData auditData) { + final AnnotationInstance auditTable = JandexHelper.getSingleAnnotation( classInfo, EnversDotNames.AUDIT_TABLE ); if ( auditTable != null ) { - auditData.setAuditTable( auditTable ); + auditData.setAuditTable( + context.getAnnotationProxy( + auditTable, + AuditTable.class + ) + ); } else { auditData.setAuditTable( getDefaultAuditTable() ); } } - private void addAuditSecondaryTables(XClass clazz) { + private void addAuditSecondaryTables(ClassInfo classInfo, ClassAuditingData auditData) { // Getting information on secondary tables - final SecondaryAuditTable secondaryVersionsTable1 = clazz.getAnnotation( SecondaryAuditTable.class ); - if ( secondaryVersionsTable1 != null ) { + final AnnotationInstance secondaryAuditTable1 = JandexHelper.getSingleAnnotation( + classInfo, EnversDotNames.SECONDARY_AUDIT_TABLE + ); + if ( secondaryAuditTable1 != null ) { auditData.getSecondaryTableDictionary().put( - secondaryVersionsTable1.secondaryTableName(), - secondaryVersionsTable1.secondaryAuditTableName() + JandexHelper.getValue( + secondaryAuditTable1, "secondaryTableName", String.class, context.getClassLoaderService() + ), + JandexHelper.getValue( + secondaryAuditTable1, "secondaryAuditTableName", String.class, context.getClassLoaderService() + ) ); } - final SecondaryAuditTables secondaryAuditTables = clazz.getAnnotation( SecondaryAuditTables.class ); + final AnnotationInstance secondaryAuditTables = JandexHelper.getSingleAnnotation( classInfo, EnversDotNames.SECONDARY_AUDIT_TABLES ); if ( secondaryAuditTables != null ) { - for ( SecondaryAuditTable secondaryAuditTable2 : secondaryAuditTables.value() ) { + final AnnotationInstance[] secondaryAuditTableValues = + JandexHelper.getValue( secondaryAuditTables, "value", AnnotationInstance[].class, context.getClassLoaderService() ); + for ( AnnotationInstance secondaryAuditTable : secondaryAuditTableValues ) { auditData.getSecondaryTableDictionary().put( - secondaryAuditTable2.secondaryTableName(), - secondaryAuditTable2.secondaryAuditTableName() + JandexHelper.getValue( + secondaryAuditTable, "secondaryTableName", String.class, context.getClassLoaderService() + ), + JandexHelper.getValue( + secondaryAuditTable, "secondaryAuditTableName", String.class, context.getClassLoaderService() + ) ); } } } - public ClassAuditingData getAuditData() { - if ( pc.getClassName() == null ) { + public ClassAuditingData getAuditData(EntityBinding entityBinding) { + /** + * This object is filled with information read from annotations and returned by the getVersioningData + * method. + */ + final ClassAuditingData auditData = new ClassAuditingData(); + + if ( entityBinding.getEntity().getDescriptor() == null ) { + // TODO: What is the case here? Test by throwing exception. return auditData; } - try { - final XClass xclass = reflectionManager.classForName( pc.getClassName(), this.getClass() ); + final PersistentClassPropertiesSource persistentClassPropertiesSource = new PersistentClassPropertiesSource( + entityBinding, + context.getClassInfo( + entityBinding.getEntity().getDescriptor().getName().toString() + ) + ); - final ModificationStore defaultStore = getDefaultAudited( xclass ); - if ( defaultStore != null ) { - auditData.setDefaultAudited( true ); - } + ModificationStore defaultStore = getDefaultAudited( persistentClassPropertiesSource.getClassInfo() ); + auditData.setDefaultAudited( defaultStore != null ); - new AuditedPropertiesReader( - defaultStore, - new PersistentClassPropertiesSource( xclass ), - auditData, - globalCfg, - reflectionManager, - "" - ).read(); - - addAuditTable( xclass ); - addAuditSecondaryTables( xclass ); - } - catch (ClassNotFoundException e) { - throw new MappingException( e ); - } + new AuditedPropertiesReader( + context, + auditData, + persistentClassPropertiesSource, + "" + ).read(); + + addAuditTable( persistentClassPropertiesSource.getClassInfo(), auditData ); + addAuditSecondaryTables( persistentClassPropertiesSource.getClassInfo(), auditData ); return auditData; } - private AuditTable defaultAuditTable = new AuditTable() { - public String value() { - return ""; - } - - public String schema() { - return ""; - } - - public String catalog() { - return ""; - } - - public Class annotationType() { - return this.getClass(); - } - }; - private AuditTable getDefaultAuditTable() { - return defaultAuditTable; + return DEFAULT_AUDIT_TABLE; } private class PersistentClassPropertiesSource implements PersistentPropertiesSource { - private final XClass xclass; + private final EntityBinding entityBinding; + private final ClassInfo classInfo; - private PersistentClassPropertiesSource(XClass xclass) { - this.xclass = xclass; + private PersistentClassPropertiesSource(EntityBinding entityBinding, ClassInfo classInfo) { + this.entityBinding = entityBinding; + this.classInfo = classInfo; } @SuppressWarnings({"unchecked"}) - public Iterator getPropertyIterator() { - return pc.getPropertyIterator(); + public Iterable getNonIdAttributeBindings() { + return entityBinding.getNonIdAttributeBindings(); + } + + public AttributeBinding getAttributeBinding(String attributeName) { + return entityBinding.locateAttributeBinding( attributeName ); } - public Property getProperty(String propertyName) { - return pc.getProperty( propertyName ); + @Override + public AttributeBindingContainer getAttributeBindingContainer() { + return entityBinding; } - public XClass getXClass() { - return xclass; + public ClassInfo getClassInfo() { + return classInfo; } } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java index cfc9218e7cad..5ea34eaec591 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java @@ -25,37 +25,42 @@ import java.lang.annotation.Annotation; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; -import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.JoinColumn; -import javax.persistence.MapKey; -import javax.persistence.OneToMany; -import javax.persistence.Version; import org.hibernate.MappingException; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.annotations.common.reflection.XClass; -import org.hibernate.annotations.common.reflection.XProperty; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.AccessType; +import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.envers.AuditJoinTable; -import org.hibernate.envers.AuditMappedBy; import org.hibernate.envers.AuditOverride; import org.hibernate.envers.AuditOverrides; import org.hibernate.envers.Audited; import org.hibernate.envers.ModificationStore; -import org.hibernate.envers.NotAudited; import org.hibernate.envers.RelationTargetAuditMode; -import org.hibernate.envers.configuration.internal.GlobalConfiguration; import org.hibernate.envers.configuration.internal.metadata.MetadataTools; +import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.envers.event.spi.EnversDotNames; import org.hibernate.envers.internal.tools.MappingTools; -import org.hibernate.envers.internal.tools.ReflectionTools; import org.hibernate.envers.internal.tools.StringTools; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Value; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.Hierarchical; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; import static org.hibernate.envers.internal.tools.Tools.newHashMap; import static org.hibernate.envers.internal.tools.Tools.newHashSet; @@ -72,11 +77,11 @@ * @author Lukasz Zuchowski (author at zuchos dot com) */ public class AuditedPropertiesReader { - protected final ModificationStore defaultStore; - private final PersistentPropertiesSource persistentPropertiesSource; + private final AuditConfiguration.AuditConfigurationContext context; + // TODO: is AttributeBindingContainer actually needed or is Hierarchical sufficient? + private final PersistentPropertiesSource processedPersistentPropertiesSource; + private final ClassInfo processedClassInfo; private final AuditedPropertiesHolder auditedPropertiesHolder; - private final GlobalConfiguration globalCfg; - private final ReflectionManager reflectionManager; private final String propertyNamePrefix; private final Set propertyAccessedPersistentProperties; @@ -84,24 +89,23 @@ public class AuditedPropertiesReader { // Mapping class field to corresponding element. private final Map propertiesGroupMapping; - private final Set overriddenAuditedProperties; - private final Set overriddenNotAuditedProperties; + private final Set overriddenAuditedProperties; + private final Set overriddenNotAuditedProperties; - private final Set overriddenAuditedClasses; - private final Set overriddenNotAuditedClasses; + private final Set overriddenAuditedClasses; + private final Set overriddenNotAuditedClasses; public AuditedPropertiesReader( - ModificationStore defaultStore, - PersistentPropertiesSource persistentPropertiesSource, + AuditConfiguration.AuditConfigurationContext context, AuditedPropertiesHolder auditedPropertiesHolder, - GlobalConfiguration globalCfg, - ReflectionManager reflectionManager, + PersistentPropertiesSource processedPersistentPropertiesSource, String propertyNamePrefix) { - this.defaultStore = defaultStore; - this.persistentPropertiesSource = persistentPropertiesSource; + this.context = context; this.auditedPropertiesHolder = auditedPropertiesHolder; - this.globalCfg = globalCfg; - this.reflectionManager = reflectionManager; + this.processedPersistentPropertiesSource = processedPersistentPropertiesSource; + this.processedClassInfo = context.getClassInfo( + processedPersistentPropertiesSource.getAttributeBindingContainer().getAttributeContainer() + ); this.propertyNamePrefix = propertyNamePrefix; propertyAccessedPersistentProperties = newHashSet(); @@ -119,103 +123,122 @@ public void read() { // First reading the access types for the persistent properties. readPersistentPropertiesAccess(); - if ( persistentPropertiesSource instanceof DynamicComponentSource ) { - addPropertiesFromDynamicComponent( (DynamicComponentSource) persistentPropertiesSource ); + if ( processedPersistentPropertiesSource instanceof DynamicComponentSource ) { + addPropertiesFromDynamicComponent( (DynamicComponentSource) processedPersistentPropertiesSource ); } else { // Retrieve classes and properties that are explicitly marked for auditing process by any superclass // of currently mapped entity or itself. - final XClass clazz = persistentPropertiesSource.getXClass(); - readAuditOverrides( clazz ); + readAuditOverrides( + processedClassInfo, + (Hierarchical) processedPersistentPropertiesSource.getAttributeBindingContainer().getAttributeContainer() + ); // Adding all properties from the given class. - addPropertiesFromClass( clazz ); + addPropertiesFromClass( processedPersistentPropertiesSource.getAttributeBindingContainer() ); } } + protected AuditConfiguration.AuditConfigurationContext getContext() { + return context; + } + /** * Recursively constructs sets of audited and not audited properties and classes which behavior has been overridden * using {@link AuditOverride} annotation. * - * @param clazz Class that is being processed. Currently mapped entity shall be passed during first invocation. + * @param classInfo Class that is being processed. Currently mapped entity shall be passed during first invocation. */ - private void readAuditOverrides(XClass clazz) { - /* TODO: Code to remove with @Audited.auditParents - start. */ - final Audited allClassAudited = clazz.getAnnotation( Audited.class ); - if ( allClassAudited != null && allClassAudited.auditParents().length > 0 ) { - for ( Class c : allClassAudited.auditParents() ) { - final XClass parentClass = reflectionManager.toXClass( c ); - checkSuperclass( clazz, parentClass ); - if ( !overriddenNotAuditedClasses.contains( parentClass ) ) { - // If the class has not been marked as not audited by the subclass. - overriddenAuditedClasses.add( parentClass ); - } - } - } - /* TODO: Code to remove with @Audited.auditParents - finish. */ - final List auditOverrides = computeAuditOverrides( clazz ); - for ( AuditOverride auditOverride : auditOverrides ) { - if ( auditOverride.forClass() != void.class ) { - final XClass overrideClass = reflectionManager.toXClass( auditOverride.forClass() ); - checkSuperclass( clazz, overrideClass ); - final String propertyName = auditOverride.name(); + private void readAuditOverrides(ClassInfo classInfo, Hierarchical hierarchical) { + final ClassLoaderService classLoaderService = context.getClassLoaderService() ; + // TODO: Remove auditParents. + final List auditOverrides = computeAuditOverrides( classInfo ); + for (AnnotationInstance auditOverride : auditOverrides) { + final String overrideClassName = JandexHelper.getValue( + auditOverride, "forClass", String.class, classLoaderService + ); + final boolean isAudited = JandexHelper.getValue( + auditOverride, "isAudited", boolean.class, classLoaderService + ); + if ( !void.class.getName().equals( overrideClassName )) { + final ClassInfo overrideClassInfo = context.getClassInfo( overrideClassName ); + checkSuperclass( classInfo, overrideClassInfo ); + final Hierarchical overrideHierarchical = getSuperHierarchical( hierarchical, overrideClassName ); + final String propertyName = JandexHelper.getValue( auditOverride, "name", String.class, classLoaderService ); if ( !StringTools.isEmpty( propertyName ) ) { // Override @Audited annotation on property level. - final XProperty property = getProperty( overrideClass, propertyName ); - if ( auditOverride.isAudited() ) { - if ( !overriddenNotAuditedProperties.contains( property ) ) { + final Attribute overrideAttribute = getAttribute( overrideHierarchical, propertyName ); + if ( isAudited ) { + if ( !overriddenNotAuditedProperties.contains( overrideAttribute ) ) { // If the property has not been marked as not audited by the subclass. - overriddenAuditedProperties.add( property ); + overriddenAuditedProperties.add( overrideAttribute ); } } else { - if ( !overriddenAuditedProperties.contains( property ) ) { + if ( !overriddenAuditedProperties.contains( overrideAttribute ) ) { // If the property has not been marked as audited by the subclass. - overriddenNotAuditedProperties.add( property ); + overriddenNotAuditedProperties.add( overrideAttribute ); } } - } - else { + } else { // Override @Audited annotation on class level. - if ( auditOverride.isAudited() ) { - if ( !overriddenNotAuditedClasses.contains( overrideClass ) ) { + if ( isAudited ) { + if (!overriddenNotAuditedClasses.contains( overrideHierarchical )) { // If the class has not been marked as not audited by the subclass. - overriddenAuditedClasses.add( overrideClass ); + overriddenAuditedClasses.add( overrideHierarchical ); } - } - else { - if ( !overriddenAuditedClasses.contains( overrideClass ) ) { + } else { + if (!overriddenAuditedClasses.contains( overrideHierarchical )) { // If the class has not been marked as audited by the subclass. - overriddenNotAuditedClasses.add( overrideClass ); + overriddenNotAuditedClasses.add( overrideHierarchical ); } } } } } - final XClass superclass = clazz.getSuperclass(); - if ( !clazz.isInterface() && !Object.class.getName().equals( superclass.getName() ) ) { - readAuditOverrides( superclass ); + // TODO: how to distinguish interface: !clazz.isInterface() && + // if (!clazz.isInterface() && !Object.class.getName().equals(superclass.getName())) { + if ( !Object.class.getName().equals( classInfo.superName().toString() ) ) { + readAuditOverrides( context.getClassInfo( classInfo.superName() ), hierarchical.getSuperType() ); } } + private Hierarchical getSuperHierarchical(Hierarchical hierarchical, String superclassName) { + Hierarchical superHierarchical = hierarchical.getSuperType(); + while ( superHierarchical != null ) { + if ( superclassName.equals( superHierarchical.getDescriptor().getName().toString() ) ) { + return superHierarchical; + } + superHierarchical = superHierarchical.getSuperType(); + } + throw new IllegalStateException( + String.format( "Hierarchical [%s] does not have a superclass with name [%s] ", + hierarchical.getRoleBaseName(), + superclassName + ) + ); + } + /** - * @param clazz Source class. + * @param classInfo Source {@link ClassInfo}. * * @return List of @AuditOverride annotations applied at class level. */ - private List computeAuditOverrides(XClass clazz) { - final AuditOverrides auditOverrides = clazz.getAnnotation( AuditOverrides.class ); - final AuditOverride auditOverride = clazz.getAnnotation( AuditOverride.class ); + private List computeAuditOverrides(ClassInfo classInfo) { + AnnotationInstance auditOverrides = JandexHelper.getSingleAnnotation( classInfo, EnversDotNames.AUDIT_OVERRIDES ); + AnnotationInstance auditOverride = JandexHelper.getSingleAnnotation( classInfo, EnversDotNames.AUDIT_OVERRIDE ); if ( auditOverrides == null && auditOverride != null ) { return Arrays.asList( auditOverride ); } else if ( auditOverrides != null && auditOverride == null ) { - return Arrays.asList( auditOverrides.value() ); + return Arrays.asList( + JandexHelper.getValue( auditOverrides, "value", AnnotationInstance[].class, context.getClassLoaderService() ) + ); } else if ( auditOverrides != null && auditOverride != null ) { throw new MappingException( "@AuditOverrides annotation should encapsulate all @AuditOverride declarations. " + - "Please revise Envers annotations applied to class " + clazz.getName() + "." + "Please revise Envers annotations applied to class " + classInfo.name() + "." ); } return Collections.emptyList(); @@ -223,15 +246,14 @@ else if ( auditOverrides != null && auditOverride != null ) { /** * Checks whether one class is assignable from another. If not {@link MappingException} is thrown. - * * @param child Subclass. * @param parent Superclass. */ - private void checkSuperclass(XClass child, XClass parent) { - if ( !parent.isAssignableFrom( child ) ) { + private void checkSuperclass(ClassInfo child, ClassInfo parent) { + if ( !context.getJandexIndex().getAllKnownSubclasses( parent.name() ).contains( child ) ) { throw new MappingException( - "Class " + parent.getName() + " is not assignable from " + child.getName() + ". " + - "Please revise Envers annotations applied to " + child.getName() + " type." + "Class " + parent.name() + " is not assignable from " + child.name() + ". " + + "Please revise Envers annotations applied to " + child.name() + " type." ); } } @@ -239,85 +261,88 @@ private void checkSuperclass(XClass child, XClass parent) { /** * Checks whether class contains property with a given name. If not {@link MappingException} is thrown. * - * @param clazz Class. + * @param hierarchical The Hierarchical domain object.. * @param propertyName Property name. - * - * @return Property object. + * @return the attribute binding. */ - private XProperty getProperty(XClass clazz, String propertyName) { - final XProperty property = ReflectionTools.getProperty( clazz, propertyName ); - if ( property == null ) { + private Attribute getAttribute(Hierarchical hierarchical, String propertyName) { + final Attribute attribute = hierarchical.locateAttribute( propertyName ); + if ( attribute == null ) { throw new MappingException( - "Property '" + propertyName + "' not found in class " + clazz.getName() + ". " + - "Please revise Envers annotations applied to class " + persistentPropertiesSource.getXClass() + "." + "Property '" + propertyName + "' not found in class " + hierarchical.getDescriptor().getName().toString() + ". " + + "Please revise Envers annotations applied to class " + processedClassInfo.name() + "." ); } - return property; + return attribute; } private void readPersistentPropertiesAccess() { - final Iterator propertyIter = persistentPropertiesSource.getPropertyIterator(); - while ( propertyIter.hasNext() ) { - final Property property = propertyIter.next(); - addPersistentProperty( property ); - if ( "embedded".equals( property.getPropertyAccessorName() ) && property.getName() - .equals( property.getNodeName() ) ) { - // If property name equals node name and embedded accessor type is used, processing component - // has been defined with tag. See HHH-6636 JIRA issue. - createPropertiesGroupMapping( property ); - } + for ( AttributeBinding attributeBinding : processedPersistentPropertiesSource.getNonIdAttributeBindings() ) { + addPersistentAttribute( attributeBinding ); +// TODO: if ("embedded".equals(property.getPropertyAccessorName()) && property.getName().equals(property.getNodeName())) { +// // If property name equals node name and embedded accessor type is used, processing component +// // has been defined with tag. See HHH-6636 JIRA issue. +// createPropertiesGroupMapping(property); +// } } } - private void addPersistentProperty(Property property) { - if ( "field".equals( property.getPropertyAccessorName() ) ) { - fieldAccessedPersistentProperties.add( property.getName() ); + private void addPersistentAttribute(AttributeBinding attributeBinding) { + if ( "field".equals( attributeBinding.getPropertyAccessorName() ) ) { + fieldAccessedPersistentProperties.add( attributeBinding.getAttribute().getName() ); } else { - propertyAccessedPersistentProperties.add( property.getName() ); + propertyAccessedPersistentProperties.add( attributeBinding.getAttribute().getName() ); } } - @SuppressWarnings("unchecked") - private void createPropertiesGroupMapping(Property property) { - final Component component = (Component) property.getValue(); - final Iterator componentProperties = component.getPropertyIterator(); - while ( componentProperties.hasNext() ) { - final Property componentProperty = componentProperties.next(); - propertiesGroupMapping.put( componentProperty.getName(), component.getNodeName() ); - } - } + // TODO: add support for + //@SuppressWarnings("unchecked") + //private void createPropertiesGroupMapping(Property property) { + // final Component component = (Component) property.getValue(); + // final Iterator componentProperties = component.getPropertyIterator(); + // while ( componentProperties.hasNext() ) { + // final Property componentProperty = componentProperties.next(); + // propertiesGroupMapping.put( componentProperty.getName(), component.getNodeName() ); + // } + //} /** - * @param clazz Class which properties are currently being added. - * + * @param attributeBindingContainer Class which properties are currently being added. * @return {@link Audited} annotation of specified class. If processed type hasn't been explicitly marked, method * checks whether given class exists in {@link AuditedPropertiesReader#overriddenAuditedClasses} collection. * In case of success, {@link Audited} configuration of currently mapped entity is returned, otherwise * {@code null}. If processed type exists in {@link AuditedPropertiesReader#overriddenNotAuditedClasses} * collection, the result is also {@code null}. */ - private Audited computeAuditConfiguration(XClass clazz) { - Audited allClassAudited = clazz.getAnnotation( Audited.class ); + private Audited computeAuditConfiguration(AttributeBindingContainer attributeBindingContainer) { + final ClassInfo classInfo = context.getClassInfo( attributeBindingContainer.getAttributeContainer() ); + // TODO: Check this method if I have migrated everything correctly. + final AnnotationInstance allClassAudited = JandexHelper.getSingleAnnotation( + classInfo.annotations(), + EnversDotNames.AUDITED, + classInfo + ); // If processed class is not explicitly marked with @Audited annotation, check whether auditing is // forced by any of its child entities configuration (@AuditedOverride.forClass). - if ( allClassAudited == null && overriddenAuditedClasses.contains( clazz ) ) { + final Hierarchical hierarchical = (Hierarchical) attributeBindingContainer.getAttributeContainer(); + if ( allClassAudited == null && overriddenAuditedClasses.contains( hierarchical ) ) { // Declared audited parent copies @Audited.modStore and @Audited.targetAuditMode configuration from // currently mapped entity. - allClassAudited = persistentPropertiesSource.getXClass().getAnnotation( Audited.class ); - if ( allClassAudited == null ) { + if ( JandexHelper.getSingleAnnotation( processedClassInfo, EnversDotNames.AUDITED ) == null ) { // If parent class declares @Audited on the field/property level. - allClassAudited = DEFAULT_AUDITED; + return DEFAULT_AUDITED; } } - else if ( allClassAudited != null && overriddenNotAuditedClasses.contains( clazz ) ) { + else if ( allClassAudited != null && overriddenNotAuditedClasses.contains( hierarchical ) ) { return null; } - return allClassAudited; + + return allClassAudited == null ? null : context.getAnnotationProxy( allClassAudited, Audited.class ); } private void addPropertiesFromDynamicComponent(DynamicComponentSource dynamicComponentSource) { - Audited audited = computeAuditConfiguration( dynamicComponentSource.getXClass() ); + Audited audited = computeAuditConfiguration( dynamicComponentSource.getAttributeBindingContainer() ); if ( !fieldAccessedPersistentProperties.isEmpty() ) { throw new MappingException( "Audited dynamic component cannot have properties with access=\"field\" for properties: " + fieldAccessedPersistentProperties + ". \n Change properties access=\"property\", to make it work)" @@ -326,18 +351,17 @@ private void addPropertiesFromDynamicComponent(DynamicComponentSource dynamicCom for ( String property : propertyAccessedPersistentProperties ) { String accessType = AccessType.PROPERTY.getType(); if ( !auditedPropertiesHolder.contains( property ) ) { - final Value propertyValue = persistentPropertiesSource.getProperty( property ).getValue(); - if ( propertyValue instanceof Component ) { + final AttributeBinding attributeBinding = processedPersistentPropertiesSource.getAttributeBinding( property ); + if ( EmbeddedAttributeBinding.class.isInstance( attributeBinding ) ) { this.addFromComponentProperty( - new DynamicProperty( dynamicComponentSource, property ), + (EmbeddedAttributeBinding) attributeBinding, accessType, - (Component) propertyValue, audited ); } else { this.addFromNotComponentProperty( - new DynamicProperty( dynamicComponentSource, property ), + attributeBinding, accessType, audited ); @@ -346,218 +370,218 @@ private void addPropertiesFromDynamicComponent(DynamicComponentSource dynamicCom } } + private Collection getAttributeBindings( + AttributeBindingContainer attributeBindingContainer, + String propertyAccessorName) { + // TODO: why a LinkedList? + final List attributes = new LinkedList(); + for ( AttributeBinding attributeBinding : attributeBindingContainer.attributeBindings() ) { + if ( propertyAccessorName.equals( attributeBinding.getPropertyAccessorName() ) ) { + attributes.add( attributeBinding ); + } + } + return attributes; + } + /** * Recursively adds all audited properties of entity class and its superclasses. * - * @param clazz Currently processed class. + * @param attributeBindingContainer Currently processed attribute binding container.. */ - private void addPropertiesFromClass(XClass clazz) { - final Audited allClassAudited = computeAuditConfiguration( clazz ); + private void addPropertiesFromClass(AttributeBindingContainer attributeBindingContainer) { + final ClassInfo classInfo = context.getClassInfo( attributeBindingContainer.getAttributeContainer() ); + + final Audited allClassAudited = computeAuditConfiguration( attributeBindingContainer ); //look in the class - addFromProperties( - clazz.getDeclaredProperties( "field" ), - "field", - fieldAccessedPersistentProperties, - allClassAudited - ); - addFromProperties( - clazz.getDeclaredProperties( "property" ), - "property", - propertyAccessedPersistentProperties, - allClassAudited - ); + addFromProperties( getAttributeBindings( attributeBindingContainer, "field" ), "field", fieldAccessedPersistentProperties, allClassAudited ); + addFromProperties( getAttributeBindings( attributeBindingContainer, "property" ), "property", propertyAccessedPersistentProperties, allClassAudited ); if ( allClassAudited != null || !auditedPropertiesHolder.isEmpty() ) { - final XClass superclazz = clazz.getSuperclass(); - if ( !clazz.isInterface() && !"java.lang.Object".equals( superclazz.getName() ) ) { - addPropertiesFromClass( superclazz ); + if ( EntityBinding.class.isInstance( attributeBindingContainer ) ) { + final EntityBinding entityBinding = (EntityBinding) attributeBindingContainer; + if ( entityBinding.getSuperEntityBinding() != null ) { + addPropertiesFromClass( entityBinding.getSuperEntityBinding() ); + } } } } private void addFromProperties( - Iterable properties, + Iterable attributes, String accessType, Set persistentProperties, Audited allClassAudited) { - for ( XProperty property : properties ) { - // If this is not a persistent property, with the same access type as currently checked, - // it's not audited as well. - // If the property was already defined by the subclass, is ignored by superclasses - if ( persistentProperties.contains( property.getName() ) - && !auditedPropertiesHolder.contains( property.getName() ) ) { - final Value propertyValue = persistentPropertiesSource.getProperty( property.getName() ).getValue(); - if ( propertyValue instanceof Component ) { - this.addFromComponentProperty( property, accessType, (Component) propertyValue, allClassAudited ); - } - else { - this.addFromNotComponentProperty( property, accessType, allClassAudited ); - } - } - else if ( propertiesGroupMapping.containsKey( property.getName() ) ) { - // Retrieve embedded component name based on class field. - final String embeddedName = propertiesGroupMapping.get( property.getName() ); - if ( !auditedPropertiesHolder.contains( embeddedName ) ) { - // Manage properties mapped within tag. - final Value propertyValue = persistentPropertiesSource.getProperty( embeddedName ).getValue(); - this.addFromPropertiesGroup( - embeddedName, - property, - accessType, - (Component) propertyValue, - allClassAudited - ); + for ( AttributeBinding attributeBinding : attributes ) { + // If this is not a persistent property, with the same access type as currently checked, + // it's not audited as well. + // If the property was already defined by the subclass, is ignored by superclasses + final String attributeName = attributeBinding.getAttribute().getName(); + if ( persistentProperties.contains( attributeName ) && !auditedPropertiesHolder.contains( attributeName ) ) { + if ( attributeBinding instanceof EmbeddedAttributeBinding ) { + this.addFromComponentProperty( + (EmbeddedAttributeBinding) attributeBinding, accessType, allClassAudited + ); + } + else { + // TODO: is "this." needed? + this.addFromNotComponentProperty( attributeBinding, accessType, allClassAudited ); + } } - } +// TODO: else if ( propertiesGroupMapping.containsKey( attributeName ) ) { +// // Retrieve embedded component name based on class field. +// final String embeddedName = propertiesGroupMapping.get(attributeName); +// if (!auditedPropertiesHolder.contains(embeddedName)) { +// // Manage properties mapped within tag. +// Value propertyValue = persistentPropertiesSource.getProperty(embeddedName).getValue(); +// this.addFromPropertiesGroup( embeddedName, property, accessType, (Component) propertyValue, allClassAudited ); +// } +// } } } - private void addFromPropertiesGroup( - String embeddedName, - XProperty property, - String accessType, - Component propertyValue, - Audited allClassAudited) { - final ComponentAuditingData componentData = new ComponentAuditingData(); - final boolean isAudited = fillPropertyData( property, componentData, accessType, allClassAudited ); - if ( isAudited ) { - // EntityPersister.getPropertyNames() returns name of embedded component instead of class field. - componentData.setName( embeddedName ); - // Marking component properties as placed directly in class (not inside another component). - componentData.setBeanName( null ); - - final PersistentPropertiesSource componentPropertiesSource = new ComponentPropertiesSource( - reflectionManager, - propertyValue - ); - final AuditedPropertiesReader audPropReader = new AuditedPropertiesReader( - ModificationStore.FULL, componentPropertiesSource, componentData, globalCfg, reflectionManager, - propertyNamePrefix + MappingTools.createComponentPrefix( embeddedName ) - ); - audPropReader.read(); - - auditedPropertiesHolder.addPropertyAuditingData( embeddedName, componentData ); - } - } +// TODO: private void addFromPropertiesGroup( +// String embeddedName, +// XProperty property, +// String accessType, +// Component propertyValue, +// Audited allClassAudited) { +// final ComponentAuditingData componentData = new ComponentAuditingData(); +// final boolean isAudited = fillPropertyData( property, componentData, accessType, allClassAudited ); +// if ( isAudited ) { +// // EntityPersister.getPropertyNames() returns name of embedded component instead of class field. +// componentData.setName( embeddedName ); +// // Marking component properties as placed directly in class (not inside another component). +// componentData.setBeanName( null ); +// +// final PersistentPropertiesSource componentPropertiesSource = new ComponentPropertiesSource( +// reflectionManager, +// propertyValue +// ); +// final AuditedPropertiesReader audPropReader = new AuditedPropertiesReader( +// ModificationStore.FULL, componentPropertiesSource, componentData, globalCfg, reflectionManager, +// propertyNamePrefix + MappingTools.createComponentPrefix( embeddedName ) +// ); +// audPropReader.read(); +// +// auditedPropertiesHolder.addPropertyAuditingData( embeddedName, componentData ); +// } +// } private void addFromComponentProperty( - XProperty property, + EmbeddedAttributeBinding attributeBinding, String accessType, - Component propertyValue, Audited allClassAudited) { final ComponentAuditingData componentData = new ComponentAuditingData(); - final boolean isAudited = fillPropertyData( property, componentData, accessType, allClassAudited ); + final boolean isAudited = fillPropertyData( attributeBinding.getAttribute(), componentData, accessType, allClassAudited ); final PersistentPropertiesSource componentPropertiesSource; - if ( propertyValue.isDynamic() ) { - componentPropertiesSource = new DynamicComponentSource( reflectionManager, propertyValue, property ); - } - else { - componentPropertiesSource = new ComponentPropertiesSource( reflectionManager, propertyValue ); - } + // TODO: + //if ( attributeBinding.isDynamic() ) { + // componentPropertiesSource = new DynamicComponentSource( attributeBinding ); + //} + //else { + componentPropertiesSource = new ComponentPropertiesSource( + context.getClassInfo( attributeBinding.getEmbeddableBinding().getAttributeContainer() ), + attributeBinding.getEmbeddableBinding() + ); + //} final ComponentAuditedPropertiesReader audPropReader = new ComponentAuditedPropertiesReader( - ModificationStore.FULL, - componentPropertiesSource, + context, componentData, - globalCfg, - reflectionManager, - propertyNamePrefix + MappingTools.createComponentPrefix( property.getName() ) + componentPropertiesSource, + propertyNamePrefix + MappingTools.createComponentPrefix( attributeBinding.getAttribute().getName() ) ); audPropReader.read(); if ( isAudited ) { // Now we know that the property is audited - auditedPropertiesHolder.addPropertyAuditingData( property.getName(), componentData ); + auditedPropertiesHolder.addPropertyAuditingData( attributeBinding.getAttribute().getName(), componentData ); } } - private void addFromNotComponentProperty(XProperty property, String accessType, Audited allClassAudited) { - final PropertyAuditingData propertyData = new PropertyAuditingData(); - final boolean isAudited = fillPropertyData( property, propertyData, accessType, allClassAudited ); + private void addFromNotComponentProperty(AttributeBinding attributeBinding, String accessType, Audited allClassAudited) { + PropertyAuditingData propertyData = new PropertyAuditingData(); + boolean isAudited = fillPropertyData( attributeBinding.getAttribute(), propertyData, accessType, allClassAudited ); if ( isAudited ) { // Now we know that the property is audited - auditedPropertiesHolder.addPropertyAuditingData( property.getName(), propertyData ); + auditedPropertiesHolder.addPropertyAuditingData( attributeBinding.getAttribute().getName(), propertyData ); } } - /** * Checks if a property is audited and if yes, fills all of its data. - * - * @param property Property to check. + * @param attribute Property to check. * @param propertyData Property data, on which to set this property's modification store. * @param accessType Access type for the property. - * * @return False if this property is not audited. */ private boolean fillPropertyData( - XProperty property, + Attribute attribute, PropertyAuditingData propertyData, String accessType, Audited allClassAudited) { - // check if a property is declared as not audited to exclude it // useful if a class is audited but some properties should be excluded - final NotAudited unVer = property.getAnnotation( NotAudited.class ); - if ( ( unVer != null - && !overriddenAuditedProperties.contains( property ) ) - || overriddenNotAuditedProperties.contains( property ) ) { + Map> attributeAnnotations = context.locateAttributeAnnotations( + attribute + ); + if ( ( attributeAnnotations.containsKey( EnversDotNames.NOT_AUDITED ) && !overriddenAuditedProperties.contains( attribute ) ) + || overriddenNotAuditedProperties.contains( attribute ) ) { return false; } else { // if the optimistic locking field has to be unversioned and the current property // is the optimistic locking field, don't audit it - if ( globalCfg.isDoNotAuditOptimisticLockingField() ) { - final Version jpaVer = property.getAnnotation( Version.class ); - if ( jpaVer != null ) { + if ( context.getGlobalConfiguration().isDoNotAuditOptimisticLockingField() ) { + if ( attributeAnnotations.containsKey( JPADotNames.VERSION ) ) { return false; } } } - - if ( !this.checkAudited( property, propertyData, allClassAudited ) ) { + // TODO: is "this." needed? + if ( !this.checkAudited( attribute, propertyData, allClassAudited ) ) { return false; } - final String propertyName = propertyNamePrefix + property.getName(); + String propertyName = propertyNamePrefix + attribute.getName(); propertyData.setName( propertyName ); propertyData.setModifiedFlagName( MetadataTools.getModifiedFlagPropertyName( propertyName, - globalCfg.getModifiedFlagSuffix() + context.getGlobalConfiguration().getModifiedFlagSuffix() ) ); - propertyData.setBeanName( property.getName() ); + propertyData.setBeanName( attribute.getName() ); propertyData.setAccessType( accessType ); - addPropertyJoinTables( property, propertyData ); - addPropertyAuditingOverrides( property, propertyData ); - if ( !processPropertyAuditingOverrides( property, propertyData ) ) { - // not audited due to AuditOverride annotation - return false; + addPropertyJoinTables( attributeAnnotations, propertyData ); + addPropertyAuditingOverrides( attributeAnnotations, propertyData ); + if ( !processPropertyAuditingOverrides( attribute, propertyData ) ) { + return false; // not audited due to AuditOverride annotation } - addPropertyMapKey( property, propertyData ); - setPropertyAuditMappedBy( property, propertyData ); - setPropertyRelationMappedBy( property, propertyData ); + addPropertyMapKey( attributeAnnotations, propertyData ); + setPropertyAuditMappedBy( attributeAnnotations, propertyData ); + setPropertyRelationMappedBy( attributeAnnotations, propertyData ); return true; } - - protected boolean checkAudited( - XProperty property, - PropertyAuditingData propertyData, Audited allClassAudited) { + protected boolean checkAudited(Attribute attribute, PropertyAuditingData propertyData, Audited allClassAudited) { + Map> attributeAnnotations = context.locateAttributeAnnotations( attribute ); // Checking if this property is explicitly audited or if all properties are. - Audited aud = ( property.isAnnotationPresent( Audited.class ) ) - ? property.getAnnotation( Audited.class ) + Audited aud = attributeAnnotations.containsKey( EnversDotNames.AUDITED ) + ? context.getAnnotationProxy( + attributeAnnotations.get( EnversDotNames.AUDITED ).get( 0 ), + Audited.class + ) : allClassAudited; - if ( aud == null - && overriddenAuditedProperties.contains( property ) - && !overriddenNotAuditedProperties.contains( property ) ) { + if ( aud == null && + overriddenAuditedProperties.contains( attribute ) && + !overriddenNotAuditedProperties.contains( attribute ) ) { // Assigning @Audited defaults. If anyone needs to customize those values in the future, // appropriate fields shall be added to @AuditOverride annotation. aud = DEFAULT_AUDITED; @@ -574,84 +598,117 @@ protected boolean checkAudited( } protected boolean checkUsingModifiedFlag(Audited aud) { - return globalCfg.hasSettingForUsingModifiedFlag() ? - globalCfg.isGlobalWithModifiedFlag() : aud.withModifiedFlag(); + return context.getGlobalConfiguration().hasSettingForUsingModifiedFlag() ? + context.getGlobalConfiguration().isGlobalWithModifiedFlag() : aud.withModifiedFlag(); } - private void setPropertyRelationMappedBy(XProperty property, PropertyAuditingData propertyData) { - final OneToMany oneToMany = property.getAnnotation( OneToMany.class ); - if ( oneToMany != null && !"".equals( oneToMany.mappedBy() ) ) { - propertyData.setRelationMappedBy( oneToMany.mappedBy() ); + private void setPropertyRelationMappedBy(Map> attributeAnnotations, + PropertyAuditingData propertyData) { + final AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( + attributeAnnotations, + JPADotNames.ONE_TO_MANY + ); + if ( oneToMany != null ) { + final String mappedBy = JandexHelper.getValue( + oneToMany, "mappedBy", String.class, context.getClassLoaderService() + ); + if ( StringHelper.isNotEmpty( mappedBy ) ) { + propertyData.setRelationMappedBy( mappedBy ); + } } } - private void setPropertyAuditMappedBy(XProperty property, PropertyAuditingData propertyData) { - final AuditMappedBy auditMappedBy = property.getAnnotation( AuditMappedBy.class ); + private void setPropertyAuditMappedBy( + Map> attributeAnnotations, + PropertyAuditingData propertyData) { + final AnnotationInstance auditMappedBy = JandexHelper.getSingleAnnotation( + attributeAnnotations, + EnversDotNames.AUDIT_MAPPED_BY + ); if ( auditMappedBy != null ) { - propertyData.setAuditMappedBy( auditMappedBy.mappedBy() ); - if ( !"".equals( auditMappedBy.positionMappedBy() ) ) { - propertyData.setPositionMappedBy( auditMappedBy.positionMappedBy() ); + propertyData.setAuditMappedBy( + JandexHelper.getValue( auditMappedBy, "mappedBy", String.class, context.getClassLoaderService() ) + ); + final String positionMappedBy = JandexHelper.getValue( + auditMappedBy, "positionMappedBy", String.class, context.getClassLoaderService() + ); + if ( StringHelper.isNotEmpty( positionMappedBy ) ) { + propertyData.setPositionMappedBy( positionMappedBy ); } } } - private void addPropertyMapKey(XProperty property, PropertyAuditingData propertyData) { - final MapKey mapKey = property.getAnnotation( MapKey.class ); + private void addPropertyMapKey( + Map> attributeAnnotations, + PropertyAuditingData propertyData) { + final AnnotationInstance mapKey = JandexHelper.getSingleAnnotation( attributeAnnotations, JPADotNames.MAP_KEY ); if ( mapKey != null ) { - propertyData.setMapKey( mapKey.name() ); + propertyData.setMapKey( + JandexHelper.getValue( + mapKey, + "name", + String.class, + context.getClassLoaderService() + ) + ); } } - private void addPropertyJoinTables(XProperty property, PropertyAuditingData propertyData) { + private void addPropertyJoinTables(Map> attributeAnnotations, + PropertyAuditingData propertyData) { // first set the join table based on the AuditJoinTable annotation - final AuditJoinTable joinTable = property.getAnnotation( AuditJoinTable.class ); + final AnnotationInstance joinTable = JandexHelper.getSingleAnnotation( + attributeAnnotations, + EnversDotNames.AUDIT_JOIN_TABLE + ); if ( joinTable != null ) { - propertyData.setJoinTable( joinTable ); - } - else { + propertyData.setJoinTable( context.getAnnotationProxy( joinTable, AuditJoinTable.class ) ); + } else { propertyData.setJoinTable( DEFAULT_AUDIT_JOIN_TABLE ); } } - /** - * Add the {@link AuditOverride} annotations. + /*** + * Add the {@link org.hibernate.envers.AuditOverride} annotations. * - * @param property the property being processed + * @param attributeAnnotations the property being processed * @param propertyData the Envers auditing data for this property */ - private void addPropertyAuditingOverrides(XProperty property, PropertyAuditingData propertyData) { - final AuditOverride annotationOverride = property.getAnnotation( AuditOverride.class ); + private void addPropertyAuditingOverrides( + Map> attributeAnnotations, + PropertyAuditingData propertyData) { + final AnnotationInstance annotationOverride = JandexHelper.getSingleAnnotation( attributeAnnotations, EnversDotNames.AUDIT_OVERRIDE ); if ( annotationOverride != null ) { - propertyData.addAuditingOverride( annotationOverride ); + propertyData.addAuditingOverride( context.getAnnotationProxy( annotationOverride, AuditOverride.class ) ); } - final AuditOverrides annotationOverrides = property.getAnnotation( AuditOverrides.class ); + final AnnotationInstance annotationOverrides = JandexHelper.getSingleAnnotation( attributeAnnotations, EnversDotNames.AUDIT_OVERRIDES ); if ( annotationOverrides != null ) { - propertyData.addAuditingOverrides( annotationOverrides ); + propertyData.addAuditingOverrides( context.getAnnotationProxy( annotationOverrides, AuditOverrides.class ) ); } } /** - * Process the {@link AuditOverride} annotations for this property. - * - * @param property the property for which the {@link AuditOverride} - * annotations are being processed - * @param propertyData the Envers auditing data for this property + * Process the {@link org.hibernate.envers.AuditOverride} annotations for this property. * + * @param attribute + * the property for which the {@link org.hibernate.envers.AuditOverride} + * annotations are being processed + * @param propertyData + * the Envers auditing data for this property * @return {@code false} if isAudited() of the override annotation was set to */ - private boolean processPropertyAuditingOverrides(XProperty property, PropertyAuditingData propertyData) { + private boolean processPropertyAuditingOverrides(Attribute attribute, PropertyAuditingData propertyData) { // if this property is part of a component, process all override annotations - if ( this.auditedPropertiesHolder instanceof ComponentAuditingData ) { - final List overrides = ( (ComponentAuditingData) this.auditedPropertiesHolder ).getAuditingOverrides(); - for ( AuditOverride override : overrides ) { - if ( property.getName().equals( override.name() ) ) { + if (this.auditedPropertiesHolder instanceof ComponentAuditingData) { + List overrides = ((ComponentAuditingData) this.auditedPropertiesHolder).getAuditingOverrides(); + for (AuditOverride override : overrides) { + if (attribute.getName().equals(override.name())) { // the override applies to this property - if ( !override.isAudited() ) { + if (!override.isAudited()) { return false; - } - else { - if ( override.auditJoinTable() != null ) { - propertyData.setJoinTable( override.auditJoinTable() ); + } else { + if (override.auditJoinTable() != null) { + propertyData.setJoinTable(override.auditJoinTable()); } } } @@ -716,50 +773,46 @@ public Class annotationType() { }; public static class ComponentPropertiesSource implements PersistentPropertiesSource { - private final XClass xclass; - private final Component component; + private final ClassInfo classInfo; + private final AttributeBindingContainer attributeBindingContainer; - protected ComponentPropertiesSource(XClass xClazz, Component component) { - this.xclass = xClazz; - this.component = component; + public ComponentPropertiesSource( + ClassInfo classInfo, + AttributeBindingContainer attributeBindingContainer) { + this.classInfo = classInfo; + this.attributeBindingContainer = attributeBindingContainer; } - public ComponentPropertiesSource(ReflectionManager reflectionManager, Component component) { - try { - this.xclass = reflectionManager.classForName( component.getComponentClassName(), this.getClass() ); - } - catch ( ClassNotFoundException e ) { - throw new MappingException( e ); - } - - this.component = component; + @Override + @SuppressWarnings({ "unchecked" }) + public Iterable getNonIdAttributeBindings() { + return attributeBindingContainer.attributeBindings(); } @Override - @SuppressWarnings({ "unchecked" }) - public Iterator getPropertyIterator() { - return component.getPropertyIterator(); + public AttributeBinding getAttributeBinding(String attributeName) { + return attributeBindingContainer.locateAttributeBinding( attributeName ); } @Override - public Property getProperty(String propertyName) { - return component.getProperty( propertyName ); + public AttributeBindingContainer getAttributeBindingContainer() { + return attributeBindingContainer; } @Override - public XClass getXClass() { - return xclass; + public ClassInfo getClassInfo() { + return classInfo; } } public static class DynamicComponentSource extends ComponentPropertiesSource { - private XProperty baseProperty; - - public DynamicComponentSource(ReflectionManager reflectionManager, Component component, XProperty baseProperty) { - super( reflectionManager.toXClass( Map.class ), component ); - this.baseProperty = baseProperty; + public DynamicComponentSource( + AttributeBindingContainer attributeBindingContainer) { + //TODO: need a ClassInfo for Map. + //super( reflectionManager.toXClass( Map.class ), attributeBindingContainer ); + super( null, attributeBindingContainer ); + throw new NotYetImplementedException( "dynamic components are not supported yet." ); } } - } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ClassAuditingData.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ClassAuditingData.java index ed20a7f5bf02..beace10747b4 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ClassAuditingData.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ClassAuditingData.java @@ -25,6 +25,8 @@ import java.util.Map; +import org.jboss.jandex.AnnotationInstance; + import org.hibernate.envers.AuditTable; import static org.hibernate.envers.internal.tools.Tools.newHashMap; diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java index fa7d2502373c..969081a2be3a 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java @@ -23,11 +23,17 @@ */ package org.hibernate.envers.configuration.internal.metadata.reader; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.annotations.common.reflection.XProperty; +import java.util.List; +import java.util.Map; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + import org.hibernate.envers.Audited; import org.hibernate.envers.ModificationStore; -import org.hibernate.envers.configuration.internal.GlobalConfiguration; +import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.envers.event.spi.EnversDotNames; +import org.hibernate.metamodel.spi.domain.Attribute; /** * Reads the audited properties for components. @@ -38,25 +44,29 @@ public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader { public ComponentAuditedPropertiesReader( - ModificationStore defaultStore, - PersistentPropertiesSource persistentPropertiesSource, + AuditConfiguration.AuditConfigurationContext context, AuditedPropertiesHolder auditedPropertiesHolder, - GlobalConfiguration globalCfg, ReflectionManager reflectionManager, + PersistentPropertiesSource persistentPropertiesSource, String propertyNamePrefix) { super( - defaultStore, persistentPropertiesSource, auditedPropertiesHolder, - globalCfg, reflectionManager, propertyNamePrefix + context, auditedPropertiesHolder, persistentPropertiesSource, propertyNamePrefix ); } @Override protected boolean checkAudited( - XProperty property, + Attribute attribute, PropertyAuditingData propertyData, Audited allClassAudited) { // Checking if this property is explicitly audited or if all properties are. - final Audited aud = property.getAnnotation( Audited.class ); - if ( aud != null ) { + final Map> attributeAnnotations = + getContext().locateAttributeAnnotations( attribute ); + // Checking if this property is explicitly audited or if all properties are. + if ( attributeAnnotations.containsKey( EnversDotNames.AUDITED ) ) { + final Audited aud = getContext().getAnnotationProxy( + attributeAnnotations.get( EnversDotNames.AUDITED ).get( 0 ), + Audited.class + ); propertyData.setStore( aud.modStore() ); propertyData.setRelationTargetAuditMode( aud.targetAuditMode() ); propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/DynamicProperty.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/DynamicProperty.java deleted file mode 100644 index 7b0b7ec30374..000000000000 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/DynamicProperty.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.hibernate.envers.configuration.internal.metadata.reader; - -import java.lang.annotation.Annotation; -import java.util.Collection; - -import org.hibernate.annotations.common.reflection.XClass; -import org.hibernate.annotations.common.reflection.XProperty; - -/** - * This class prenteds to be property but in fact it represents entry in the map (for dynamic component) - * - * @author Lukasz Zuchowski (author at zuchos dot com) - */ -public class DynamicProperty implements XProperty { - - private AuditedPropertiesReader.DynamicComponentSource source; - private String propertyName; - - public DynamicProperty(AuditedPropertiesReader.DynamicComponentSource source, String propertyName) { - this.source = source; - this.propertyName = propertyName; - } - - @Override - public XClass getDeclaringClass() { - return source.getXClass(); - } - - @Override - public String getName() { - return propertyName; - } - - @Override - public boolean isCollection() { - return false; - } - - @Override - public boolean isArray() { - return false; - } - - @Override - public Class getCollectionClass() { - return null; - } - - @Override - public XClass getType() { - return source.getXClass(); - } - - @Override - public XClass getElementClass() { - return null; - } - - @Override - public XClass getClassOrElementClass() { - return null; - } - - @Override - public XClass getMapKey() { - return null; - } - - @Override - public int getModifiers() { - return 0; - } - - @Override - public void setAccessible(boolean accessible) { - } - - @Override - public Object invoke(Object target, Object... parameters) { - return null; - } - - @Override - public boolean isTypeResolved() { - return false; - } - - @Override - public T getAnnotation(Class annotationType) { - return null; - } - - @Override - public boolean isAnnotationPresent(Class annotationType) { - return false; - } - - @Override - public Annotation[] getAnnotations() { - return new Annotation[0]; - } -} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PersistentPropertiesSource.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PersistentPropertiesSource.java index b4832e5f91ea..2453fc4162e2 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PersistentPropertiesSource.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PersistentPropertiesSource.java @@ -24,9 +24,15 @@ package org.hibernate.envers.configuration.internal.metadata.reader; import java.util.Iterator; +import java.util.List; + +import org.jboss.jandex.ClassInfo; import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.domain.AttributeContainer; /** * A source of data on persistent properties of a class or component. @@ -34,9 +40,11 @@ * @author Adam Warski (adam at warski dot org) */ public interface PersistentPropertiesSource { - Iterator getPropertyIterator(); + Iterable getNonIdAttributeBindings(); + + AttributeBinding getAttributeBinding(String attributeName); - Property getProperty(String propertyName); + AttributeBindingContainer getAttributeBindingContainer(); - XClass getXClass(); + ClassInfo getClassInfo(); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/spi/AuditConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/spi/AuditConfiguration.java index 1c2024b401a5..1d7a94b69748 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/spi/AuditConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/spi/AuditConfiguration.java @@ -24,18 +24,21 @@ package org.hibernate.envers.configuration.spi; import java.util.HashSet; +import java.util.List; import java.util.Map; -import java.util.Properties; +import java.util.UUID; import java.util.WeakHashMap; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; + import org.hibernate.MappingException; -import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.cfg.Configuration; import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration; import org.hibernate.envers.configuration.internal.EntitiesConfigurator; import org.hibernate.envers.configuration.internal.GlobalConfiguration; -import org.hibernate.envers.configuration.internal.RevisionInfoConfiguration; import org.hibernate.envers.configuration.internal.RevisionInfoConfigurationResult; import org.hibernate.envers.internal.entities.EntitiesConfigurations; import org.hibernate.envers.internal.entities.PropertyData; @@ -46,8 +49,13 @@ import org.hibernate.envers.internal.tools.ReflectionTools; import org.hibernate.envers.strategy.AuditStrategy; import org.hibernate.envers.strategy.ValidityAuditStrategy; -import org.hibernate.internal.util.ClassLoaderHelper; import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.AttributeContainer; import org.hibernate.property.Getter; /** @@ -101,45 +109,37 @@ public ClassLoaderService getClassLoaderService() { return classLoaderService; } - public AuditConfiguration(Configuration cfg) { - this( cfg, null ); - } + //public AuditConfiguration(Configuration cfg) { + // this( cfg, null ); + //} + + public AuditConfiguration(AuditConfigurationContext context) { + this.globalCfg = context.getGlobalConfiguration(); + this.auditEntCfg = context.getAuditEntitiesConfiguration(); + + this.auditProcessManager = new AuditProcessManager( context.getRevisionInfoConfigurationResult().getRevisionInfoGenerator() ); + this.revisionInfoQueryCreator = context.getRevisionInfoConfigurationResult().getRevisionInfoQueryCreator(); + this.revisionInfoNumberReader = context.getRevisionInfoConfigurationResult().getRevisionInfoNumberReader(); + this.modifiedEntityNamesReader = context.getRevisionInfoConfigurationResult().getModifiedEntityNamesReader(); - public AuditConfiguration(Configuration cfg, ClassLoaderService classLoaderService) { - // TODO: Temporarily allow Envers to continuing using - // hibernate-commons-annotations' for reflection and class loading. - final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader( ClassLoaderHelper.getContextClassLoader() ); - - final Properties properties = cfg.getProperties(); - - final ReflectionManager reflectionManager = cfg.getReflectionManager(); - this.globalCfg = new GlobalConfiguration( properties, classLoaderService ); - final RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration( globalCfg ); - final RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure( cfg, reflectionManager ); - this.auditEntCfg = new AuditEntitiesConfiguration( properties, revInfoCfgResult.getRevisionInfoEntityName() ); - this.auditProcessManager = new AuditProcessManager( revInfoCfgResult.getRevisionInfoGenerator() ); - this.revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator(); - this.revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader(); - this.modifiedEntityNamesReader = revInfoCfgResult.getModifiedEntityNamesReader(); - this.classLoaderService = classLoaderService; this.auditStrategy = initializeAuditStrategy( - revInfoCfgResult.getRevisionInfoClass(), - revInfoCfgResult.getRevisionInfoTimestampData() + context.getRevisionInfoConfigurationResult().getRevisionInfoClass(), + context.getRevisionInfoConfigurationResult().getRevisionInfoTimestampData() ); this.entCfg = new EntitiesConfigurator().configure( - cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy, classLoaderService, - revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping() + context, + auditStrategy, + context.getRevisionInfoConfigurationResult().getRevisionInfoXmlMapping(), + context.getRevisionInfoConfigurationResult().getRevisionInfoRelationMapping() ); - Thread.currentThread().setContextClassLoader( tccl ); } private AuditStrategy initializeAuditStrategy(Class revisionInfoClass, PropertyData revisionInfoTimestampData) { AuditStrategy strategy; try { - Class auditStrategyClass = null; + Class auditStrategyClass; try { auditStrategyClass = this.getClass().getClassLoader().loadClass( auditEntCfg.getAuditStrategyName() ); } @@ -167,20 +167,19 @@ private AuditStrategy initializeAuditStrategy(Class revisionInfoClass, Proper return strategy; } - private static final Map CFGS = new WeakHashMap(); + private static final Map CFGS = new WeakHashMap(); - public synchronized static AuditConfiguration getFor(Configuration cfg) { - return getFor( cfg, null ); - } + //public synchronized static AuditConfiguration register(MetadataImplementor metadata) { + // return register( metadata, null ); + //} - public synchronized static AuditConfiguration getFor(Configuration cfg, ClassLoaderService classLoaderService) { - AuditConfiguration verCfg = CFGS.get( cfg ); + public synchronized static AuditConfiguration register( + AuditConfigurationContext context, Metadata metadata) { + AuditConfiguration verCfg = CFGS.get( metadata.getUUID() ); if ( verCfg == null ) { - verCfg = new AuditConfiguration( cfg, classLoaderService ); - CFGS.put( cfg, verCfg ); - - cfg.buildMappings(); + verCfg = new AuditConfiguration( context ); + CFGS.put( metadata.getUUID(), verCfg ); } return verCfg; @@ -188,7 +187,7 @@ public synchronized static AuditConfiguration getFor(Configuration cfg, ClassLoa public void destroy() { synchronized (AuditConfiguration.class) { - for ( Map.Entry c : new HashSet>( + for ( Map.Entry c : new HashSet>( CFGS.entrySet() ) ) { if ( c.getValue() == this ) { // this is nasty cleanup fix, whole static CFGS should be reworked CFGS.remove( c.getKey() ); @@ -197,4 +196,41 @@ public void destroy() { } classLoaderService = null; } + + public interface AuditConfigurationContext { + //InFlightMetadataCollector metadataCollector, + //AdditionalJaxbRootProducer.AdditionalJaxbRootProducerContext context, + //GlobalConfiguration globalCfg, + //AuditEntitiesConfiguration verEntCfg, + //AuditStrategy auditStrategy, + + Metadata getMetadata(); + + EntityBinding getEntityBinding(String entityName); + + EntityBinding getEntityBinding(ClassInfo classInfo); + + IndexView getJandexIndex(); + + ClassInfo getClassInfo(String className); + + ClassInfo getClassInfo(DotName classDotName); + + ClassInfo getClassInfo(AttributeContainer attributeContainer); + + ClassLoaderService getClassLoaderService(); + + T getAnnotationProxy(AnnotationInstance annotationInstance, Class annotationClass); + + Map> locateAttributeAnnotations(Attribute attribute); + // return coreConfiguration.locateAttributeAnnotations; + + GlobalConfiguration getGlobalConfiguration(); + + AuditEntitiesConfiguration getAuditEntitiesConfiguration(); + + public RevisionInfoConfigurationResult getRevisionInfoConfigurationResult(); + + void addDocument(org.w3c.dom.Document document); + } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdTrackingModifiedEntitiesRevisionEntity.java b/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdTrackingModifiedEntitiesRevisionEntity.java index 169b74d17e66..0cbe5c0911d5 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdTrackingModifiedEntitiesRevisionEntity.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdTrackingModifiedEntitiesRevisionEntity.java @@ -25,11 +25,11 @@ import java.util.HashSet; import java.util.Set; +import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.FetchType; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.MappedSuperclass; import org.hibernate.annotations.Fetch; @@ -46,7 +46,7 @@ @MappedSuperclass public class SequenceIdTrackingModifiedEntitiesRevisionEntity extends SequenceIdRevisionEntity { @ElementCollection(fetch = FetchType.EAGER) - @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) + @CollectionTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) @Column(name = "ENTITYNAME") @Fetch(FetchMode.JOIN) @ModifiedEntityNames diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversDotNames.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversDotNames.java new file mode 100644 index 000000000000..6e412ef9ae4d --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversDotNames.java @@ -0,0 +1,36 @@ +package org.hibernate.envers.event.spi; + +import org.jboss.jandex.DotName; + +import org.hibernate.envers.AuditJoinTable; +import org.hibernate.envers.AuditMappedBy; +import org.hibernate.envers.AuditOverride; +import org.hibernate.envers.AuditOverrides; +import org.hibernate.envers.AuditTable; +import org.hibernate.envers.Audited; +import org.hibernate.envers.ModifiedEntityNames; +import org.hibernate.envers.NotAudited; +import org.hibernate.envers.RevisionEntity; +import org.hibernate.envers.RevisionNumber; +import org.hibernate.envers.RevisionTimestamp; +import org.hibernate.envers.SecondaryAuditTable; +import org.hibernate.envers.SecondaryAuditTables; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public interface EnversDotNames { + DotName AUDITED = DotName.createSimple( Audited.class.getName() ); + DotName AUDIT_JOIN_TABLE = DotName.createSimple( AuditJoinTable.class.getName() ); + DotName AUDIT_MAPPED_BY = DotName.createSimple( AuditMappedBy.class.getName() ); + DotName AUDIT_OVERRIDE = DotName.createSimple( AuditOverride.class.getName() ); + DotName AUDIT_OVERRIDES = DotName.createSimple( AuditOverrides.class.getName() ); + DotName AUDIT_TABLE = DotName.createSimple( AuditTable.class.getName() ); + DotName MODIFIED_ENTITY_NAMES = DotName.createSimple( ModifiedEntityNames.class.getName() ); + DotName NOT_AUDITED = DotName.createSimple( NotAudited.class.getName() ); + DotName REVISION_ENTITY = DotName.createSimple( RevisionEntity.class.getName() ); + DotName REVISION_NUMBER = DotName.createSimple( RevisionNumber.class.getName() ); + DotName REVISION_TIMESTAMP = DotName.createSimple( RevisionTimestamp.class.getName() ); + DotName SECONDARY_AUDIT_TABLE = DotName.createSimple( SecondaryAuditTable.class.getName() ); + DotName SECONDARY_AUDIT_TABLES = DotName.createSimple( SecondaryAuditTables.class.getName() ); +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversIntegrator.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversIntegrator.java index 1539db52daf3..874c2f049c52 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversIntegrator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversIntegrator.java @@ -23,8 +23,10 @@ */ package org.hibernate.envers.event.spi; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.AssertionFailure; import org.hibernate.cfg.Configuration; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.event.service.spi.EventListenerRegistry; @@ -32,7 +34,7 @@ import org.hibernate.integrator.spi.Integrator; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.jboss.logging.Logger; @@ -73,13 +75,6 @@ public void integrate( final EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); listenerRegistry.addDuplicationStrategy( EnversListenerDuplicationStrategy.INSTANCE ); - enversConfiguration = AuditConfiguration.getFor( - configuration, - serviceRegistry.getService( - ClassLoaderService.class - ) - ); - if ( enversConfiguration.getEntCfg().hasAuditedEntities() ) { listenerRegistry.appendListeners( EventType.POST_DELETE, new EnversPostDeleteEventListenerImpl( @@ -108,6 +103,7 @@ EventType.POST_UPDATE, new EnversPostUpdateEventListenerImpl( EventType.PRE_COLLECTION_UPDATE, new EnversPreCollectionUpdateEventListenerImpl( enversConfiguration ) ); + throw new AssertionFailure( "No longer implemented." ); } } @@ -121,13 +117,60 @@ public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactor /** * {@inheritDoc} * - * @see org.hibernate.integrator.spi.Integrator#integrate(org.hibernate.metamodel.source.MetadataImplementor, org.hibernate.engine.spi.SessionFactoryImplementor, org.hibernate.service.spi.SessionFactoryServiceRegistry) + * @see org.hibernate.integrator.spi.Integrator#integrate(org.hibernate.metamodel.spi.MetadataImplementor, org.hibernate.engine.spi.SessionFactoryImplementor, org.hibernate.service.spi.SessionFactoryServiceRegistry) */ @Override public void integrate( MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - // TODO: implement + final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); + final boolean autoRegister = configurationService.getSetting( + AUTO_REGISTER, + StandardConverters.BOOLEAN, + true + ); + if ( !autoRegister ) { + LOG.debug( "Skipping Envers listener auto registration" ); + return; + } + + final EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); + listenerRegistry.addDuplicationStrategy( EnversListenerDuplicationStrategy.INSTANCE ); + + enversConfiguration = AuditConfiguration.register( + null, + metadata + ); + + if ( enversConfiguration.getEntCfg().hasAuditedEntities() ) { + listenerRegistry.appendListeners( + EventType.POST_DELETE, new EnversPostDeleteEventListenerImpl( + enversConfiguration + ) + ); + listenerRegistry.appendListeners( + EventType.POST_INSERT, new EnversPostInsertEventListenerImpl( + enversConfiguration + ) + ); + listenerRegistry.appendListeners( + EventType.POST_UPDATE, new EnversPostUpdateEventListenerImpl( + enversConfiguration + ) + ); + listenerRegistry.appendListeners( + EventType.POST_COLLECTION_RECREATE, + new EnversPostCollectionRecreateEventListenerImpl( enversConfiguration ) + ); + listenerRegistry.appendListeners( + EventType.PRE_COLLECTION_REMOVE, + new EnversPreCollectionRemoveEventListenerImpl( enversConfiguration ) + ); + listenerRegistry.appendListeners( + EventType.PRE_COLLECTION_UPDATE, + new EnversPreCollectionUpdateEventListenerImpl( enversConfiguration ) + ); + } } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversJaxbRootProducer.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversJaxbRootProducer.java new file mode 100644 index 000000000000..1488af19080c --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/EnversJaxbRootProducer.java @@ -0,0 +1,200 @@ +package org.hibernate.envers.event.spi; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; +import org.jboss.logging.Logger; + +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.envers.configuration.internal.AnnotationProxyBuilder; +import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration; +import org.hibernate.envers.configuration.internal.GlobalConfiguration; +import org.hibernate.envers.configuration.internal.RevisionInfoConfiguration; +import org.hibernate.envers.configuration.internal.RevisionInfoConfigurationResult; +import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.AdditionalJaxbRootProducer; +import org.hibernate.metamodel.spi.InFlightMetadataCollector; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.domain.Attribute; +import org.hibernate.metamodel.spi.domain.AttributeContainer; +import org.hibernate.xml.internal.jaxb.MappingXmlBinder; +import org.hibernate.xml.spi.BindResult; +import org.hibernate.xml.spi.Origin; +import org.hibernate.xml.spi.SourceType; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class EnversJaxbRootProducer implements AdditionalJaxbRootProducer { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + EnversJaxbRootProducer.class.getName() + ); + + @Override + public List produceRoots( + final InFlightMetadataCollector metadataCollector, + final AdditionalJaxbRootProducerContext additionalJaxbRootProducerContext) { + + final AuditConfigurationContextImpl context = new AuditConfigurationContextImpl( + metadataCollector, + additionalJaxbRootProducerContext + ); + + final AuditConfiguration configuration = AuditConfiguration.register( context, metadataCollector); + return Collections.unmodifiableList( context.getBindResults() ); + } + + + private class AuditConfigurationContextImpl implements AuditConfiguration.AuditConfigurationContext { + + private final InFlightMetadataCollector metadataCollector; + private final AdditionalJaxbRootProducerContext additionalJaxbRootProducerContext; + private final AnnotationProxyBuilder annotationProxyBuilder = new AnnotationProxyBuilder(); + private final MappingXmlBinder jaxbProcessor; + private final List bindResults = new ArrayList(); + private final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH ); + private final GlobalConfiguration globalCfg; + private final AuditEntitiesConfiguration auditEntCfg; + private final RevisionInfoConfigurationResult revInfoCfgResult; + + AuditConfigurationContextImpl( + final InFlightMetadataCollector metadataCollector, + final AdditionalJaxbRootProducerContext additionalJaxbRootProducerContext) { + this.metadataCollector = metadataCollector; + this.additionalJaxbRootProducerContext = additionalJaxbRootProducerContext; + this.globalCfg = new GlobalConfiguration( additionalJaxbRootProducerContext.getServiceRegistry() ); + final RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration( globalCfg ); + this.revInfoCfgResult = revInfoCfg.configure( metadataCollector, additionalJaxbRootProducerContext ); + this.auditEntCfg = new AuditEntitiesConfiguration( additionalJaxbRootProducerContext.getServiceRegistry(), revInfoCfgResult.getRevisionInfoEntityName() ); + jaxbProcessor = new MappingXmlBinder( + additionalJaxbRootProducerContext.getServiceRegistry() + ); + } + + @Override + public Metadata getMetadata() { + return metadataCollector; + } + + @Override + public EntityBinding getEntityBinding(String entityName) { + return metadataCollector.getEntityBinding( entityName ); + } + + @Override + public EntityBinding getEntityBinding(final ClassInfo clazz) { + // TODO: Is there a better way? +// final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( clazz, JPADotNames.ENTITY ); +// String entityName = JandexHelper.getValue( jpaEntityAnnotation, "name", String.class ); +// if ( entityName == null ) { +// entityName = clazz.name().toString(); +// } + return getEntityBinding( clazz.name().toString() ); + } + + @Override + public IndexView getJandexIndex() { + return additionalJaxbRootProducerContext.getJandexIndex(); + } + + @Override + public ClassInfo getClassInfo(AttributeContainer attributeContainer) { + return getClassInfo( + attributeContainer.getDescriptor().getName().toString() + ); + } + + @Override + public ClassInfo getClassInfo(String className) { + return getClassInfo( DotName.createSimple( className ) ); + } + + @Override + public ClassInfo getClassInfo(DotName classDotName) { + return getJandexIndex().getClassByName( classDotName ); + } + + @Override + public ClassLoaderService getClassLoaderService() { + return additionalJaxbRootProducerContext.getServiceRegistry().getService( ClassLoaderService.class ); + } + + @Override + public T getAnnotationProxy(AnnotationInstance annotationInstance, Class annotationClass) { + return annotationProxyBuilder.getAnnotationProxy( + annotationInstance, annotationClass, getClassLoaderService() + ); + } + + @Override + public Map> locateAttributeAnnotations(final Attribute attribute) { + final ClassInfo classInfo = getClassInfo( attribute.getAttributeContainer() ); + return JandexHelper.getMemberAnnotations( + classInfo, + attribute.getName(), + additionalJaxbRootProducerContext.getServiceRegistry() + ); + } + + @Override + public GlobalConfiguration getGlobalConfiguration() { + return globalCfg; + } + + @Override + public AuditEntitiesConfiguration getAuditEntitiesConfiguration() { + return auditEntCfg; + } + + @Override + public RevisionInfoConfigurationResult getRevisionInfoConfigurationResult() { + return revInfoCfgResult; + } + + @Override + public void addDocument(org.w3c.dom.Document document) { + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Source xmlSource = new DOMSource( document ); + Result outputTarget = new StreamResult( outputStream ); + try { + TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget); + } + catch ( TransformerConfigurationException ex ){ + throw new MappingException( ex ); + } + catch ( TransformerException ex ) { + throw new MappingException( ex ); + } + InputStream is = new ByteArrayInputStream(outputStream.toByteArray()); + bindResults.add( jaxbProcessor.bind( is, origin ) ); + + } + + private List getBindResults() { + return bindResults; + } + } +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/ToOneIdMapper.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/ToOneIdMapper.java index d99b31f26efc..2f5b85c24fd5 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/ToOneIdMapper.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/ToOneIdMapper.java @@ -107,7 +107,7 @@ public void nullSafeMapToEntityFromMap(AuditConfiguration verCfg, Object obj, Ma boolean ignoreNotFound = false; if ( !referencedEntity.isAudited() ) { final String referencingEntityName = verCfg.getEntCfg().getEntityNameForVersionsEntityName( (String) data.get( "$type$" ) ); - ignoreNotFound = verCfg.getEntCfg().get( referencingEntityName ).getRelationDescription( getPropertyData().getName() ).isIgnoreNotFound(); + ignoreNotFound = verCfg.getEntCfg().getRelationDescription( referencingEntityName, getPropertyData().getName() ).isIgnoreNotFound(); } if ( ignoreNotFound ) { // Eagerly loading referenced entity to silence potential (in case of proxy) diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/component/MiddleEmbeddableComponentMapper.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/component/MiddleEmbeddableComponentMapper.java index 8a3631582966..402a42d91748 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/component/MiddleEmbeddableComponentMapper.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/relation/component/MiddleEmbeddableComponentMapper.java @@ -118,7 +118,12 @@ else if ( nestedMapper instanceof ToOneIdMapper ) { ); } else { - parameters.addWhere( prefix1 + '.' + propertyName, false, "=", prefix2 + '.' + propertyName, false ); + // (p1.prop = p2.prop or (p1.prop is null and p2.prop is null)) + Parameters sub1 = parameters.addSubParameters( "or" ); + sub1.addWhere( prefix1 + '.' + propertyName, false, "=", prefix2 + '.' + propertyName, false ); + Parameters sub2 = sub1.addSubParameters( "and" ); + sub2.addNullRestriction( prefix1 + '.' + propertyName, false ); + sub2.addNullRestriction( prefix2 + '.' + propertyName, false ); } } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/synchronization/SessionCacheCleaner.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/synchronization/SessionCacheCleaner.java index ed465a37070c..15fef67e6d55 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/synchronization/SessionCacheCleaner.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/synchronization/SessionCacheCleaner.java @@ -23,6 +23,7 @@ */ package org.hibernate.envers.internal.synchronization; +import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.action.spi.AfterTransactionCompletionProcess; import org.hibernate.engine.spi.SessionImplementor; @@ -45,9 +46,13 @@ public class SessionCacheCleaner { public void scheduleAuditDataRemoval(final Session session, final Object data) { ((EventSource) session).getActionQueue().registerProcess( new AfterTransactionCompletionProcess() { - public void doAfterTransactionCompletion(boolean success, SessionImplementor session) { - if ( !session.isClosed() ) { - ((Session) session).evict( data ); + public void doAfterTransactionCompletion(boolean success, SessionImplementor sessionImplementor) { + if ( !sessionImplementor.isClosed() ) { + try { + ( (Session) sessionImplementor ).evict( data ); + } + catch ( HibernateException ignore ) { + } } } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/MappingTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/MappingTools.java index 52446e8da685..4a98202dfefa 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/MappingTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/MappingTools.java @@ -23,11 +23,15 @@ */ package org.hibernate.envers.internal.tools; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.ManyToOne; -import org.hibernate.mapping.OneToMany; -import org.hibernate.mapping.ToOne; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.spi.PluralAttributeElementNature; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding; +import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.type.EntityType; /** * @author Adam Warski (adam at warski dot org) @@ -51,30 +55,43 @@ public static String createToOneRelationPrefix(String referencePropertyName) { return referencePropertyName + "_"; } - public static String getReferencedEntityName(Value value) { - if ( value instanceof ToOne ) { - return ((ToOne) value).getReferencedEntityName(); + public static String getReferencedEntityName(AttributeBinding attributeBinding) { + if ( attributeBinding.getAttribute().isSingular() ) { + final SingularAttributeBinding singularAttributeBinding = (SingularAssociationAttributeBinding) attributeBinding; + if ( singularAttributeBinding.isAssociation() ) { + return SingularAssociationAttributeBinding.class.cast( singularAttributeBinding ).getReferencedEntityName(); + } } - else if ( value instanceof OneToMany ) { - return ((OneToMany) value).getReferencedEntityName(); + else { + final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + if ( pluralAttributeBinding.getPluralAttributeElementBinding().getNature().isAssociation() ) { + final PluralAttributeAssociationElementBinding associationPluralAttributeElementBinding = + (PluralAttributeAssociationElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding(); + final EntityType entityType = + (EntityType) associationPluralAttributeElementBinding + .getHibernateTypeDescriptor() + .getResolvedTypeMapping(); + return entityType.getAssociatedEntityName(); + } } - else if ( value instanceof Collection ) { - return getReferencedEntityName( ((Collection) value).getElement() ); - } - return null; } /** - * @param value Persistent property. + * @param attributeBinding Persistent property. * @return {@code false} if lack of associated entity shall raise an exception, {@code true} otherwise. */ - public static boolean ignoreNotFound(Value value) { - if ( value instanceof ManyToOne ) { - return ( (ManyToOne) value ).isIgnoreNotFound(); + public static boolean ignoreNotFound(AttributeBinding attributeBinding) { + if ( ManyToOneAttributeBinding.class.isInstance( attributeBinding )) { + return ( (ManyToOneAttributeBinding) attributeBinding ).isIgnoreNotFound(); } - else if ( value instanceof OneToMany ) { - return ( (OneToMany) value ).isIgnoreNotFound(); + else if ( attributeBinding instanceof PluralAttributeBinding ) { + final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding; + final PluralAttributeElementBinding elementBinding = pluralAttributeBinding.getPluralAttributeElementBinding(); + if ( elementBinding.getNature() == PluralAttributeElementNature.ONE_TO_MANY ) { + // TODO: FIX THIS!!! + //return !( (PluralAttributeElementBindingOneToMany) elementBinding ).isNotFoundAnException(); + } } return false; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/ReflectionTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/ReflectionTools.java index 64e0b4dceecf..4c0e1567ab85 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/ReflectionTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/ReflectionTools.java @@ -126,7 +126,7 @@ public static XProperty getProperty(XClass clazz, String propertyName, String ac * * @param name Fully qualified class name. * @param classLoaderService Class loading service. Passing {@code null} reference - * in case of {@link AuditConfiguration#getFor(Configuration)} usage. + * in case of {@link AuditConfiguration#register(Configuration)} usage. * * @return The cass reference. * diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/Tools.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/Tools.java index 0fafa83c1de0..830d6d4b9663 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/Tools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/Tools.java @@ -32,6 +32,13 @@ import java.util.Map; import java.util.Set; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.MethodInfo; + +import org.hibernate.AssertionFailure; import org.hibernate.envers.tools.Pair; /** @@ -100,4 +107,21 @@ public static List> listToIndexElementPairList(List list return ret; } + + public static boolean isFieldOrPropertyOfClass(AnnotationTarget target, ClassInfo clazz, IndexView jandexIndex) { + final ClassInfo enclosingClass; + if ( target instanceof FieldInfo ) { + final FieldInfo field = (FieldInfo) target; + enclosingClass = field.declaringClass(); + } + else if ( target instanceof MethodInfo ) { + final MethodInfo method = (MethodInfo) target; + enclosingClass = method.declaringClass(); + } + else { + throw new AssertionFailure( "Unexpected annotation target " + target.toString() ); + } + return enclosingClass.equals( clazz ) || jandexIndex.getAllKnownSubclasses( clazz.name() ).contains( enclosingClass ); + } + } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java b/hibernate-envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java index 3b480686d36d..25583400041a 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java @@ -10,8 +10,12 @@ import java.util.Map; import java.util.Set; +import org.jboss.logging.Logger; + import org.hibernate.LockOptions; import org.hibernate.Session; +import org.hibernate.action.spi.AfterTransactionCompletionProcess; +import org.hibernate.action.spi.BeforeTransactionCompletionProcess; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; @@ -39,8 +43,6 @@ import org.hibernate.type.ComponentType; import org.hibernate.type.Type; -import org.jboss.logging.Logger; - import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.MIDDLE_ENTITY_ALIAS; import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.REVISION_PARAMETER; @@ -73,7 +75,7 @@ public class ValidityAuditStrategy implements AuditStrategy { /** * getter for the revision entity field annotated with @RevisionTimestamp */ - private Getter revisionTimestampGetter; + private Getter revisionTimestampGetter = null; private final SessionCacheCleaner sessionCacheCleaner; @@ -83,20 +85,17 @@ public ValidityAuditStrategy() { public void perform( final Session session, - String entityName, + final String entityName, final AuditConfiguration auditCfg, final Serializable id, - Object data, + final Object data, final Object revision) { final AuditEntitiesConfiguration audEntitiesCfg = auditCfg.getAuditEntCfg(); final String auditedEntityName = audEntitiesCfg.getAuditEntityName( entityName ); final String revisionInfoEntityName = auditCfg.getAuditEntCfg().getRevisionInfoEntityName(); - final SessionImplementor sessionImplementor = (SessionImplementor) session; - final Dialect dialect = sessionImplementor.getFactory().getDialect(); // Save the audit data session.save( auditedEntityName, data ); - sessionCacheCleaner.scheduleAuditDataRemoval( session, data ); // Update the end date of the previous row. // @@ -107,173 +106,134 @@ public void perform( // null end date exists for each identifier. final boolean reuseEntityIdentifier = auditCfg.getGlobalCfg().isAllowIdentifierReuse(); if ( reuseEntityIdentifier || getRevisionType( auditCfg, data ) != RevisionType.ADD ) { - final Queryable productionEntityQueryable = getQueryable( entityName, sessionImplementor ); - final Queryable rootProductionEntityQueryable = getQueryable( - productionEntityQueryable.getRootEntityName(), - sessionImplementor - ); - final Queryable auditedEntityQueryable = getQueryable( auditedEntityName, sessionImplementor ); - final Queryable rootAuditedEntityQueryable = getQueryable( - auditedEntityQueryable.getRootEntityName(), - sessionImplementor - ); - final Queryable revisionInfoEntityQueryable = getQueryable( revisionInfoEntityName, sessionImplementor ); - - final String updateTableName; - if ( UnionSubclassEntityPersister.class.isInstance( rootProductionEntityQueryable ) ) { - // this is the condition causing all the problems in terms of the generated SQL UPDATE - // the problem being that we currently try to update the in-line view made up of the union query - // - // this is extremely hacky means to get the root table name for the union subclass style entities. - // hacky because it relies on internal behavior of UnionSubclassEntityPersister - // !!!!!! NOTICE - using subclass persister, not root !!!!!! - updateTableName = auditedEntityQueryable.getSubclassTableName( 0 ); - } - else { - updateTableName = rootAuditedEntityQueryable.getTableName(); - } - - - // first we need to flush the session in order to have the new audit data inserted - // todo: expose org.hibernate.internal.SessionImpl.autoFlushIfRequired via SessionImplementor - // for now, we duplicate some of that logic here - autoFlushIfRequired( sessionImplementor, rootAuditedEntityQueryable, revisionInfoEntityQueryable ); - - final Type revisionInfoIdType = sessionImplementor.getFactory() - .getEntityPersister( revisionInfoEntityName ) - .getIdentifierType(); - final String revEndColumnName = rootAuditedEntityQueryable.toColumns( - auditCfg.getAuditEntCfg() - .getRevisionEndFieldName() - )[0]; - - final boolean isRevisionEndTimestampEnabled = auditCfg.getAuditEntCfg().isRevisionEndTimestampEnabled(); - - // update audit_ent set REVEND = ? [, REVEND_TSTMP = ?] where (prod_ent_id) = ? and REV <> ? and REVEND is null - final Update update = new Update( dialect ).setTableName( updateTableName ); - // set REVEND = ? - update.addColumn( revEndColumnName ); - // set [, REVEND_TSTMP = ?] - if ( isRevisionEndTimestampEnabled ) { - update.addColumn( - rootAuditedEntityQueryable.toColumns( - auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName() - )[0] - ); - } - - // where (prod_ent_id) = ? - update.addPrimaryKeyColumns( rootProductionEntityQueryable.getIdentifierColumnNames() ); - // where REV <> ? - update.addWhereColumn( - rootAuditedEntityQueryable.toColumns( - auditCfg.getAuditEntCfg().getRevisionNumberPath() - )[0], - "<> ?" - ); - // where REVEND is null - update.addWhereColumn( revEndColumnName, " is null" ); - - // Now lets execute the sql... - final String updateSql = update.toStatementString(); - - int rowCount = session.doReturningWork( - new ReturningWork() { - @Override - public Integer execute(Connection connection) throws SQLException { - PreparedStatement preparedStatement = sessionImplementor.getTransactionCoordinator() - .getJdbcCoordinator() - .getStatementPreparer() - .prepareStatement( updateSql ); - - try { - int index = 1; - - // set REVEND = ? - final Number revisionNumber = auditCfg.getRevisionInfoNumberReader().getRevisionNumber( - revision - ); - revisionInfoIdType.nullSafeSet( - preparedStatement, - revisionNumber, - index, - sessionImplementor - ); - index += revisionInfoIdType.getColumnSpan( sessionImplementor.getFactory() ); - - // set [, REVEND_TSTMP = ?] - if ( isRevisionEndTimestampEnabled ) { - final Object revEndTimestampObj = revisionTimestampGetter.get( revision ); - final Date revisionEndTimestamp = convertRevEndTimestampToDate( revEndTimestampObj ); - final Type revEndTsType = rootAuditedEntityQueryable.getPropertyType( - auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName() - ); - revEndTsType.nullSafeSet( - preparedStatement, - revisionEndTimestamp, - index, - sessionImplementor - ); - index += revEndTsType.getColumnSpan( sessionImplementor.getFactory() ); - } + // Register transaction completion process to guarantee execution of UPDATE statement after INSERT. + ( (EventSource) session ).getActionQueue().registerProcess( new BeforeTransactionCompletionProcess() { + @Override + public void doBeforeTransactionCompletion(final SessionImplementor sessionImplementor) { + final Queryable productionEntityQueryable = getQueryable( entityName, sessionImplementor ); + final Queryable rootProductionEntityQueryable = getQueryable( + productionEntityQueryable.getRootEntityName(), sessionImplementor + ); + final Queryable auditedEntityQueryable = getQueryable( auditedEntityName, sessionImplementor ); + final Queryable rootAuditedEntityQueryable = getQueryable( + auditedEntityQueryable.getRootEntityName(), sessionImplementor + ); + + final String updateTableName; + if ( UnionSubclassEntityPersister.class.isInstance( rootProductionEntityQueryable ) ) { + // this is the condition causing all the problems in terms of the generated SQL UPDATE + // the problem being that we currently try to update the in-line view made up of the union query + // + // this is extremely hacky means to get the root table name for the union subclass style entities. + // hacky because it relies on internal behavior of UnionSubclassEntityPersister + // !!!!!! NOTICE - using subclass persister, not root !!!!!! + updateTableName = auditedEntityQueryable.getSubclassTableName( 0 ); + } + else { + updateTableName = rootAuditedEntityQueryable.getTableName(); + } - // where (prod_ent_id) = ? - final Type idType = rootProductionEntityQueryable.getIdentifierType(); - idType.nullSafeSet( preparedStatement, id, index, sessionImplementor ); - index += idType.getColumnSpan( sessionImplementor.getFactory() ); + final Type revisionInfoIdType = sessionImplementor.getFactory().getEntityPersister( revisionInfoEntityName ).getIdentifierType(); + final String revEndColumnName = rootAuditedEntityQueryable.toColumns( auditCfg.getAuditEntCfg().getRevisionEndFieldName() )[0]; - // where REV <> ? - final Type revType = rootAuditedEntityQueryable.getPropertyType( - auditCfg.getAuditEntCfg().getRevisionNumberPath() - ); - revType.nullSafeSet( preparedStatement, revisionNumber, index, sessionImplementor ); + final boolean isRevisionEndTimestampEnabled = auditCfg.getAuditEntCfg().isRevisionEndTimestampEnabled(); - // where REVEND is null - // nothing to bind.... + // update audit_ent set REVEND = ? [, REVEND_TSTMP = ?] where (prod_ent_id) = ? and REV <> ? and REVEND is null + final Update update = new Update( sessionImplementor.getFactory().getDialect() ).setTableName( updateTableName ); + // set REVEND = ? + update.addColumn( revEndColumnName ); + // set [, REVEND_TSTMP = ?] + if ( isRevisionEndTimestampEnabled ) { + update.addColumn( + rootAuditedEntityQueryable.toColumns( auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName() )[0] + ); + } - return sessionImplementor.getTransactionCoordinator() - .getJdbcCoordinator() - .getResultSetReturn() - .executeUpdate( preparedStatement ); - } - finally { - sessionImplementor.getTransactionCoordinator().getJdbcCoordinator().release( - preparedStatement - ); + // where (prod_ent_id) = ? + update.addPrimaryKeyColumns( rootProductionEntityQueryable.getIdentifierColumnNames() ); + // where REV <> ? + update.addWhereColumn( + rootAuditedEntityQueryable.toColumns( auditCfg.getAuditEntCfg().getRevisionNumberPath() )[0], "<> ?" + ); + // where REVEND is null + update.addWhereColumn( revEndColumnName, " is null" ); + + // Now lets execute the sql... + final String updateSql = update.toStatementString(); + + int rowCount = ( (Session) sessionImplementor ).doReturningWork( + new ReturningWork() { + @Override + public Integer execute(Connection connection) throws SQLException { + PreparedStatement preparedStatement = sessionImplementor.getTransactionCoordinator() + .getJdbcCoordinator().getStatementPreparer().prepareStatement( updateSql ); + + try { + int index = 1; + + // set REVEND = ? + final Number revisionNumber = auditCfg.getRevisionInfoNumberReader().getRevisionNumber( + revision + ); + revisionInfoIdType.nullSafeSet( + preparedStatement, revisionNumber, index, sessionImplementor + ); + index += revisionInfoIdType.getColumnSpan( sessionImplementor.getFactory() ); + + // set [, REVEND_TSTMP = ?] + if ( isRevisionEndTimestampEnabled ) { + final Object revEndTimestampObj = revisionTimestampGetter.get( revision ); + final Date revisionEndTimestamp = convertRevEndTimestampToDate( revEndTimestampObj ); + final Type revEndTsType = rootAuditedEntityQueryable.getPropertyType( + auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName() + ); + revEndTsType.nullSafeSet( + preparedStatement, revisionEndTimestamp, index, sessionImplementor + ); + index += revEndTsType.getColumnSpan( sessionImplementor.getFactory() ); + } + + // where (prod_ent_id) = ? + final Type idType = rootProductionEntityQueryable.getIdentifierType(); + idType.nullSafeSet( preparedStatement, id, index, sessionImplementor ); + index += idType.getColumnSpan( sessionImplementor.getFactory() ); + + // where REV <> ? + final Type revType = rootAuditedEntityQueryable.getPropertyType( + auditCfg.getAuditEntCfg().getRevisionNumberPath() + ); + revType.nullSafeSet( preparedStatement, revisionNumber, index, sessionImplementor ); + + // where REVEND is null + // nothing to bind.... + + return sessionImplementor.getTransactionCoordinator() + .getJdbcCoordinator().getResultSetReturn().executeUpdate( preparedStatement ); + } + finally { + sessionImplementor.getTransactionCoordinator().getJdbcCoordinator().release( + preparedStatement + ); + } + } } - } - } - ); + ); - if ( rowCount != 1 && ( !reuseEntityIdentifier || ( getRevisionType( auditCfg, data ) != RevisionType.ADD ) ) ) { - throw new RuntimeException( - "Cannot update previous revision for entity " + auditedEntityName + " and id " + id - ); - } + if ( rowCount != 1 && ( !reuseEntityIdentifier || ( getRevisionType( auditCfg, data ) != RevisionType.ADD ) ) ) { + throw new RuntimeException( + "Cannot update previous revision for entity " + auditedEntityName + " and id " + id + ); + } + } + }); } + sessionCacheCleaner.scheduleAuditDataRemoval( session, data ); } private Queryable getQueryable(String entityName, SessionImplementor sessionImplementor) { return (Queryable) sessionImplementor.getFactory().getEntityPersister( entityName ); } - private void autoFlushIfRequired( - SessionImplementor sessionImplementor, - Queryable auditedEntityQueryable, - Queryable revisionInfoEntityQueryable) { - final Set querySpaces = new HashSet(); - querySpaces.add( auditedEntityQueryable.getTableName() ); - querySpaces.add( revisionInfoEntityQueryable.getTableName() ); - final AutoFlushEvent event = new AutoFlushEvent( querySpaces, (EventSource) sessionImplementor ); - final Iterable listeners = sessionImplementor.getFactory().getServiceRegistry() - .getService( EventListenerRegistry.class ) - .getEventListenerGroup( EventType.AUTO_FLUSH ) - .listeners(); - for ( AutoFlushEventListener listener : listeners ) { - listener.onAutoFlush( event ); - } - } - @SuppressWarnings({"unchecked"}) public void performCollectionChange( Session session, String entityName, String propertyName, AuditConfiguration auditCfg, @@ -321,12 +281,7 @@ public void performCollectionChange( // ADD, we may need to update the last revision. if ( l.size() > 0 ) { updateLastRevision( - session, - auditCfg, - l, - originalId, - persistentCollectionChangeData.getEntityName(), - revision + session, auditCfg, l, originalId, persistentCollectionChangeData.getEntityName(), revision ); } @@ -366,10 +321,7 @@ private void addRevisionRestriction( Parameters subParm = rootParameters.addSubParameters( "or" ); rootParameters.addWhereWithNamedParam( revisionProperty, addAlias, inclusive ? "<=" : "<", REVISION_PARAMETER ); subParm.addWhereWithNamedParam( - revisionEndProperty + ".id", - addAlias, - inclusive ? ">" : ">=", - REVISION_PARAMETER + revisionEndProperty + ".id", addAlias, inclusive ? ">" : ">=", REVISION_PARAMETER ); subParm.addWhere( revisionEndProperty, addAlias, "is", "null", false ); } @@ -416,5 +368,4 @@ private Date convertRevEndTimestampToDate(Object revEndTimestampObj) { } return new Date( (Long) revEndTimestampObj ); } -} - +} \ No newline at end of file diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/tools/hbm2ddl/EnversSchemaGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/tools/hbm2ddl/EnversSchemaGenerator.java index 62d8d2326915..d6664ae1ee81 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/tools/hbm2ddl/EnversSchemaGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/tools/hbm2ddl/EnversSchemaGenerator.java @@ -24,11 +24,27 @@ package org.hibernate.envers.tools.hbm2ddl; import java.sql.Connection; +import java.util.List; +import java.util.Map; import java.util.Properties; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; +import org.w3c.dom.Document; + import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.Configuration; +import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration; +import org.hibernate.envers.configuration.internal.GlobalConfiguration; +import org.hibernate.envers.configuration.internal.RevisionInfoConfigurationResult; import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.hbm2ddl.SchemaExport; @@ -38,33 +54,11 @@ public class EnversSchemaGenerator { private final SchemaExport export; - public EnversSchemaGenerator(ServiceRegistry serviceRegistry, Configuration configuration) { - configuration = configureAuditing( configuration ); - export = new SchemaExport( serviceRegistry, configuration ); - } - - public EnversSchemaGenerator(Configuration configuration) { - configuration = configureAuditing( configuration ); - export = new SchemaExport( configuration ); - } - - public EnversSchemaGenerator(Configuration configuration, Properties properties) throws HibernateException { - configuration = configureAuditing( configuration ); - export = new SchemaExport( configuration, properties ); - } - - public EnversSchemaGenerator(Configuration configuration, Connection connection) throws HibernateException { - configuration = configureAuditing( configuration ); - export = new SchemaExport( configuration, connection ); + public EnversSchemaGenerator(MetadataImplementor metadata) { + export = new SchemaExport( metadata ); } public SchemaExport export() { return export; } - - private Configuration configureAuditing(Configuration configuration) { - configuration.buildMappings(); - AuditConfiguration.getFor( configuration ); - return configuration; - } } diff --git a/hibernate-envers/src/main/resources/META-INF/services/org.hibernate.metamodel.spi.AdditionalJaxbRootProducer b/hibernate-envers/src/main/resources/META-INF/services/org.hibernate.metamodel.spi.AdditionalJaxbRootProducer new file mode 100644 index 000000000000..f2d2298f0149 --- /dev/null +++ b/hibernate-envers/src/main/resources/META-INF/services/org.hibernate.metamodel.spi.AdditionalJaxbRootProducer @@ -0,0 +1 @@ +org.hibernate.envers.event.spi.EnversJaxbRootProducer \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/AbstractOneSessionTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/AbstractOneSessionTest.java index f8359434e30b..0509faff9b86 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/AbstractOneSessionTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/AbstractOneSessionTest.java @@ -69,7 +69,9 @@ private SessionFactory getSessionFactory() { @AfterClassOnce public void closeSessionFactory() { try { - sessionFactory.close(); + if ( sessionFactory != null ) { + sessionFactory.close(); + } } finally { if ( serviceRegistry != null ) { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/BaseEnversJPAFunctionalTestCase.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/BaseEnversJPAFunctionalTestCase.java index 0bb267cbc6dc..f2c31bc98b7c 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/BaseEnversJPAFunctionalTestCase.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/BaseEnversJPAFunctionalTestCase.java @@ -52,6 +52,7 @@ import org.junit.After; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.testing.AfterClassOnce; import org.hibernate.testing.BeforeClassOnce; import org.hibernate.testing.jta.TestingJtaPlatformImpl; @@ -85,8 +86,8 @@ protected StandardServiceRegistryImpl serviceRegistry() { return serviceRegistry; } - protected Configuration getCfg() { - return entityManagerFactoryBuilder.getHibernateConfiguration(); + protected MetadataImplementor getMetadata() { + return entityManagerFactoryBuilder.getMetadata(); } @BeforeClassOnce diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity1.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity1.java index 462762552fa4..393bae9d1a50 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity1.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity1.java @@ -2,6 +2,7 @@ import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -9,7 +10,6 @@ import javax.persistence.ManyToOne; import javax.persistence.Version; -import org.hibernate.annotations.ForeignKey; import org.hibernate.envers.Audited; import org.hibernate.envers.NotAudited; @@ -29,8 +29,7 @@ public class MultipleCollectionRefEntity1 { private String text; @ManyToOne - @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false) - @ForeignKey(name = "FK_RE1_MCE") + @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_RE1_MCE") ) @NotAudited private MultipleCollectionEntity multipleCollectionEntity; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity2.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity2.java index a9c7dc283eef..0768146898c1 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity2.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/MultipleCollectionRefEntity2.java @@ -2,6 +2,7 @@ import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -9,7 +10,6 @@ import javax.persistence.ManyToOne; import javax.persistence.Version; -import org.hibernate.annotations.ForeignKey; import org.hibernate.envers.Audited; import org.hibernate.envers.NotAudited; @@ -29,8 +29,7 @@ public class MultipleCollectionRefEntity2 { private String text; @ManyToOne - @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false) - @ForeignKey(name = "FK_RE2_MCE") + @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_RE2_MCE") ) @NotAudited private MultipleCollectionEntity multipleCollectionEntity; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/StringListEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/StringListEntity.java index 7fb7669c26f2..c58d5562ef36 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/StringListEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/collection/StringListEntity.java @@ -27,10 +27,10 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.OrderColumn; import java.util.ArrayList; import java.util.List; -import org.hibernate.annotations.IndexColumn; import org.hibernate.envers.Audited; /** @@ -44,7 +44,7 @@ public class StringListEntity { @Audited @ElementCollection - @IndexColumn(name = "list_index") + @OrderColumn(name = "list_index") private List strings; public StringListEntity() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/ComponentSetTestEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/ComponentSetTestEntity.java index a9f0e7d634b6..3a174102094d 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/ComponentSetTestEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/ComponentSetTestEntity.java @@ -23,10 +23,12 @@ */ package org.hibernate.envers.test.entities.components; -import javax.persistence.Embedded; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.JoinColumn; import java.util.HashSet; import java.util.Set; @@ -42,8 +44,8 @@ public class ComponentSetTestEntity { @GeneratedValue private Integer id; - @Embedded - @Audited + @ElementCollection + @CollectionTable(name = "CompTestEntityComps", joinColumns = @JoinColumn(name = "entity_id")) private Set comps = new HashSet(); public ComponentSetTestEntity() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent1.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent1.java index 753f04dfce4c..a358be250b90 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent1.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent1.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.entities.components; +import javax.persistence.Embeddable; import javax.persistence.Embedded; /** * @author Erik-Berndt Scheper */ +@Embeddable public class DefaultValueComponent1 { private String str1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent2.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent2.java index d84b5320439f..114c0b706fdd 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent2.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/components/DefaultValueComponent2.java @@ -1,9 +1,12 @@ package org.hibernate.envers.test.entities.components; +import javax.persistence.Embeddable; + /** * @author Erik-Berndt Scheper */ +@Embeddable public class DefaultValueComponent2 { private String str1 = "defaultValue"; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytomany/SortedSetEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytomany/SortedSetEntity.java index f88dcf09fa94..02f6fd16c406 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytomany/SortedSetEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytomany/SortedSetEntity.java @@ -33,8 +33,7 @@ import java.util.TreeMap; import java.util.TreeSet; -import org.hibernate.annotations.Sort; -import org.hibernate.annotations.SortType; +import org.hibernate.annotations.SortComparator; import org.hibernate.envers.Audited; import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.entities.StrTestEntityComparator; @@ -54,12 +53,12 @@ public class SortedSetEntity { @Audited @ManyToMany - @Sort(type = SortType.COMPARATOR, comparator = StrTestEntityComparator.class) + @SortComparator(value = StrTestEntityComparator.class) private SortedSet sortedSet = new TreeSet( StrTestEntityComparator.INSTANCE ); @Audited @ElementCollection @MapKeyJoinColumn - @Sort(type = SortType.COMPARATOR, comparator = StrTestEntityComparator.class) + @SortComparator(value = StrTestEntityComparator.class) private SortedMap sortedMap = new TreeMap( StrTestEntityComparator.INSTANCE ); public SortedSetEntity() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ExtManyToOneNotAuditedNullEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ExtManyToOneNotAuditedNullEntity.java new file mode 100644 index 000000000000..fc8089215cb3 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ExtManyToOneNotAuditedNullEntity.java @@ -0,0 +1,81 @@ +/* +* Hibernate, Relational Persistence for Idiomatic Java +* +* Copyright (c) 2014, Red Hat Inc. or third-party contributors as +* indicated by the @author tags or express copyright attribution +* statements applied by the authors. All third-party contributions are +* distributed under license by Red Hat Inc. +* +* This copyrighted material is made available to anyone wishing to use, modify, +* copy, or redistribute it subject to the terms and conditions of the GNU +* Lesser General Public License, as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +* for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this distribution; if not, write to: +* Free Software Foundation, Inc. +* 51 Franklin Street, Fifth Floor +* Boston, MA 02110-1301 USA +*/ +package org.hibernate.envers.test.entities.manytoone.unidirectional; + +import javax.persistence.Entity; +import javax.persistence.Table; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.test.entities.UnversionedStrTestEntity; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Table(name = "EM2O_N_AUD_NULL") +public class ExtManyToOneNotAuditedNullEntity extends ManyToOneNotAuditedNullEntity { + @Audited + private String extension = null; + + public ExtManyToOneNotAuditedNullEntity() { + } + + public ExtManyToOneNotAuditedNullEntity(Integer id, String data, UnversionedStrTestEntity reference, String extension) { + super( id, data, reference ); + this.extension = extension; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) return true; + if ( !( o instanceof ExtManyToOneNotAuditedNullEntity ) ) return false; + if ( !super.equals( o ) ) return false; + + ExtManyToOneNotAuditedNullEntity that = (ExtManyToOneNotAuditedNullEntity) o; + + if ( extension != null ? !extension.equals( that.extension ) : that.extension != null ) return false; + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (extension != null ? extension.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "ExtManyToOneNotAuditedNullEntity(" + super.toString() + ", extension = " + extension + ")"; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ManyToOneNotAuditedNullEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ManyToOneNotAuditedNullEntity.java index ffe1b564a9b4..1cd32cbd85f0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ManyToOneNotAuditedNullEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/manytoone/unidirectional/ManyToOneNotAuditedNullEntity.java @@ -27,6 +27,8 @@ import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; import javax.persistence.ManyToOne; import javax.persistence.Table; @@ -42,6 +44,7 @@ @Audited @Entity @Table(name = "M2O_N_AUD_NULL") +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class ManyToOneNotAuditedNullEntity implements Serializable { @Id private Integer id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java index 712838b8241f..d545ab216ff0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java @@ -5,12 +5,12 @@ import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; import javax.persistence.Table; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.hibernate.annotations.IndexColumn; import org.hibernate.envers.AuditMappedBy; import org.hibernate.envers.Audited; @@ -32,7 +32,7 @@ public class IndexedListJoinColumnBidirectionalRefIngEntity { @OneToMany @JoinColumn(name = "indexed_join_column") - @IndexColumn(name = "indexed_index") + @OrderColumn(name = "indexed_index") @AuditMappedBy(mappedBy = "owner", positionMappedBy = "position") private List references; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/inheritance/ParentIndexedListJoinColumnBidirectionalRefIngEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/inheritance/ParentIndexedListJoinColumnBidirectionalRefIngEntity.java index 2f37ff3986fc..ad5efbbb4c8d 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/inheritance/ParentIndexedListJoinColumnBidirectionalRefIngEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/inheritance/ParentIndexedListJoinColumnBidirectionalRefIngEntity.java @@ -7,12 +7,12 @@ import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; import javax.persistence.Table; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.hibernate.annotations.IndexColumn; import org.hibernate.envers.AuditMappedBy; import org.hibernate.envers.Audited; @@ -35,7 +35,7 @@ public abstract class ParentIndexedListJoinColumnBidirectionalRefIngEntity { @OneToMany @JoinColumn(name = "indexed_join_column") - @IndexColumn(name = "indexed_index") + @OrderColumn(name = "indexed_index") @AuditMappedBy(mappedBy = "owner", positionMappedBy = "position") private List references; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java index 810139846168..da44572b4f6f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java @@ -1,12 +1,12 @@ package org.hibernate.envers.test.entities.reventity.trackmodifiedentities; +import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.Table; import java.util.Set; @@ -44,7 +44,7 @@ public class AnnotatedTrackingRevisionEntity { private long customTimestamp; @ElementCollection - @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) + @CollectionTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) @Column(name = "ENTITYNAME") @ModifiedEntityNames private Set entityNames; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/accesstype/MixedAccessTypeEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/accesstype/MixedAccessTypeEntity.java index df867fc11122..ffff521a5ab3 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/accesstype/MixedAccessTypeEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/accesstype/MixedAccessTypeEntity.java @@ -23,12 +23,13 @@ */ package org.hibernate.envers.test.integration.accesstype; +import javax.persistence.Access; +import javax.persistence.AccessType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Transient; -import org.hibernate.annotations.AccessType; import org.hibernate.envers.Audited; /** @@ -40,7 +41,7 @@ public class MixedAccessTypeEntity { @GeneratedValue private Integer id; - @AccessType("property") + @Access(value = AccessType.PROPERTY) private String data; @Transient diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/ColumnScalePrecisionTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/ColumnScalePrecisionTest.java index d176ee1e8d87..9428316bf635 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/ColumnScalePrecisionTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/ColumnScalePrecisionTest.java @@ -5,12 +5,12 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; import org.junit.Assert; import org.junit.Test; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.testing.TestForIssue; /** @@ -18,8 +18,8 @@ */ @TestForIssue(jiraKey = "HHH-7003") public class ColumnScalePrecisionTest extends BaseEnversJPAFunctionalTestCase { - private Table auditTable = null; - private Table originalTable = null; + private TableSpecification auditTable = null; + private TableSpecification originalTable = null; private Long id = null; @Override @@ -39,21 +39,29 @@ public void initData() { em.getTransaction().commit(); id = entity.getId(); - auditTable = getCfg().getClassMapping( "org.hibernate.envers.test.integration.basic.ScalePrecisionEntity_AUD" ) - .getTable(); - originalTable = getCfg().getClassMapping( "org.hibernate.envers.test.integration.basic.ScalePrecisionEntity" ) - .getTable(); + auditTable = getMetadata().getEntityBinding( + "org.hibernate.envers.test.integration.basic.ScalePrecisionEntity_AUD" + ) + .getPrimaryTable(); + originalTable = getMetadata().getEntityBinding( + "org.hibernate.envers.test.integration.basic.ScalePrecisionEntity" + ) + .getPrimaryTable(); } @Test public void testColumnScalePrecision() { - Column testColumn = new Column( "wholeNumber" ); - Column scalePrecisionAuditColumn = auditTable.getColumn( testColumn ); - Column scalePrecisionColumn = originalTable.getColumn( testColumn ); + String columnName = "wholeNumber"; + Column scalePrecisionAuditColumn = auditTable.locateColumn( columnName ); + Column scalePrecisionColumn = originalTable.locateColumn( columnName ); Assert.assertNotNull( scalePrecisionAuditColumn ); - Assert.assertEquals( scalePrecisionColumn.getPrecision(), scalePrecisionAuditColumn.getPrecision() ); - Assert.assertEquals( scalePrecisionColumn.getScale(), scalePrecisionAuditColumn.getScale() ); + Assert.assertNotNull( scalePrecisionAuditColumn.getSize() ); + Assert.assertEquals( + scalePrecisionColumn.getSize().getPrecision(), + scalePrecisionAuditColumn.getSize().getPrecision() + ); + Assert.assertEquals( scalePrecisionColumn.getSize().getScale(), scalePrecisionAuditColumn.getSize().getScale() ); } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/NoneAudited.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/NoneAudited.java index 2acf0545211d..f10ecf64c192 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/NoneAudited.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/basic/NoneAudited.java @@ -28,7 +28,7 @@ import java.util.List; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.junit.Assert; import org.junit.Test; @@ -44,9 +44,12 @@ protected Class[] getAnnotatedClasses() { @Test public void testRevisionInfoTableNotCreated() { - @SuppressWarnings({"unchecked"}) List pcs = iteratorToList( getCfg().getClassMappings() ); + @SuppressWarnings({"unchecked"}) List pcs = iteratorToList( + getMetadata().getEntityBindings() + .iterator() + ); Assert.assertEquals( 1, pcs.size() ); - Assert.assertTrue( pcs.get( 0 ).getClassName().contains( "BasicTestEntity3" ) ); + Assert.assertTrue( pcs.get( 0 ).getEntityName().contains( "BasicTestEntity3" ) ); } private List iteratorToList(Iterator it) { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList1.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList1.java index 2de3e23a730e..e62b575f285e 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList1.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList1.java @@ -53,7 +53,7 @@ public class EmbeddableList1 extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbeddableListEntity1.class}; + return new Class[] {EmbeddableListEntity1.class, Component3.class, Component4.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList2.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList2.java index cd10bcfd0a13..91bd75d0227b 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList2.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableList2.java @@ -62,7 +62,7 @@ public class EmbeddableList2 extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbeddableListEntity2.class, StrTestNoProxyEntity.class}; + return new Class[] {EmbeddableListEntity2.class, StrTestNoProxyEntity.class, ManyToOneEagerComponent.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableMap.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableMap.java index 2fa9be12dd6c..d1b187e3482d 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableMap.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableMap.java @@ -54,7 +54,7 @@ public class EmbeddableMap extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbeddableMapEntity.class}; + return new Class[] {EmbeddableMapEntity.class, Component3.class, Component4.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableSet.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableSet.java index 3bdb433431f7..fbb100587c85 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableSet.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/EmbeddableSet.java @@ -55,7 +55,7 @@ public class EmbeddableSet extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbeddableSetEntity.class}; + return new Class[] {EmbeddableSetEntity.class, Component3.class, Component4.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/ComponentMapKey.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/ComponentMapKey.java index c2ba8a0711db..1c4e116f4e3c 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/ComponentMapKey.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/ComponentMapKey.java @@ -32,12 +32,14 @@ import org.hibernate.envers.test.entities.components.Component2; import org.hibernate.envers.test.entities.components.ComponentTestEntity; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = " Plural attribute index that is an attribute of the referenced entity is not supported yet." ) public class ComponentMapKey extends BaseEnversJPAFunctionalTestCase { private Integer cmke_id; @@ -46,7 +48,7 @@ public class ComponentMapKey extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ComponentMapKeyEntity.class, ComponentTestEntity.class}; + return new Class[] {ComponentMapKeyEntity.class, ComponentTestEntity.class, Component1.class, Component2.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/IdMapKey.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/IdMapKey.java index de6288fb4c40..11003823bc0a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/IdMapKey.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/mapkey/IdMapKey.java @@ -30,12 +30,14 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = " Plural attribute index that is an attribute of the referenced entity is not supported yet." ) public class IdMapKey extends BaseEnversJPAFunctionalTestCase { private Integer imke_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/Components.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/Components.java index 3e54435d33b2..55ac576753ac 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/Components.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/Components.java @@ -45,7 +45,7 @@ public class Components extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ComponentTestEntity.class}; + return new Class[] {ComponentTestEntity.class, Component1.class, Component2.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/DefaultValueComponents.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/DefaultValueComponents.java index b35529ce71b4..d5aa37c5404f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/DefaultValueComponents.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/DefaultValueComponents.java @@ -57,7 +57,7 @@ public class DefaultValueComponents extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {DefaultValueComponentTestEntity.class}; + return new Class[] {DefaultValueComponentTestEntity.class, DefaultValueComponent1.class, DefaultValueComponent2.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/PropertiesGroupTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/PropertiesGroupTest.java index db70b09c9c9b..4d7e11821cd1 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/PropertiesGroupTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/PropertiesGroupTest.java @@ -5,21 +5,22 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.components.UniquePropsEntity; import org.hibernate.envers.test.entities.components.UniquePropsNotAuditedEntity; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; import org.junit.Assert; import org.junit.Test; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-6636") +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class PropertiesGroupTest extends BaseEnversFunctionalTestCase { - private PersistentClass uniquePropsAudit = null; - private PersistentClass uniquePropsNotAuditedAudit = null; + private EntityBinding uniquePropsAudit = null; + private EntityBinding uniquePropsNotAuditedAudit = null; private UniquePropsEntity entityRev1 = null; private UniquePropsNotAuditedEntity entityNotAuditedRev2 = null; @@ -34,10 +35,10 @@ protected String[] getMappings() { @Test @Priority(10) public void initData() { - uniquePropsAudit = configuration().getClassMapping( + uniquePropsAudit = metadata().getEntityBinding( "org.hibernate.envers.test.entities.components.UniquePropsEntity_AUD" ); - uniquePropsNotAuditedAudit = configuration().getClassMapping( + uniquePropsNotAuditedAudit = metadata().getEntityBinding( "org.hibernate.envers.test.entities.components.UniquePropsNotAuditedEntity_AUD" ); @@ -65,11 +66,11 @@ public void initData() { @Test public void testAuditTableColumns() { - Assert.assertNotNull( uniquePropsAudit.getTable().getColumn( new Column( "DATA1" ) ) ); - Assert.assertNotNull( uniquePropsAudit.getTable().getColumn( new Column( "DATA2" ) ) ); + Assert.assertNotNull( uniquePropsAudit.getPrimaryTable().locateColumn( "DATA1" ) ); + Assert.assertNotNull( uniquePropsAudit.getPrimaryTable().locateColumn( "DATA2" ) ); - Assert.assertNotNull( uniquePropsNotAuditedAudit.getTable().getColumn( new Column( "DATA1" ) ) ); - Assert.assertNull( uniquePropsNotAuditedAudit.getTable().getColumn( new Column( "DATA2" ) ) ); + Assert.assertNotNull( uniquePropsNotAuditedAudit.getPrimaryTable().locateColumn( "DATA1" ) ); + Assert.assertNull( uniquePropsNotAuditedAudit.getPrimaryTable().locateColumn( "DATA2" ) ); } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/collections/CollectionOfComponents.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/collections/CollectionOfComponents.java index 9f8317bb4de0..ad5645ef1745 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/collections/CollectionOfComponents.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/collections/CollectionOfComponents.java @@ -25,6 +25,7 @@ import javax.persistence.EntityManager; import java.util.Arrays; +import java.util.Collections; import java.util.Set; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; @@ -32,17 +33,20 @@ import org.hibernate.envers.test.entities.components.Component1; import org.hibernate.envers.test.entities.components.ComponentSetTestEntity; -import org.junit.Ignore; import org.junit.Test; +import org.hibernate.testing.TestForIssue; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + /** - * TODO: enable and implement - * * @author Adam Warski (adam at warski dot org) + * @author Felix Feisst */ -@Ignore public class CollectionOfComponents extends BaseEnversJPAFunctionalTestCase { private Integer id1; + private Integer id2; @Override protected Class[] getAnnotatedClasses() { @@ -58,6 +62,10 @@ public void initData() { ComponentSetTestEntity cte1 = new ComponentSetTestEntity(); + ComponentSetTestEntity cte2 = new ComponentSetTestEntity(); + cte2.getComps().add( new Component1( "string1", null ) ); + + em.persist( cte2 ); em.persist( cte1 ); em.getTransaction().commit(); @@ -73,19 +81,28 @@ public void initData() { em.getTransaction().commit(); id1 = cte1.getId(); + id2 = cte2.getId(); } @Test public void testRevisionsCounts() { - assert Arrays.asList( 1, 2 ).equals( getAuditReader().getRevisions( ComponentSetTestEntity.class, id1 ) ); + assertEquals( Arrays.asList( 1, 2 ), getAuditReader().getRevisions( ComponentSetTestEntity.class, id1 ) ); } @Test public void testHistoryOfId1() { - assert getAuditReader().find( ComponentSetTestEntity.class, id1, 1 ).getComps().size() == 0; + assertEquals( 0, getAuditReader().find( ComponentSetTestEntity.class, id1, 1 ).getComps().size() ); Set comps1 = getAuditReader().find( ComponentSetTestEntity.class, id1, 2 ).getComps(); - assert comps1.size() == 1; - assert comps1.contains( new Component1( "a", "b" ) ); + assertEquals( 1, comps1.size() ); + assertTrue( comps1.contains( new Component1( "a", "b" ) ) ); + } + + @Test + @TestForIssue(jiraKey = "HHH-8968") + public void testCollectionOfEmbeddableWithNullValue() { + final Component1 componentV1 = new Component1( "string1", null ); + final ComponentSetTestEntity entityV1 = getAuditReader().find( ComponentSetTestEntity.class, id2, 1 ); + assertEquals( "Expected a component", Collections.singleton( componentV1 ), entityV1.getComps() ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentTest.java index 91088c942287..af55a5cc703c 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentTest.java @@ -18,6 +18,7 @@ import org.hibernate.envers.test.BaseEnversFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.service.ServiceRegistry; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.TestForIssue; @@ -26,6 +27,7 @@ * @author Lukasz Zuchowski (author at zuchos dot com) */ @TestForIssue(jiraKey = "HHH-8049") +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class AuditedDynamicComponentTest extends BaseEnversFunctionalTestCase { @Override diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentsAdvancedCasesTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentsAdvancedCasesTest.java index 87d568d0338a..4978254e63bb 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentsAdvancedCasesTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/AuditedDynamicComponentsAdvancedCasesTest.java @@ -17,6 +17,7 @@ import org.hibernate.envers.query.AuditEntity; import org.hibernate.envers.test.BaseEnversFunctionalTestCase; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** @@ -24,6 +25,7 @@ * More advanced tests for dynamic component. */ @TestForIssue(jiraKey = "HHH-8049") +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class AuditedDynamicComponentsAdvancedCasesTest extends BaseEnversFunctionalTestCase { public static final String PROP_BOOLEAN = "propBoolean"; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/NotAuditedDynamicComponentTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/NotAuditedDynamicComponentTest.java index 274c6aa2420b..b58dc069547a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/NotAuditedDynamicComponentTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/NotAuditedDynamicComponentTest.java @@ -8,12 +8,14 @@ import org.hibernate.Session; import org.hibernate.envers.test.BaseEnversFunctionalTestCase; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-8049") +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class NotAuditedDynamicComponentTest extends BaseEnversFunctionalTestCase { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/SanityCheckTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/SanityCheckTest.java index 00aa5a9d8278..aa8ce61e5936 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/SanityCheckTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/dynamic/SanityCheckTest.java @@ -12,7 +12,9 @@ import org.hibernate.envers.query.AuditEntity; import org.hibernate.envers.test.BaseEnversFunctionalTestCase; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class SanityCheckTest extends BaseEnversFunctionalTestCase { @Override diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/ManyToOneInComponent.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/ManyToOneInComponent.java index fd7882aceac0..bf7f61e4af86 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/ManyToOneInComponent.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/ManyToOneInComponent.java @@ -44,7 +44,7 @@ public class ManyToOneInComponent extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ManyToOneComponentTestEntity.class, StrTestEntity.class}; + return new Class[] {ManyToOneComponentTestEntity.class, StrTestEntity.class, ManyToOneComponent.class}; } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/NotAuditedManyToOneInComponent.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/NotAuditedManyToOneInComponent.java index 114cdd9c5140..13871b4676c0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/NotAuditedManyToOneInComponent.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/NotAuditedManyToOneInComponent.java @@ -42,7 +42,11 @@ public class NotAuditedManyToOneInComponent extends BaseEnversJPAFunctionalTestC @Override protected Class[] getAnnotatedClasses() { - return new Class[] {NotAuditedManyToOneComponentTestEntity.class, UnversionedStrTestEntity.class}; + return new Class[] { + NotAuditedManyToOneComponentTestEntity.class, + UnversionedStrTestEntity.class, + NotAuditedManyToOneComponent.class + }; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/OneToManyInComponent.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/OneToManyInComponent.java index d2076681e66d..7895c073f135 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/OneToManyInComponent.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/components/relations/OneToManyInComponent.java @@ -31,12 +31,14 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.entities.components.relations.OneToManyComponent; import org.hibernate.envers.test.entities.components.relations.OneToManyComponentTestEntity; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = "Collection role is incorrect when contained in an @Embeddable" ) public class OneToManyInComponent extends BaseEnversJPAFunctionalTestCase { private Integer otmcte_id1; private Integer ste_id1; @@ -44,7 +46,7 @@ public class OneToManyInComponent extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {OneToManyComponentTestEntity.class, StrTestEntity.class}; + return new Class[] {OneToManyComponentTestEntity.class, StrTestEntity.class, OneToManyComponent.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/CalendarEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/CalendarEntity.java new file mode 100644 index 000000000000..900d74c4b02d --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/CalendarEntity.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.envers.test.integration.customtype; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +import java.io.Serializable; +import java.util.Calendar; + +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.hibernate.envers.Audited; +import org.hibernate.type.CalendarDateType; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Audited +@TypeDef(name = "hibernate_calendar_date", typeClass = CalendarDateType.class) +public class CalendarEntity implements Serializable { + @Id + @GeneratedValue + private Long id = null; + + @Type(type = "hibernate_calendar_date") + private Calendar dayOne = Calendar.getInstance(); // org.hibernate.type.CalendarDateType + + private Calendar dayTwo = Calendar.getInstance(); // org.hibernate.envers.test.integration.customtype.UTCCalendarType + + public CalendarEntity() { + } + + public CalendarEntity(Calendar dayOne, Calendar dayTwo) { + this.dayOne = dayOne; + this.dayTwo = dayTwo; + } + + public CalendarEntity(Long id, Calendar dayOne, Calendar dayTwo) { + this.id = id; + this.dayOne = dayOne; + this.dayTwo = dayTwo; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) return true; + if ( !( o instanceof CalendarEntity ) ) return false; + + CalendarEntity that = (CalendarEntity) o; + + if ( dayOne != null ? !dayOne.equals( that.dayOne ) : that.dayOne != null ) return false; + if ( dayTwo != null ? !dayTwo.equals( that.dayTwo ) : that.dayTwo != null ) return false; + if ( id != null ? !id.equals( that.id ) : that.id != null ) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (dayOne != null ? dayOne.hashCode() : 0); + result = 31 * result + (dayTwo != null ? dayTwo.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "CalendarEntity(id = " + id + ", dayOne = " + dayOne + ", dayTwo = " + dayTwo + ")"; + } + + public Calendar getDayOne() { + return dayOne; + } + + public void setDayOne(Calendar dayOne) { + this.dayOne = dayOne; + } + + public Calendar getDayTwo() { + return dayTwo; + } + + public void setDayTwo(Calendar dayTwo) { + this.dayTwo = dayTwo; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/DefaultTypeTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/DefaultTypeTest.java new file mode 100644 index 000000000000..99f642ff3508 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/DefaultTypeTest.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.envers.test.integration.customtype; + +import org.hibernate.Session; +import org.hibernate.envers.test.BaseEnversFunctionalTestCase; +import org.hibernate.envers.test.Priority; + +import org.junit.Assert; +import org.junit.Test; + +import org.hibernate.testing.TestForIssue; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@TestForIssue( jiraKey = "HHH-8602" ) +public class DefaultTypeTest extends BaseEnversFunctionalTestCase { + private Long id = null; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { CalendarEntity.class }; + } + + @Override + protected String[] getAnnotatedPackages() { + return new String[] { "org.hibernate.envers.test.integration.customtype" }; + } + + @Test + @Priority(10) + public void initData() { + Session session = openSession(); + + // Revision 1 + session.getTransaction().begin(); + final CalendarEntity entity = new CalendarEntity(); + entity.getDayOne().set( 2013, java.util.Calendar.DECEMBER, 24, 0, 0, 0 ); + entity.getDayTwo().set( 2013, java.util.Calendar.DECEMBER, 24, 0, 0, 0 ); + session.persist( entity ); + session.getTransaction().commit(); + + id = entity.getId(); + + session.close(); + } + + @Test + public void testDateEqualityWithCurrentObject() { + final CalendarEntity ver1 = getAuditReader().find( CalendarEntity.class, id, 1 ); + final Session session = openSession(); + final CalendarEntity current = (CalendarEntity) session.get( CalendarEntity.class, id ); + session.close(); + + Assert.assertEquals( current.getDayOne(), ver1.getDayOne() ); + Assert.assertEquals( current.getDayTwo(), ver1.getDayTwo() ); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UTCCalendarType.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UTCCalendarType.java new file mode 100644 index 000000000000..84c83af7bd35 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UTCCalendarType.java @@ -0,0 +1,140 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.envers.test.integration.customtype; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Calendar; +import java.util.TimeZone; + +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.type.CalendarType; +import org.hibernate.usertype.UserType; + +/** + * @author Sebastian Götz (s got goetz at inform dot ch) + */ +public class UTCCalendarType implements UserType { + private static final TimeZone timeZone = TimeZone.getTimeZone( "UTC" ); + + @Override + public int[] sqlTypes() { + return new int[] { Types.TIMESTAMP }; + } + + @Override + public Class returnedClass() { + return Calendar.class; + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + if ( x == y ) { + return true; + } + if ( x == null || y == null ) { + return false; + } + return x.equals( y ); + } + + @Override + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + @Override + public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException { + /* + * Delegate the nullSafeGet to the Hibernate CalendarType since we ensured upon insert that the value is in UTC. + * + * ATTENTION: Hibernate CalendarType will read the date value into a Calendar instance generated by + * Calendar.getInstance(). So the resulting calendar will have the system's default time zone but the value + * actually is in UTC since we corrected it upon insertion already. So we just have to ensure, that the time + * zone of the calendar is being set to UTC. Otherwise when it comes to insertion/update again we would subtract + * the offset again which would lead to incorrect values. + */ + Calendar calendar = CalendarType.INSTANCE.nullSafeGet( rs, names[0], session ); + + if (calendar != null) { + calendar.setTimeZone( timeZone ); + } + + return calendar; + } + + @Override + public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { + if ( value instanceof Calendar ) { + value = convertToTimeZone( (Calendar) value, timeZone ); + } + CalendarType.INSTANCE.nullSafeSet( st, value, index, session ); + } + + @Override + public Object deepCopy(Object value) throws HibernateException { + if ( value == null ) { + return null; + } + return ( (Calendar) value ).clone(); + } + + @Override + public boolean isMutable() { + return true; + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + return (Serializable) deepCopy( value ); + } + + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return deepCopy( cached ); + } + + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return deepCopy( original ); + } + + public static Calendar convertToTimeZone(Calendar calendar, TimeZone timeZone) { + if ( calendar != null ) { + final TimeZone currentTimeZone = calendar.getTimeZone(); + if ( !currentTimeZone.equals( timeZone ) ) { + int currentOffset = currentTimeZone.getOffset( calendar.getTimeInMillis() ); + int targetOffset = timeZone.getOffset( calendar.getTimeInMillis() ); + int offset = currentOffset - targetOffset; + calendar.add( Calendar.MILLISECOND, -offset ); + calendar.setTimeZone( timeZone ); + } + } + return calendar; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UnspecifiedEnumTypeTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UnspecifiedEnumTypeTest.java index 97cc813613a3..534d604c7769 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UnspecifiedEnumTypeTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/UnspecifiedEnumTypeTest.java @@ -14,6 +14,7 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; @@ -22,6 +23,7 @@ */ @TestForIssue(jiraKey = "HHH-7780") @RequiresDialect(value = H2Dialect.class) +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class UnspecifiedEnumTypeTest extends BaseEnversFunctionalTestCase { private Long id = null; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/package-info.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/package-info.java new file mode 100644 index 000000000000..b902322b0dec --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/customtype/package-info.java @@ -0,0 +1,30 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +@TypeDef(defaultForType = Calendar.class, name = "calendar_date", typeClass = UTCCalendarType.class) +// HHH-8602: Name collision with org.hibernate.type.CalendarDateType. +package org.hibernate.envers.test.integration.customtype; + +import java.util.Calendar; + +import org.hibernate.annotations.TypeDef; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/auditedEntity/ReadEntityWhitEntityNameTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/auditedEntity/ReadEntityWhitEntityNameTest.java index 7dd5e33c4e67..54ec10ac6ca0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/auditedEntity/ReadEntityWhitEntityNameTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/auditedEntity/ReadEntityWhitEntityNameTest.java @@ -8,12 +8,14 @@ import org.hibernate.MappingException; import org.hibernate.envers.test.AbstractOneSessionTest; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hernán Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest { private long id_pers1; @@ -36,6 +38,7 @@ protected void initMappings() throws MappingException, URISyntaxException { @Test @Priority(10) + //@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public void initData() { initializeSession(); @@ -79,6 +82,7 @@ public void initData() { @Test + @FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public void testRetrieveRevisionsWithEntityName() { List pers1Revs = getAuditReader().getRevisions( Person.class, "Personaje", id_pers1 ); List pers2Revs = getAuditReader().getRevisions( Person.class, "Personaje", id_pers2 ); @@ -90,6 +94,7 @@ public void testRetrieveRevisionsWithEntityName() { } @Test + @FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public void testRetrieveAuditedEntityWithEntityName() { person1_1 = getAuditReader().find( Person.class, "Personaje", id_pers1, 1 ); person1_2 = getAuditReader().find( Person.class, "Personaje", id_pers1, 2 ); @@ -102,6 +107,7 @@ public void testRetrieveAuditedEntityWithEntityName() { } @Test + @FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public void testObtainEntityNameAuditedEntityWithEntityName() { person1_1 = getAuditReader().find( Person.class, "Personaje", id_pers1, 1 ); person1_2 = getAuditReader().find( Person.class, "Personaje", id_pers1, 2 ); @@ -121,6 +127,7 @@ public void testObtainEntityNameAuditedEntityWithEntityName() { } @Test + @FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public void testRetrieveAuditedEntityWithEntityNameWithNewSession() { // force a new session and AR diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java index d18900cfb4be..ca530627aefc 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java @@ -9,12 +9,14 @@ import org.hibernate.MappingException; import org.hibernate.envers.test.AbstractOneSessionTest; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hernán Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class ReadEntityWithAuditedManyToManyTest extends AbstractOneSessionTest { private long id_car1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java index f65fc0b464eb..4d10fa48a34e 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java @@ -9,12 +9,14 @@ import org.hibernate.MappingException; import org.hibernate.envers.test.AbstractOneSessionTest; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hernán Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class ReadEntityWithAuditedCollectionTest extends AbstractOneSessionTest { private long id_car1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java index bdc40336ab23..c5417857cf98 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java @@ -7,12 +7,14 @@ import org.hibernate.MappingException; import org.hibernate.envers.test.AbstractOneSessionTest; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hernán Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class ReadEntityAssociatedAuditedTest extends AbstractOneSessionTest { private long id_car1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/SingleDomainObjectToMultipleTablesTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/SingleDomainObjectToMultipleTablesTest.java index 2f7f8731a236..9004d2470f57 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/SingleDomainObjectToMultipleTablesTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/SingleDomainObjectToMultipleTablesTest.java @@ -11,11 +11,13 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class SingleDomainObjectToMultipleTablesTest extends AbstractOneSessionTest { private long carId = 0; private long ownerId = 0; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java index 3fcb36bb83ba..63952ac912d7 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java @@ -7,12 +7,14 @@ import org.hibernate.MappingException; import org.hibernate.envers.test.AbstractOneSessionTest; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hernán Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class ReadEntityAssociatedNotAuditedTest extends AbstractOneSessionTest { private long id_car1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/flush/CommitFlush.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/flush/CommitFlush.java new file mode 100644 index 000000000000..8ea32cd28c03 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/flush/CommitFlush.java @@ -0,0 +1,106 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.envers.test.integration.flush; + +import javax.persistence.EntityManager; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.FlushMode; +import org.hibernate.envers.RevisionType; +import org.hibernate.envers.query.AuditEntity; +import org.hibernate.envers.test.Priority; +import org.hibernate.envers.test.entities.StrTestEntity; + +import org.junit.Test; + +import org.hibernate.testing.TestForIssue; + +import static org.junit.Assert.assertEquals; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@TestForIssue( jiraKey = "HHH-8243" ) +public class CommitFlush extends AbstractFlushTest { + private Integer id = null; + + @Override + public FlushMode getFlushMode() { + return FlushMode.COMMIT; + } + + @Test + @Priority(10) + public void initData() { + EntityManager em = getEntityManager(); + + // Revision 1 + em.getTransaction().begin(); + StrTestEntity entity = new StrTestEntity( "x" ); + em.persist( entity ); + em.getTransaction().commit(); + + id = entity.getId(); + + // Revision 2 + em.getTransaction().begin(); + entity = em.find( StrTestEntity.class, entity.getId() ); + entity.setStr( "y" ); + entity = em.merge( entity ); + em.getTransaction().commit(); + + em.close(); + } + + @Test + public void testRevisionsCounts() { + assertEquals( Arrays.asList( 1, 2 ), getAuditReader().getRevisions( StrTestEntity.class, id ) ); + } + + @Test + public void testHistoryOfId() { + StrTestEntity ver1 = new StrTestEntity( "x", id ); + StrTestEntity ver2 = new StrTestEntity( "y", id ); + + assertEquals( ver1, getAuditReader().find( StrTestEntity.class, id, 1 ) ); + assertEquals( ver2, getAuditReader().find( StrTestEntity.class, id, 2 ) ); + } + + @Test + public void testCurrent() { + assertEquals( new StrTestEntity( "y", id ), getEntityManager().find( StrTestEntity.class, id ) ); + } + + @Test + public void testRevisionTypes() { + List results = getAuditReader().createQuery() + .forRevisionsOfEntity( StrTestEntity.class, false, true ) + .add( AuditEntity.id().eq( id ) ) + .getResultList(); + + assertEquals( results.get( 0 )[2], RevisionType.ADD ); + assertEquals( results.get( 1 )[2], RevisionType.MOD ); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeDateId.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeDateId.java index 0f3d28d9653e..bfc6309f03ef 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeDateId.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeDateId.java @@ -42,7 +42,7 @@ public class CompositeDateId extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {CompositeDateIdTestEntity.class}; + return new Class[] {CompositeDateIdTestEntity.class, DateEmbId.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeIds.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeIds.java index fdedd4a2c06a..42055b491f17 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeIds.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/CompositeIds.java @@ -51,7 +51,13 @@ public class CompositeIds extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbIdTestEntity.class, MulIdTestEntity.class, EmbIdWithCustomTypeTestEntity.class}; + return new Class[] { + EmbIdTestEntity.class, + MulIdTestEntity.class, + EmbIdWithCustomTypeTestEntity.class, + EmbId.class, + EmbIdWithCustomType.class + }; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/ManyToOneIdNotAudited.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/ManyToOneIdNotAudited.java index 9fb2e9b12591..ef22d80f6cdc 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/ManyToOneIdNotAudited.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/ManyToOneIdNotAudited.java @@ -22,7 +22,12 @@ public class ManyToOneIdNotAudited extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ManyToOneIdNotAuditedTestEntity.class, UnversionedStrTestEntity.class, StrTestEntity.class}; + return new Class[] { + ManyToOneIdNotAuditedTestEntity.class, + UnversionedStrTestEntity.class, + StrTestEntity.class, + ManyToOneNotAuditedEmbId.class + }; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/embeddedid/RelationInsideEmbeddableTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/embeddedid/RelationInsideEmbeddableTest.java index cfc6c47c5975..c56fb54e0c5f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/embeddedid/RelationInsideEmbeddableTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/ids/embeddedid/RelationInsideEmbeddableTest.java @@ -9,12 +9,14 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-7690") +@FailureExpectedWithNewMetamodel( message = "Associations with non-envers entities not supported yet." ) public class RelationInsideEmbeddableTest extends BaseEnversJPAFunctionalTestCase { private Integer orderId = null; private ItemId itemId = null; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/joined/primarykeyjoin/ChildPrimaryKeyJoinAuditing.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/joined/primarykeyjoin/ChildPrimaryKeyJoinAuditing.java index 2d96f5b5686a..b50a3aba031f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/joined/primarykeyjoin/ChildPrimaryKeyJoinAuditing.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/joined/primarykeyjoin/ChildPrimaryKeyJoinAuditing.java @@ -30,7 +30,7 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.integration.inheritance.joined.ParentEntity; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.relational.Column; import org.junit.Assert; import org.junit.Test; @@ -101,11 +101,15 @@ assert getAuditReader().createQuery().forEntitiesAtRevision( ParentEntity.class, public void testChildIdColumnName() { Assert.assertEquals( "other_id", - ((Column) getCfg() - .getClassMapping( + ( (Column) getMetadata() + .getEntityBinding( "org.hibernate.envers.test.integration.inheritance.joined.primarykeyjoin.ChildPrimaryKeyJoinEntity_AUD" ) - .getKey().getColumnIterator().next()).getName() + .getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding() + .getValues() + .get( 0 ) ).getColumnName().getText() ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/mixed/MixedInheritanceStrategiesEntityTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/mixed/MixedInheritanceStrategiesEntityTest.java index 5b9354e76d2f..86ef3e96df07 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/mixed/MixedInheritanceStrategiesEntityTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/mixed/MixedInheritanceStrategiesEntityTest.java @@ -30,7 +30,8 @@ protected Class[] getAnnotatedClasses() { AbstractActivity.class, AbstractCheckActivity.class, CheckInActivity.class, - NormalActivity.class + NormalActivity.class, + ActivityId.class }; } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/single/discriminatorformula/DiscriminatorFormulaTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/single/discriminatorformula/DiscriminatorFormulaTest.java index d471294988f6..99d998f8254b 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/single/discriminatorformula/DiscriminatorFormulaTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/single/discriminatorformula/DiscriminatorFormulaTest.java @@ -2,13 +2,14 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Formula; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.EntityDiscriminator; +import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.Value; import org.junit.Assert; import org.junit.Test; @@ -17,7 +18,7 @@ * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ public class DiscriminatorFormulaTest extends BaseEnversJPAFunctionalTestCase { - private PersistentClass parentAudit = null; + private EntityBinding parentAudit = null; private ChildEntity childVer1 = null; private ChildEntity childVer2 = null; private ParentEntity parentVer1 = null; @@ -31,7 +32,7 @@ protected Class[] getAnnotatedClasses() { @Test @Priority(10) public void initData() { - parentAudit = getCfg().getClassMapping( + parentAudit = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.inheritance.single.discriminatorformula.ParentEntity_AUD" ); @@ -87,16 +88,10 @@ public void initData() { @Test public void testDiscriminatorFormulaInAuditTable() { - assert parentAudit.getDiscriminator().hasFormula(); - Iterator iterator = parentAudit.getDiscriminator().getColumnIterator(); - while ( iterator.hasNext() ) { - Object o = iterator.next(); - if ( o instanceof Formula ) { - Formula formula = (Formula) o; - Assert.assertEquals( ParentEntity.DISCRIMINATOR_QUERY, formula.getText() ); - return; - } - } + final EntityDiscriminator entityDiscriminator = parentAudit.getHierarchyDetails().getEntityDiscriminator(); + assert entityDiscriminator.getRelationalValue().getValueType() == Value.ValueType.DERIVED_VALUE; + DerivedValue derivedValue = (DerivedValue) entityDiscriminator.getRelationalValue(); + Assert.assertEquals( ParentEntity.DISCRIMINATOR_QUERY, derivedValue.getExpression() ); assert false; } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/tableperclass/abstractparent/AuditedAbstractParentTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/tableperclass/abstractparent/AuditedAbstractParentTest.java index f6b95aedad56..344cefa1e085 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/tableperclass/abstractparent/AuditedAbstractParentTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/inheritance/tableperclass/abstractparent/AuditedAbstractParentTest.java @@ -1,15 +1,16 @@ package org.hibernate.envers.test.integration.inheritance.tableperclass.abstractparent; import javax.persistence.EntityManager; -import java.util.Iterator; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Table; import org.junit.Assert; import org.junit.Test; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.testing.TestForIssue; /** @@ -38,12 +39,12 @@ public void initData() { @Test public void testAbstractTableExistence() { - Iterator
    tableIterator = getCfg().getTableMappings(); - while ( tableIterator.hasNext() ) { - Table table = tableIterator.next(); - if ( "AbstractEntity_AUD".equals( table.getName() ) ) { - Assert.assertFalse( table.isPhysicalTable() ); - return; + for ( Schema schema : getMetadata().getDatabase().getSchemas() ) { + for ( TableSpecification table : schema.getTables() ) { + if ( "AbstractEntity_AUD".equals( table.getLogicalName().getText() ) ) { + Assert.assertFalse( Table.class.isInstance( table ) ); + return; + } } } Assert.fail(); diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/components/InterfacesComponents.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/components/InterfacesComponents.java index f28e6032ada1..c07ad1d858b7 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/components/InterfacesComponents.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/components/InterfacesComponents.java @@ -39,7 +39,7 @@ public class InterfacesComponents extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ComponentTestEntity.class}; + return new Class[] {ComponentTestEntity.class, Component1.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/joined/JoinedAllAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/joined/JoinedAllAuditedTest.java index 0242ecf0dd6c..9ca90dee2055 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/joined/JoinedAllAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/joined/JoinedAllAuditedTest.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.allAudited.joined; import org.hibernate.envers.test.integration.interfaces.hbm.allAudited.AbstractAllAuditedTest; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class JoinedAllAuditedTest extends AbstractAllAuditedTest { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/subclass/SubclassAllAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/subclass/SubclassAllAuditedTest.java index 6cbb92252dbd..8fa57049b236 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/subclass/SubclassAllAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/subclass/SubclassAllAuditedTest.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.allAudited.subclass; import org.hibernate.envers.test.integration.interfaces.hbm.allAudited.AbstractAllAuditedTest; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class SubclassAllAuditedTest extends AbstractAllAuditedTest { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/union/UnionAllAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/union/UnionAllAuditedTest.java index 033741a0d7a2..d8474336a8a8 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/union/UnionAllAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/allAudited/union/UnionAllAuditedTest.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.allAudited.union; import org.hibernate.envers.test.integration.interfaces.hbm.allAudited.AbstractAllAuditedTest; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class UnionAllAuditedTest extends AbstractAllAuditedTest { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/joined/JoinedPropertiesAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/joined/JoinedPropertiesAuditedTest.java index ee043e4e4879..28a5baac51c0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/joined/JoinedPropertiesAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/joined/JoinedPropertiesAuditedTest.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.joined; import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.AbstractPropertiesAuditedTest; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class JoinedPropertiesAuditedTest extends AbstractPropertiesAuditedTest { @Override diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/subclass/SubclassPropertiesAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/subclass/SubclassPropertiesAuditedTest.java index 7caf878627b3..c3607594a05a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/subclass/SubclassPropertiesAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/subclass/SubclassPropertiesAuditedTest.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.subclass; import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.AbstractPropertiesAuditedTest; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class SubclassPropertiesAuditedTest extends AbstractPropertiesAuditedTest { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/union/UnionPropertiesAuditedTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/union/UnionPropertiesAuditedTest.java index 1ec2f8b854b9..e0cfd87c00b4 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/union/UnionPropertiesAuditedTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited/union/UnionPropertiesAuditedTest.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.union; import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.AbstractPropertiesAuditedTest; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class UnionPropertiesAuditedTest extends AbstractPropertiesAuditedTest { @Override diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/joined/JoinedPropertiesAudited2Test.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/joined/JoinedPropertiesAudited2Test.java index 7f4acf547582..2a7d5429091b 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/joined/JoinedPropertiesAudited2Test.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/joined/JoinedPropertiesAudited2Test.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.joined; import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.AbstractPropertiesAudited2Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class JoinedPropertiesAudited2Test extends AbstractPropertiesAudited2Test { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/subclass/SubclassPropertiesAudited2Test.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/subclass/SubclassPropertiesAudited2Test.java index 1adce3c08e3e..feae6d2845a2 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/subclass/SubclassPropertiesAudited2Test.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/subclass/SubclassPropertiesAudited2Test.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.subclass; import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.AbstractPropertiesAudited2Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class SubclassPropertiesAudited2Test extends AbstractPropertiesAudited2Test { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/union/UnionPropertiesAudited2Test.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/union/UnionPropertiesAudited2Test.java index 01088eafb87e..e44205848f35 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/union/UnionPropertiesAudited2Test.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/interfaces/hbm/propertiesAudited2/union/UnionPropertiesAudited2Test.java @@ -1,10 +1,12 @@ package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.union; import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.AbstractPropertiesAudited2Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class UnionPropertiesAudited2Test extends AbstractPropertiesAudited2Test { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/CustomComparatorEntityTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/CustomComparatorEntityTest.java index cc5bb26d3603..de882a88b4e0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/CustomComparatorEntityTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/CustomComparatorEntityTest.java @@ -35,6 +35,7 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.entities.StrTestEntityComparator; import org.hibernate.envers.test.entities.manytomany.SortedSetEntity; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -43,6 +44,7 @@ /** * @author Michal Skowronek (mskowr at o2 pl) */ +@FailureExpectedWithNewMetamodel( message = "@MapKeyJoinColumn is not supported yet" ) public class CustomComparatorEntityTest extends BaseEnversJPAFunctionalTestCase { private Integer id1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/inverseToSuperclass/ManyToManyInverseToSuperclassTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/inverseToSuperclass/ManyToManyInverseToSuperclassTest.java index 4a0f2a4f7193..3266f53bf2ad 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/inverseToSuperclass/ManyToManyInverseToSuperclassTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/inverseToSuperclass/ManyToManyInverseToSuperclassTest.java @@ -5,12 +5,14 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hern�n Chanfreau */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class ManyToManyInverseToSuperclassTest extends BaseEnversJPAFunctionalTestCase { private long m1_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMap.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMap.java index f527070643f1..6a620bfc844b 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMap.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMap.java @@ -31,6 +31,7 @@ import org.hibernate.envers.test.entities.IntTestPrivSeqEntity; import org.hibernate.envers.test.entities.StrTestPrivSeqEntity; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Assert; import org.junit.Test; @@ -38,6 +39,8 @@ /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = "@MapKeyJoinColumn is not supported yet" ) + public class TernaryMap extends BaseEnversJPAFunctionalTestCase { private Integer str1_id; private Integer str2_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMapFlush.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMapFlush.java index e072ec36b760..ace5289482ce 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMapFlush.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/ternary/TernaryMapFlush.java @@ -32,6 +32,7 @@ import org.hibernate.envers.test.entities.IntTestPrivSeqEntity; import org.hibernate.envers.test.entities.StrTestPrivSeqEntity; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -40,6 +41,7 @@ /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = "@MapKeyJoinColumn is not supported yet" ) public class TernaryMapFlush extends BaseEnversJPAFunctionalTestCase { private Integer str1_id; private Integer str2_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/merge/AddDelTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/merge/AddDelTest.java index b7afd264cb51..e6c750db4f31 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/merge/AddDelTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/merge/AddDelTest.java @@ -10,6 +10,7 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedAuditedManyToManyTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedAuditedManyToManyTest.java index 3df9dd68dbc2..28dc476fbdd8 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedAuditedManyToManyTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedAuditedManyToManyTest.java @@ -11,6 +11,7 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.integration.entityNames.manyToManyAudited.Car; import org.hibernate.envers.test.integration.entityNames.manyToManyAudited.Person; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -22,6 +23,7 @@ * @author Hernán Chanfreau * @author Michal Skowronek (mskowr at o2 dot pl) */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class HasChangedAuditedManyToManyTest extends AbstractModifiedFlagsOneSessionTest { private long id_car1; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentCollection.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentCollection.java index 49db29119a76..f701fef0ed0b 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentCollection.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentCollection.java @@ -30,7 +30,7 @@ public class HasChangedComponentCollection extends AbstractModifiedFlagsEntityTe @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbeddableListEntity1.class}; + return new Class[] {EmbeddableListEntity1.class, Component3.class, Component4.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentMapKey.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentMapKey.java index 54909f5ea03e..bcb0a9a59832 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentMapKey.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponentMapKey.java @@ -31,6 +31,7 @@ import org.hibernate.envers.test.entities.components.Component2; import org.hibernate.envers.test.entities.components.ComponentTestEntity; import org.hibernate.envers.test.integration.collection.mapkey.ComponentMapKeyEntity; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -42,6 +43,7 @@ * @author Adam Warski (adam at warski dot org) * @author Michal Skowronek (mskowr at o2 dot pl) */ +@FailureExpectedWithNewMetamodel( message = "Plural attribute index that is an attribute of the referenced entity is not supported yet." ) public class HasChangedComponentMapKey extends AbstractModifiedFlagsEntityTest { private Integer cmke_id; @@ -50,7 +52,7 @@ public class HasChangedComponentMapKey extends AbstractModifiedFlagsEntityTest { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ComponentMapKeyEntity.class, ComponentTestEntity.class}; + return new Class[] {ComponentMapKeyEntity.class, ComponentTestEntity.class, Component1.class, Component2.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponents.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponents.java index f39023c8cb73..b44da52d07ec 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponents.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedComponents.java @@ -51,7 +51,7 @@ public class HasChangedComponents extends AbstractModifiedFlagsEntityTest { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ComponentTestEntity.class}; + return new Class[] {ComponentTestEntity.class, Component1.class, Component2.class}; } @Test @@ -139,7 +139,7 @@ public void testModFlagProperties() { assertEquals( TestTools.makeSet( "comp1_MOD" ), TestTools.extractModProperties( - getCfg().getClassMapping( + getMetadata().getEntityBinding( "org.hibernate.envers.test.entities.components.ComponentTestEntity_AUD" ) ) diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedForDefaultNotUsing.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedForDefaultNotUsing.java index ce28305313b7..4da889c64823 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedForDefaultNotUsing.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedForDefaultNotUsing.java @@ -58,7 +58,9 @@ protected Class[] getAnnotatedClasses() { return new Class[] { PartialModifiedFlagsEntity.class, WithModifiedFlagReferencingEntity.class, - StrTestEntity.class + StrTestEntity.class, + Component1.class, + Component2.class }; } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedIdMapKey.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedIdMapKey.java index 1b8837dc7c74..3ba1acf23fb8 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedIdMapKey.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedIdMapKey.java @@ -29,6 +29,7 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.integration.collection.mapkey.IdMapKeyEntity; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -40,6 +41,7 @@ * @author Adam Warski (adam at warski dot org) * @author Michal Skowronek (mskowr at o2 dot pl) */ +@FailureExpectedWithNewMetamodel( message = "Plural attribute index that is an attribute of the referenced entity is not supported yet." ) public class HasChangedIdMapKey extends AbstractModifiedFlagsEntityTest { private Integer imke_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedManyToOneInComponent.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedManyToOneInComponent.java index 1a771185f97b..3f491792a2b0 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedManyToOneInComponent.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedManyToOneInComponent.java @@ -46,7 +46,7 @@ public class HasChangedManyToOneInComponent extends AbstractModifiedFlagsEntityT @Override protected Class[] getAnnotatedClasses() { - return new Class[] {ManyToOneComponentTestEntity.class, StrTestEntity.class}; + return new Class[] {ManyToOneComponentTestEntity.class, StrTestEntity.class, ManyToOneComponent.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedOneToManyInComponent.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedOneToManyInComponent.java index e6453884f240..1ffadc4dedeb 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedOneToManyInComponent.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/HasChangedOneToManyInComponent.java @@ -30,6 +30,8 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.entities.components.relations.OneToManyComponent; import org.hibernate.envers.test.entities.components.relations.OneToManyComponentTestEntity; +import org.hibernate.envers.test.integration.naming.VersionsJoinTableRangeComponent; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -46,11 +48,17 @@ public class HasChangedOneToManyInComponent extends AbstractModifiedFlagsEntityT @Override protected Class[] getAnnotatedClasses() { - return new Class[] {OneToManyComponentTestEntity.class, StrTestEntity.class}; + return new Class[] { + OneToManyComponentTestEntity.class, + StrTestEntity.class, + OneToManyComponent.class, + VersionsJoinTableRangeComponent.class + }; } @Test @Priority(10) + @FailureExpectedWithNewMetamodel( message = "Collction role is incorrect when contained in an @Embeddable" ) public void initData() { // Revision 1 EntityManager em = getEntityManager(); @@ -91,6 +99,7 @@ public void initData() { } @Test + @FailureExpectedWithNewMetamodel( message = "Fails because initData fails." ) public void testHasChangedId1() throws Exception { List list = queryForPropertyHasChanged( diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/ModifiedFlagSuffix.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/ModifiedFlagSuffix.java index a88b79d180ef..938ba319a923 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/ModifiedFlagSuffix.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/ModifiedFlagSuffix.java @@ -78,7 +78,7 @@ public void testModFlagProperties() { assertEquals( TestTools.makeSet( "str1_CHANGED", "long1_CHANGED" ), TestTools.extractModProperties( - getCfg().getClassMapping( + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.basic.BasicTestEntity1_AUD" ), "_CHANGED" diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/entities/PartialModifiedFlagsEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/entities/PartialModifiedFlagsEntity.java index 76e22e31b6ec..2f22ba23a2f6 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/entities/PartialModifiedFlagsEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/modifiedflags/entities/PartialModifiedFlagsEntity.java @@ -75,25 +75,25 @@ public class PartialModifiedFlagsEntity { @Audited(withModifiedFlag = true) @ElementCollection - @JoinTable(name = "PartialModFlags_StrSet") + @CollectionTable(name = "PartialModFlags_StrSet") @AuditJoinTable(name = "PartialModFlags_StrSet_AUD") private Set stringSet = new HashSet(); @Audited(withModifiedFlag = true) @ManyToMany - @CollectionTable(name = "ENTITIESSET") + @JoinTable(name = "ENTITIESSET") private Set entitiesSet = new HashSet(); @Audited(withModifiedFlag = true) @ElementCollection @MapKeyColumn(nullable = false) - @JoinTable(name = "PartialModFlags_StrMap") + @CollectionTable(name = "PartialModFlags_StrMap") @AuditJoinTable(name = "PartialModFlags_StrMap_AUD") private Map stringMap = new HashMap(); @Audited(withModifiedFlag = true) @ManyToMany - @CollectionTable(name = "ENTITIESMAP") + @JoinTable(name = "ENTITIESMAP") @MapKeyColumn(nullable = false) private Map entitiesMap = new HashMap(); diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/BasicNaming.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/BasicNaming.java index 99711705d310..ac2c42d27770 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/BasicNaming.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/BasicNaming.java @@ -110,8 +110,8 @@ public void testHistoryOfId2() { @Test public void testTableName() { assert "naming_test_entity_1_versions".equals( - getCfg().getClassMapping( "org.hibernate.envers.test.integration.naming.NamingTestEntity1_AUD" ) - .getTable().getName() + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.naming.NamingTestEntity1_AUD" ) + .getPrimaryTableName() ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/JoinNaming.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/JoinNaming.java index 166635d22c31..3a154242df2b 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/JoinNaming.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/JoinNaming.java @@ -25,16 +25,16 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; import org.junit.Test; import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; /** @@ -128,11 +128,17 @@ assert getAuditReader().find( JoinNamingRefIngEntity.class, ing_id1, 2 ).getRefe @SuppressWarnings({"unchecked"}) @Test public void testJoinColumnName() { - Iterator columns = - getCfg().getClassMapping( "org.hibernate.envers.test.integration.naming.JoinNamingRefIngEntity_AUD" ) - .getProperty( "reference_id" ).getColumnIterator(); - assertTrue( columns.hasNext() ); - assertEquals( "jnree_column_reference", columns.next().getName() ); - assertFalse( columns.hasNext() ); + final AttributeBinding attributeBinding = getMetadata().getEntityBinding( + "org.hibernate.envers.test.integration.naming.JoinNamingRefIngEntity_AUD" + ).locateAttributeBinding( "reference_id" ); + assertTrue( attributeBinding.getAttribute().isSingular() ); + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + assertTrue( !singularAttributeBinding.getValues().isEmpty() ); + + assertEquals( + "jnree_column_reference", + ( (Column) singularAttributeBinding.getValues().get( 0 ) ).getColumnName().getText() + ); + assertEquals( singularAttributeBinding.getValues().size(), 1 ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/OneToManyUnidirectionalNaming.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/OneToManyUnidirectionalNaming.java index cb52a4abbfdf..9de6eee67e43 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/OneToManyUnidirectionalNaming.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/OneToManyUnidirectionalNaming.java @@ -26,13 +26,14 @@ import javax.persistence.EntityManager; import java.util.Arrays; import java.util.HashSet; -import java.util.Iterator; +import java.util.List; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.tools.TestTools; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; import org.junit.Test; @@ -104,26 +105,25 @@ public void testHistoryOfUniId1() { @Test public void testTableName() { assert MIDDLE_VERSIONS_ENTITY_NAME.equals( - getCfg().getClassMapping( MIDDLE_VERSIONS_ENTITY_NAME ).getTable().getName() + getMetadata().getEntityBinding( MIDDLE_VERSIONS_ENTITY_NAME ).getPrimaryTableName() ); } @SuppressWarnings({"unchecked"}) @Test public void testJoinColumnName() { - Iterator columns = - getCfg().getClassMapping( MIDDLE_VERSIONS_ENTITY_NAME ).getTable().getColumnIterator(); boolean id1Found = false; boolean id2Found = false; - while ( columns.hasNext() ) { - Column column = columns.next(); - if ( "ID_1".equals( column.getName() ) ) { + final List values = getMetadata().getEntityBinding( MIDDLE_VERSIONS_ENTITY_NAME ).getPrimaryTable().values(); + for ( Value value : values ) { + Column column = (Column) value; + if ( "ID_1".equals( column.getColumnName().getText() ) ) { id1Found = true; } - if ( "ID_2".equals( column.getName() ) ) { + if ( "ID_2".equals( column.getColumnName().getText() ) ) { id2Found = true; } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableNaming.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableNaming.java index 70d410d043dd..8d6bbdd80ae8 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableNaming.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableNaming.java @@ -26,13 +26,14 @@ import javax.persistence.EntityManager; import java.util.Arrays; import java.util.HashSet; -import java.util.Iterator; +import java.util.List; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.tools.TestTools; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; import org.junit.Test; @@ -109,26 +110,26 @@ public void testHistoryOfUniId1() { @Test public void testTableName() { assert MIDDLE_VERSIONS_ENTITY_NAME.equals( - getCfg().getClassMapping( MIDDLE_VERSIONS_ENTITY_NAME ).getTable().getName() + getMetadata().getEntityBinding( MIDDLE_VERSIONS_ENTITY_NAME ).getPrimaryTableName() ); } @SuppressWarnings({"unchecked"}) @Test public void testJoinColumnName() { - Iterator columns = - getCfg().getClassMapping( MIDDLE_VERSIONS_ENTITY_NAME ).getTable().getColumnIterator(); + List values = + getMetadata().getEntityBinding( MIDDLE_VERSIONS_ENTITY_NAME ).getPrimaryTable().values(); boolean id1Found = false; boolean id2Found = false; - while ( columns.hasNext() ) { - Column column = columns.next(); - if ( "VJT_ID".equals( column.getName() ) ) { + for ( Value value : values ) { + Column column = (Column) value; + if ( "VJT_ID".equals( column.getColumnName().getText() ) ) { id1Found = true; } - if ( "STR_ID".equals( column.getName() ) ) { + if ( "STR_ID".equals( column.getColumnName().getText() ) ) { id2Found = true; } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponent.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponent.java index a1d0641ab9c2..7f07fe3eade2 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponent.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponent.java @@ -21,9 +21,8 @@ @Embeddable public final class VersionsJoinTableRangeComponent { - @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) @org.hibernate.annotations.Fetch(value = FetchMode.SUBSELECT) - @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @JoinColumn(name = "VJTRCTE_ID", insertable = true, updatable = false, nullable = false) // Note: If this is processed without override annotation, then we should get a // org.hibernate.DuplicateMappingException: diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponentNamingTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponentNamingTest.java index 03303fa215c1..2c1b8278ebd2 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponentNamingTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/VersionsJoinTableRangeComponentNamingTest.java @@ -31,8 +31,9 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.components.Component1; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; import org.junit.Test; @@ -54,7 +55,9 @@ protected Class[] getAnnotatedClasses() { VersionsJoinTableRangeComponentTestEntity.class, VersionsJoinTableRangeTestEntitySuperClass.class, VersionsJoinTableRangeTestEntity.class, - VersionsJoinTableRangeTestAlternateEntity.class + VersionsJoinTableRangeTestAlternateEntity.class, + VersionsJoinTableRangeComponent.class, + Component1.class }; } @@ -198,31 +201,29 @@ public void testHistoryOfUniId1() { @Test public void testExpectedTableNameComponent1() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( COMPONENT_1_AUDIT_JOIN_TABLE_NAME ); assert auditClass != null; assert COMPONENT_1_AUDIT_JOIN_TABLE_NAME.equals( - auditClass.getTable() - .getName() + auditClass.getPrimaryTableName() ); } @Test public void testExpectedTableNameComponent2() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( COMPONENT_2_AUDIT_JOIN_TABLE_NAME ); assert auditClass != null; assert COMPONENT_2_AUDIT_JOIN_TABLE_NAME.equals( - auditClass.getTable() - .getName() + auditClass.getPrimaryTableName() ); } @Test public void testWrongTableNameComponent1() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( UNMODIFIED_COMPONENT_1_AUDIT_JOIN_TABLE_NAME ); assert auditClass == null; @@ -230,7 +231,7 @@ public void testWrongTableNameComponent1() { @Test public void testWrongTableNameComponent2() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( UNMODIFIED_COMPONENT_2_AUDIT_JOIN_TABLE_NAME ); assert auditClass == null; @@ -238,24 +239,22 @@ public void testWrongTableNameComponent2() { @Test public void testJoinColumnNamesComponent1() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( COMPONENT_1_AUDIT_JOIN_TABLE_NAME ); assert auditClass != null; - @SuppressWarnings({"unchecked"}) - Iterator columns = auditClass.getTable().getColumnIterator(); - boolean id1Found = false; boolean id2Found = false; - while ( columns.hasNext() ) { - Column column = columns.next(); - if ( "VJTRCTE1_ID".equals( column.getName() ) ) { + List values = auditClass.getPrimaryTable().values(); + for ( Value value : values ) { + Column column = (Column) value; + if ( "VJTRCTE1_ID".equals( column.getColumnName().getText() ) ) { id1Found = true; } - if ( "VJTRTE_ID".equals( column.getName() ) ) { + if ( "VJTRTE_ID".equals( column.getColumnName().getText() ) ) { id2Found = true; } } @@ -265,24 +264,22 @@ public void testJoinColumnNamesComponent1() { @Test public void testJoinColumnNamesComponent2() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( COMPONENT_2_AUDIT_JOIN_TABLE_NAME ); assert auditClass != null; - @SuppressWarnings({"unchecked"}) - Iterator columns = auditClass.getTable().getColumnIterator(); - boolean id1Found = false; boolean id2Found = false; - while ( columns.hasNext() ) { - Column column = columns.next(); - if ( "VJTRCTE2_ID".equals( column.getName() ) ) { + List values = auditClass.getPrimaryTable().values(); + for ( Value value : values ) { + Column column = (Column) value; + if ( "VJTRCTE2_ID".equals( column.getColumnName().getText() ) ) { id1Found = true; } - if ( "VJTRTAE_ID".equals( column.getName() ) ) { + if ( "VJTRTAE_ID".equals( column.getColumnName().getText() ) ) { id2Found = true; } } @@ -297,25 +294,23 @@ public void testJoinColumnNamesComponent2() { */ @Test public void testOverrideNotAudited() { - PersistentClass auditClass = getCfg().getClassMapping( + EntityBinding auditClass = getMetadata().getEntityBinding( VersionsJoinTableRangeComponentTestEntity.class.getName() + "_AUD" ); assert auditClass != null; - @SuppressWarnings({"unchecked"}) - Iterator columns = auditClass.getTable().getColumnIterator(); - boolean auditColumn1Found = false; boolean auditColumn2Found = false; - while ( columns.hasNext() ) { - Column column = columns.next(); - if ( "STR1".equals( column.getName() ) ) { + List values = auditClass.getPrimaryTable().values(); + for ( Value value : values ) { + Column column = (Column) value; + if ( "STR1".equals( column.getColumnName().getText() ) ) { auditColumn1Found = true; } - if ( "STR2".equals( column.getName() ) ) { + if ( "STR2".equals( column.getColumnName().getText() ) ) { auditColumn2Found = true; } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinEmbIdNaming.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinEmbIdNaming.java index cbb4ac50c864..aaa4fec49177 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinEmbIdNaming.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinEmbIdNaming.java @@ -25,21 +25,24 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; +import java.util.List; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = " No support yet for referenced join columns unless they correspond with columns bound for an attribute binding." ) public class JoinEmbIdNaming extends BaseEnversJPAFunctionalTestCase { private EmbIdNaming ed_id1; private EmbIdNaming ed_id2; @@ -141,22 +144,23 @@ assert getAuditReader().find( JoinEmbIdNamingRefIngEntity.class, ing_id1, 2 ).ge @SuppressWarnings({"unchecked"}) @Test public void testJoinColumnNames() { - Iterator columns = - getCfg().getClassMapping( + SingularAttributeBinding attributeBinding = (SingularAttributeBinding) + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.naming.ids.JoinEmbIdNamingRefIngEntity_AUD" - ) - .getProperty( "reference_x" ).getColumnIterator(); - assertTrue( columns.hasNext() ); - assertEquals( "XX_reference", columns.next().getName() ); - assertFalse( columns.hasNext() ); - - columns = getCfg().getClassMapping( - "org.hibernate.envers.test.integration.naming.ids.JoinEmbIdNamingRefIngEntity_AUD" - ) - .getProperty( "reference_y" ).getColumnIterator(); - - assertTrue( columns.hasNext() ); - assertEquals( "YY_reference", columns.next().getName() ); - assertFalse( columns.hasNext() ); + ).locateAttributeBinding( "reference_x" ); + List values = attributeBinding.getValues(); + assertTrue( !values.isEmpty() ); + assertEquals( "XX_reference", ( (Column) values.get( 0 ) ).getColumnName().getText() ); + assertEquals( 1, values.size() ); + + attributeBinding = (SingularAttributeBinding) + getMetadata().getEntityBinding( + "org.hibernate.envers.test.integration.naming.ids.JoinEmbIdNamingRefIngEntity_AUD" + ).locateAttributeBinding( "reference_y" ); + values = attributeBinding.getValues(); + + assertTrue( !values.isEmpty() ); + assertEquals( "YY_reference", ( (Column) values.get( 0 ) ).getColumnName().getText() ); + assertEquals( 1, values.size() ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinMulIdNaming.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinMulIdNaming.java index 9d3a05017267..097560ef31bf 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinMulIdNaming.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/ids/JoinMulIdNaming.java @@ -25,11 +25,14 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; +import java.util.List; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -40,6 +43,8 @@ /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = " No support yet for referenced join columns unless they correspond with columns bound for an attribute binding." ) + public class JoinMulIdNaming extends BaseEnversJPAFunctionalTestCase { private MulIdNaming ed_id1; private MulIdNaming ed_id2; @@ -141,21 +146,20 @@ assert getAuditReader().find( JoinMulIdNamingRefIngEntity.class, ing_id1, 2 ).ge @SuppressWarnings({"unchecked"}) @Test public void testJoinColumnNames() { - Iterator columns = - getCfg().getClassMapping( - "org.hibernate.envers.test.integration.naming.ids.JoinMulIdNamingRefIngEntity_AUD" - ) - .getProperty( "reference_id1" ).getColumnIterator(); - assertTrue( columns.hasNext() ); - assertEquals( "ID1_reference", columns.next().getName() ); - assertFalse( columns.hasNext() ); + SingularAttributeBinding attributeBinding = (SingularAttributeBinding) getMetadata().getEntityBinding( + "org.hibernate.envers.test.integration.naming.ids.JoinMulIdNamingRefIngEntity_AUD" + ).locateAttributeBinding( "reference_id1" ); + List values = attributeBinding.getValues(); + assertTrue( !values.isEmpty() ); + assertEquals( "ID1_reference", ( (Column) values.get( 0 ) ).getColumnName().getText() ); + assertEquals( 1, values.size() ); - columns = getCfg().getClassMapping( + attributeBinding = (SingularAttributeBinding) getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.naming.ids.JoinMulIdNamingRefIngEntity_AUD" - ) - .getProperty( "reference_id2" ).getColumnIterator(); - assertTrue( columns.hasNext() ); - assertEquals( "ID2_reference", columns.next().getName() ); - assertFalse( columns.hasNext() ); + ).locateAttributeBinding( "reference_id2" ); + values = attributeBinding.getValues(); + assertTrue( !values.isEmpty() ); + assertEquals( "ID2_reference", ( (Column) values.get( 0 ) ).getColumnName().getText() ); + assertEquals( 1, values.size() ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/quotation/QuotedFieldsTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/quotation/QuotedFieldsTest.java index 8ba87cdf0cd1..2b9c7ee4d65c 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/quotation/QuotedFieldsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/quotation/QuotedFieldsTest.java @@ -2,12 +2,11 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.junit.Test; @@ -80,28 +79,17 @@ public void testHistoryOfId2() { @Test public void testEscapeEntityField() { - Table table = getCfg().getClassMapping( + TableSpecification table = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.naming.quotation.QuotedFieldsEntity_AUD" - ).getTable(); - Column column1 = getColumnByName( table, "id" ); - Column column2 = getColumnByName( table, "data1" ); - Column column3 = getColumnByName( table, "data2" ); + ).getPrimaryTable(); + Column column1 = table.locateColumn( "id" ); + Column column2 = table.locateColumn( "data1" ); + Column column3 = table.locateColumn( "data2" ); assert column1 != null; assert column2 != null; assert column3 != null; - assert column1.isQuoted(); - assert column2.isQuoted(); - assert column3.isQuoted(); - } - - private Column getColumnByName(Table table, String columnName) { - Iterator columnIterator = table.getColumnIterator(); - while ( columnIterator.hasNext() ) { - Column column = columnIterator.next(); - if ( columnName.equals( column.getName() ) ) { - return column; - } - } - return null; + assert column1.getColumnName().isQuoted(); + assert column2.getColumnName().isQuoted(); + assert column3.getColumnName().isQuoted(); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithEmbId.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithEmbId.java index af713707f49a..06f283605e37 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithEmbId.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithEmbId.java @@ -49,7 +49,7 @@ public class BasicSetWithEmbId extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {SetRefEdEmbIdEntity.class, SetRefIngEmbIdEntity.class}; + return new Class[] {SetRefEdEmbIdEntity.class, SetRefIngEmbIdEntity.class, EmbId.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithMulId.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithMulId.java index c2adab7ad10e..bcd10075a4cc 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithMulId.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicSetWithMulId.java @@ -34,12 +34,14 @@ import org.hibernate.envers.test.entities.ids.MulId; import org.hibernate.envers.test.entities.onetomany.ids.SetRefEdMulIdEntity; import org.hibernate.envers.test.entities.onetomany.ids.SetRefIngMulIdEntity; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055 : Association with an entity with @IdClass is broken." ) public class BasicSetWithMulId extends BaseEnversJPAFunctionalTestCase { private MulId ed1_id; private MulId ed2_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BidirectionalMapKey.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BidirectionalMapKey.java index 494c4cc0ed95..47ad32ec4952 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BidirectionalMapKey.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BidirectionalMapKey.java @@ -29,12 +29,14 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( message = "Plural attribute index that is an attribute of the referenced entity is not supported yet" ) public class BidirectionalMapKey extends BaseEnversJPAFunctionalTestCase { private Integer ed_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java index 2b3e9bad8a5a..852a75741cd2 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java @@ -47,7 +47,7 @@ public class BasicDetachedSetWithEmbId extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbIdTestEntity.class, SetRefCollEntityEmbId.class}; + return new Class[] {EmbIdTestEntity.class, SetRefCollEntityEmbId.class, EmbId.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java index 3403a7538e65..87ade4f7efdb 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java @@ -33,12 +33,14 @@ import org.hibernate.envers.test.entities.ids.MulIdTestEntity; import org.hibernate.envers.test.entities.onetomany.detached.ids.SetRefCollEntityMulId; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055 : Association with an entity with @IdClass is broken." ) public class BasicDetachedSetWithMulId extends BaseEnversJPAFunctionalTestCase { private MulId str1_id; private MulId str2_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/inverseToSuperclass/OneToManyInverseToSuperclassTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/inverseToSuperclass/OneToManyInverseToSuperclassTest.java index 68daa683797b..68d8673b405a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/inverseToSuperclass/OneToManyInverseToSuperclassTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/inverseToSuperclass/OneToManyInverseToSuperclassTest.java @@ -5,13 +5,14 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Hern�n Chanfreau */ - +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class OneToManyInverseToSuperclassTest extends BaseEnversJPAFunctionalTestCase { private long m1_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/BidirectionalEagerHbmTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/BidirectionalEagerHbmTest.java index 1b5d29d38123..7f9b8c12a492 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/BidirectionalEagerHbmTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/BidirectionalEagerHbmTest.java @@ -32,6 +32,7 @@ import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; import static org.junit.Assert.assertNotNull; @@ -40,6 +41,7 @@ * @author Erik-Berndt Scheper, Amar Singh */ @TestForIssue(jiraKey = "HHH-3854") +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class BidirectionalEagerHbmTest extends BaseEnversJPAFunctionalTestCase { private Long refIngId1 = null; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java index b713c870567c..abd622e7edd3 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java @@ -43,7 +43,7 @@ public class EmbIdBidirectional extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {BiEmbIdRefEdEntity.class, BiEmbIdRefIngEntity.class}; + return new Class[] {BiEmbIdRefEdEntity.class, BiEmbIdRefIngEntity.class, EmbId.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java index da1087c79ce3..5be610fc9cb1 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java @@ -29,12 +29,14 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.ids.MulId; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Adam Warski (adam at warski dot org) */ +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055 : Association with an entity with @IdClass is broken." ) public class MulIdBidirectional extends BaseEnversJPAFunctionalTestCase { private MulId ed1_id; private MulId ed2_id; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/unidirectional/UnidirectionalMulIdWithNulls.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/unidirectional/UnidirectionalMulIdWithNulls.java index 8d6bb63ca860..d1b14b45e2e4 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/unidirectional/UnidirectionalMulIdWithNulls.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetoone/unidirectional/UnidirectionalMulIdWithNulls.java @@ -21,7 +21,7 @@ public class UnidirectionalMulIdWithNulls extends BaseEnversJPAFunctionalTestCas @Override protected Class[] getAnnotatedClasses() { - return new Class[] {EmbIdTestEntity.class, UniRefIngMulIdEntity.class}; + return new Class[] {EmbIdTestEntity.class, UniRefIngMulIdEntity.class, EmbId.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/properties/UnversionedOptimisticLockingField.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/properties/UnversionedOptimisticLockingField.java index 655d1f2dc076..3f2c59f5e580 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/properties/UnversionedOptimisticLockingField.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/properties/UnversionedOptimisticLockingField.java @@ -31,8 +31,7 @@ import org.hibernate.envers.configuration.EnversSettings; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.junit.Test; @@ -92,11 +91,7 @@ assert getAuditReader().find( UnversionedOptimisticLockingFieldEntity.class, id1 @Test public void testMapping() { - PersistentClass pc = getCfg().getClassMapping( UnversionedOptimisticLockingFieldEntity.class.getName() + "_AUD" ); - Iterator pi = pc.getPropertyIterator(); - while ( pi.hasNext() ) { - Property p = (Property) pi.next(); - assert !"optLocking".equals( p.getName() ); - } + EntityBinding entityBinding = getMetadata().getEntityBinding( UnversionedOptimisticLockingFieldEntity.class.getName() + "_AUD" ); + assert entityBinding.locateAttributeBinding( "optLocking" ) == null; } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/ProxyIdentifier.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/ProxyIdentifier.java index c3b73ca6f5e8..5134cd13c3d8 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/ProxyIdentifier.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/ProxyIdentifier.java @@ -32,11 +32,13 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.UnversionedStrTestEntity; import org.hibernate.envers.test.entities.manytomany.unidirectional.ManyToManyNotAuditedNullEntity; +import org.hibernate.envers.test.entities.manytoone.unidirectional.ExtManyToOneNotAuditedNullEntity; import org.hibernate.envers.test.entities.manytoone.unidirectional.ManyToOneNotAuditedNullEntity; import org.hibernate.envers.test.entities.manytoone.unidirectional.TargetNotAuditedEntity; import org.hibernate.envers.test.entities.onetomany.OneToManyNotAuditedNullEntity; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** @@ -45,6 +47,7 @@ public class ProxyIdentifier extends BaseEnversJPAFunctionalTestCase { private TargetNotAuditedEntity tnae1 = null; private ManyToOneNotAuditedNullEntity mtonane1 = null; + private ExtManyToOneNotAuditedNullEntity emtonane1 = null; private ManyToManyNotAuditedNullEntity mtmnane1 = null; private OneToManyNotAuditedNullEntity otmnane1 = null; private UnversionedStrTestEntity uste1 = null; @@ -54,7 +57,8 @@ public class ProxyIdentifier extends BaseEnversJPAFunctionalTestCase { protected Class[] getAnnotatedClasses() { return new Class[] { TargetNotAuditedEntity.class, ManyToOneNotAuditedNullEntity.class, UnversionedStrTestEntity.class, - ManyToManyNotAuditedNullEntity.class, OneToManyNotAuditedNullEntity.class + ManyToManyNotAuditedNullEntity.class, OneToManyNotAuditedNullEntity.class, + ExtManyToOneNotAuditedNullEntity.class }; } @@ -87,9 +91,11 @@ public void initData() { mtmnane1.getReferences().add( uste2 ); otmnane1 = new OneToManyNotAuditedNullEntity( 4, "otmnane1" ); otmnane1.getReferences().add( uste2 ); + emtonane1 = new ExtManyToOneNotAuditedNullEntity( 5, "emtonane1", uste2, "extension" ); em.persist( mtonane1 ); em.persist( mtmnane1 ); em.persist( otmnane1 ); + em.persist( emtonane1 ); em.getTransaction().commit(); em.clear(); @@ -107,6 +113,9 @@ public void initData() { OneToManyNotAuditedNullEntity tmp3 = em.find( OneToManyNotAuditedNullEntity.class, otmnane1.getId() ); tmp3.setReferences( null ); tmp3 = em.merge( tmp3 ); + ExtManyToOneNotAuditedNullEntity tmp4 = em.find( ExtManyToOneNotAuditedNullEntity.class, emtonane1.getId() ); + tmp4.setReference( null ); + tmp4 = em.merge( tmp4 ); em.remove( em.getReference( UnversionedStrTestEntity.class, uste2.getId() ) ); em.getTransaction().commit(); @@ -147,4 +156,12 @@ public void testNullReferenceWithNotFoundActionIgnore() { Assert.assertEquals( otmnane1, otmRev2 ); Assert.assertTrue( otmRev2.getReferences().isEmpty() ); } + + @Test + @TestForIssue( jiraKey = "HHH-8912" ) + public void testNullReferenceWithNotFoundActionIgnoreInParent() { + ExtManyToOneNotAuditedNullEntity emtoRev2 = getAuditReader().find( ExtManyToOneNotAuditedNullEntity.class, emtonane1.getId(), 2 ); + Assert.assertEquals( emtonane1, emtoRev2 ); + Assert.assertNull( emtoRev2.getReference() ); + } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/QueryingWithProxyObjectTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/QueryingWithProxyObjectTest.java index c411e8225634..4d57480dbd3d 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/QueryingWithProxyObjectTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/QueryingWithProxyObjectTest.java @@ -10,6 +10,7 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/RemovedObjectQueryTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/RemovedObjectQueryTest.java index 3f862afae9fc..c4ad36919ee6 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/RemovedObjectQueryTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/proxy/RemovedObjectQueryTest.java @@ -33,12 +33,14 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-5845") +@FailureExpectedWithNewMetamodel( message = "@MapKeyJoinColumn is not supported yet" ) public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase { private Integer stringSetId = null; private Integer ternaryMapId = null; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/NullPropertyQuery.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/NullPropertyQuery.java index 1e146e7b471e..d0a3de6b52c6 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/NullPropertyQuery.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/NullPropertyQuery.java @@ -31,7 +31,8 @@ protected Class[] getAnnotatedClasses() { SetRefEdEmbIdEntity.class, SetRefIngEmbIdEntity.class, CollectionRefEdEntity.class, - CollectionRefIngEntity.class + CollectionRefIngEntity.class, + EmbId.class }; } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java index f2dd4ff8121b..030d65a1ea14 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java @@ -59,7 +59,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { StrIntTestEntity.class, MulIdTestEntity.class, EmbIdTestEntity.class }; + return new Class[] { StrIntTestEntity.class, MulIdTestEntity.class, EmbIdTestEntity.class, EmbId.class }; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/EmbIdOneToManyQuery.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/EmbIdOneToManyQuery.java index 2e53bf689f33..0a2f3171092c 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/EmbIdOneToManyQuery.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/EmbIdOneToManyQuery.java @@ -51,7 +51,7 @@ public class EmbIdOneToManyQuery extends BaseEnversJPAFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {SetRefEdEmbIdEntity.class, SetRefIngEmbIdEntity.class}; + return new Class[] {SetRefEdEmbIdEntity.class, SetRefIngEmbIdEntity.class, EmbId.class}; } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/MulIdOneToManyQuery.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/MulIdOneToManyQuery.java index f3c58669b0c8..93813f2a8fe6 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/MulIdOneToManyQuery.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/ids/MulIdOneToManyQuery.java @@ -35,6 +35,7 @@ import org.hibernate.envers.test.entities.onetomany.ids.SetRefEdMulIdEntity; import org.hibernate.envers.test.entities.onetomany.ids.SetRefIngMulIdEntity; import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; @@ -44,6 +45,7 @@ * @author Adam Warski (adam at warski dot org) */ @SuppressWarnings({"unchecked"}) +@FailureExpectedWithNewMetamodel( jiraKey = "HHH-9055 : Association with an entity with @IdClass is broken." ) public class MulIdOneToManyQuery extends BaseEnversJPAFunctionalTestCase { private MulId id1; private MulId id2; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/DifferentDBSchemaTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/DifferentDBSchemaTest.java index 96b90a80d10c..d5c2882d64d6 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/DifferentDBSchemaTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/DifferentDBSchemaTest.java @@ -10,10 +10,10 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrTestEntity; -import org.hibernate.mapping.Table; import org.junit.Test; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.testing.RequiresDialect; /** @@ -65,9 +65,9 @@ public void initData() throws InterruptedException { @Test public void testRevinfoSchemaName() { - Table revisionTable = getCfg().getClassMapping( "org.hibernate.envers.enhanced.SequenceIdRevisionEntity" ) - .getTable(); - assert SCHEMA_NAME.equals( revisionTable.getSchema() ); + TableSpecification revisionTable = getMetadata().getEntityBinding( "org.hibernate.envers.enhanced.SequenceIdRevisionEntity" ) + .getPrimaryTable(); + assert SCHEMA_NAME.equals( revisionTable.getSchema().getName().getSchema().getText() ); } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevEntityInheritanceChildAuditing.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevEntityInheritanceChildAuditing.java index c73030cd11d5..3970f481a80f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevEntityInheritanceChildAuditing.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevEntityInheritanceChildAuditing.java @@ -29,7 +29,7 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.integration.inheritance.joined.ChildEntity; import org.hibernate.envers.test.integration.inheritance.joined.ParentEntity; -import org.hibernate.mapping.Column; +import org.hibernate.metamodel.spi.relational.Value; import org.junit.Test; @@ -50,13 +50,12 @@ protected Class[] getAnnotatedClasses() { @Test public void testChildRevColumnType() { // We need the second column - Iterator childEntityKeyColumnsIterator = getCfg() - .getClassMapping( "org.hibernate.envers.test.integration.inheritance.joined.ChildEntity_AUD" ) - .getKey() - .getColumnIterator(); + Iterator childEntityKeyColumnsIterator = getMetadata() + .getEntityBinding( "org.hibernate.envers.test.integration.inheritance.joined.ChildEntity_AUD" ) + .getHierarchyDetails().getEntityIdentifier().getAttributeBinding().getValues().iterator(); childEntityKeyColumnsIterator.next(); - Column second = (Column) childEntityKeyColumnsIterator.next(); + Value second = (Value) childEntityKeyColumnsIterator.next(); - assertEquals( second.getSqlType(), "int" ); + assertEquals( second.getJdbcDataType().getTypeName(), "int" ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java index 4f73a6699f16..0833c8e96f62 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java @@ -1,7 +1,6 @@ package org.hibernate.envers.test.integration.reventity.trackmodifiedentities; import javax.persistence.EntityManager; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -14,8 +13,8 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.tools.TestTools; import org.hibernate.envers.tools.Pair; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.junit.Test; @@ -73,14 +72,14 @@ public void initData() { @Test public void testRevEntityTableCreation() { - Iterator
    tableIterator = getCfg().getTableMappings(); - while ( tableIterator.hasNext() ) { - Table table = tableIterator.next(); - if ( "REVCHANGES".equals( table.getName() ) ) { - assert table.getColumnSpan() == 2; - assert table.getColumn( new Column( "REV" ) ) != null; - assert table.getColumn( new Column( "ENTITYNAME" ) ) != null; - return; + for ( Schema schema : getMetadata().getDatabase().getSchemas() ) { + for ( TableSpecification table : schema.getTables() ) { + if ( "REVCHANGES".equals( table.getLogicalName().getText() ) ) { + assert table.values().size() == 2; + assert table.locateColumn( "REV" ) != null; + assert table.locateColumn( "ENTITYNAME" ) != null; + return; + } } } assert false; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/EntityNamesTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/EntityNamesTest.java index 703fe1b19f43..fd38e0838662 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/EntityNamesTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/EntityNamesTest.java @@ -11,12 +11,14 @@ import org.hibernate.envers.test.integration.entityNames.manyToManyAudited.Person; import org.hibernate.envers.test.tools.TestTools; import org.hibernate.envers.tools.Pair; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Test; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ +@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." ) public class EntityNamesTest extends BaseEnversFunctionalTestCase { @Override protected String[] getMappings() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/BasicSecondary.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/BasicSecondary.java index f09bf20823e6..f9440e4b7c70 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/BasicSecondary.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/BasicSecondary.java @@ -29,7 +29,8 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Join; +import org.hibernate.metamodel.spi.binding.SecondaryTable; +import org.hibernate.metamodel.spi.relational.Identifier; import org.junit.Test; @@ -89,12 +90,11 @@ public void testHistoryOfId() { @Test public void testTableNames() { assert "secondary_AUD".equals( - ((Iterator) - getCfg().getClassMapping( + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.secondary.SecondaryTestEntity_AUD" ) - .getJoinIterator()) - .next().getTable().getName() + .getSecondaryTables().values().iterator().next() + .getSecondaryTableReference().getLogicalName().getText() ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/NamingSecondary.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/NamingSecondary.java index 34122b1a8f65..43c5b559376a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/NamingSecondary.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/NamingSecondary.java @@ -25,11 +25,9 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Join; import org.junit.Test; @@ -89,12 +87,10 @@ public void testHistoryOfId() { @Test public void testTableNames() { assert "sec_versions".equals( - ((Iterator) - getCfg().getClassMapping( + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.secondary.SecondaryNamingTestEntity_AUD" ) - .getJoinIterator()) - .next().getTable().getName() + .getSecondaryTables().keySet().iterator().next().getText() ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/EmbIdSecondary.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/EmbIdSecondary.java index add9e2dba717..91da2adbfb76 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/EmbIdSecondary.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/EmbIdSecondary.java @@ -25,12 +25,10 @@ import javax.persistence.EntityManager; import java.util.Arrays; -import java.util.Iterator; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.ids.EmbId; -import org.hibernate.mapping.Join; import org.junit.Test; @@ -88,12 +86,10 @@ public void testHistoryOfId() { @Test public void testTableNames() { assert "sec_embid_versions".equals( - ((Iterator) - getCfg().getClassMapping( + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.secondary.ids.SecondaryEmbIdTestEntity_AUD" ) - .getJoinIterator()) - .next().getTable().getName() + .getSecondaryTables().keySet().iterator().next().getText() ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/MulIdSecondary.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/MulIdSecondary.java index 897eb0314955..2ac4775680fd 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/MulIdSecondary.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/secondary/ids/MulIdSecondary.java @@ -88,12 +88,10 @@ public void testHistoryOfId() { @Test public void testTableNames() { assert "sec_mulid_versions".equals( - ((Iterator) - getCfg().getClassMapping( + getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.secondary.ids.SecondaryMulIdTestEntity_AUD" ) - .getJoinIterator()) - .next().getTable().getName() + .getSecondaryTables().keySet().iterator().next().getText() ); } } \ No newline at end of file diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditClassOverrideTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditClassOverrideTest.java index 2d9a2cb15921..0f2ed23ae8c5 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditClassOverrideTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditClassOverrideTest.java @@ -4,12 +4,12 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; import org.junit.Assert; import org.junit.Test; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** @@ -19,8 +19,8 @@ public class AuditClassOverrideTest extends BaseEnversJPAFunctionalTestCase { private Integer classAuditedEntityId = null; private Integer classNotAuditedEntityId = null; - private Table classAuditedTable = null; - private Table classNotAuditedTable = null; + private TableSpecification classAuditedTable = null; + private TableSpecification classNotAuditedTable = null; @Override protected Class[] getAnnotatedClasses() { @@ -50,26 +50,26 @@ public void initData() { em.getTransaction().commit(); classNotAuditedEntityId = classOverrideNotAuditedEntity.getId(); - classAuditedTable = getCfg().getClassMapping( + classAuditedTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditoverride.ClassOverrideAuditedEntity_AUD" - ).getTable(); - classNotAuditedTable = getCfg().getClassMapping( + ).getPrimaryTable(); + classNotAuditedTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditoverride.ClassOverrideNotAuditedEntity_AUD" - ).getTable(); + ).getPrimaryTable(); } @Test public void testAuditedProperty() { - Assert.assertNotNull( classAuditedTable.getColumn( new Column( "number1" ) ) ); - Assert.assertNotNull( classAuditedTable.getColumn( new Column( "str1" ) ) ); - Assert.assertNotNull( classAuditedTable.getColumn( new Column( "str2" ) ) ); - Assert.assertNotNull( classNotAuditedTable.getColumn( new Column( "str2" ) ) ); + Assert.assertNotNull( classAuditedTable.locateColumn( "number1" ) ); + Assert.assertNotNull( classAuditedTable.locateColumn( "str1" ) ); + Assert.assertNotNull( classAuditedTable.locateColumn( "str2" ) ); + Assert.assertNotNull( classNotAuditedTable.locateColumn( "str2" ) ); } @Test public void testNotAuditedProperty() { - Assert.assertNull( classNotAuditedTable.getColumn( new Column( "number1" ) ) ); - Assert.assertNull( classNotAuditedTable.getColumn( new Column( "str1" ) ) ); + Assert.assertNull( classNotAuditedTable.locateColumn( "number1" ) ); + Assert.assertNull( classNotAuditedTable.locateColumn( "str1" ) ); } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditPropertyOverrideTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditPropertyOverrideTest.java index 4ee096fb9249..8b569fe05640 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditPropertyOverrideTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/AuditPropertyOverrideTest.java @@ -4,25 +4,26 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; import org.junit.Assert; import org.junit.Test; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-4439") +@FailureExpectedWithNewMetamodel( message = "Audit overrides on MappedSuperclasses not supported yet.") public class AuditPropertyOverrideTest extends BaseEnversJPAFunctionalTestCase { private Integer propertyEntityId = null; private Integer transitiveEntityId = null; private Integer auditedEntityId = null; - private Table propertyTable = null; - private Table transitiveTable = null; - private Table auditedTable = null; + private TableSpecification propertyTable = null; + private TableSpecification transitiveTable = null; + private TableSpecification auditedTable = null; @Override protected Class[] getAnnotatedClasses() { @@ -55,33 +56,33 @@ public void initData() { em.getTransaction().commit(); auditedEntityId = auditedEntity.getId(); - propertyTable = getCfg().getClassMapping( + propertyTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditoverride.PropertyOverrideEntity_AUD" - ).getTable(); - transitiveTable = getCfg().getClassMapping( + ).getPrimaryTable(); + transitiveTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditoverride.TransitiveOverrideEntity_AUD" - ).getTable(); - auditedTable = getCfg().getClassMapping( + ).getPrimaryTable(); + auditedTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditoverride.AuditedSpecialEntity_AUD" - ).getTable(); + ).getPrimaryTable(); } @Test public void testNotAuditedProperty() { - Assert.assertNull( propertyTable.getColumn( new Column( "str1" ) ) ); + Assert.assertNull( propertyTable.locateColumn( "str1" ) ); } @Test public void testAuditedProperty() { - Assert.assertNotNull( propertyTable.getColumn( new Column( "number1" ) ) ); - Assert.assertNotNull( transitiveTable.getColumn( new Column( "number2" ) ) ); - Assert.assertNotNull( auditedTable.getColumn( new Column( "str1" ) ) ); + Assert.assertNotNull( propertyTable.locateColumn( "number1" ) ); + Assert.assertNotNull( transitiveTable.locateColumn( "number2" ) ); + Assert.assertNotNull( auditedTable.locateColumn( "str1" ) ); } @Test public void testTransitiveAuditedProperty() { - Assert.assertNotNull( transitiveTable.getColumn( new Column( "number1" ) ) ); - Assert.assertNotNull( transitiveTable.getColumn( new Column( "str1" ) ) ); + Assert.assertNotNull( transitiveTable.locateColumn( "number1" ) ); + Assert.assertNotNull( transitiveTable.locateColumn( "str1" ) ); } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideEntity.java index e3f6e20d8e34..d60b0cd12bec 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideEntity.java @@ -5,6 +5,7 @@ import org.hibernate.envers.AuditOverride; import org.hibernate.envers.AuditOverrides; import org.hibernate.envers.Audited; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideTest.java index 169d0afb68b8..71831931da70 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditoverride/MixedOverrideTest.java @@ -4,21 +4,22 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; import org.junit.Assert; import org.junit.Test; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @TestForIssue(jiraKey = "HHH-4439") +@FailureExpectedWithNewMetamodel( message = "Audit overrides on MappedSuperclasses not supported yet.") public class MixedOverrideTest extends BaseEnversJPAFunctionalTestCase { private Integer mixedEntityId = null; - private Table mixedTable = null; + private TableSpecification mixedTable = null; @Override protected Class[] getAnnotatedClasses() { @@ -37,20 +38,20 @@ public void initData() { em.getTransaction().commit(); mixedEntityId = mixedEntity.getId(); - mixedTable = getCfg().getClassMapping( + mixedTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditoverride.MixedOverrideEntity_AUD" - ).getTable(); + ).getPrimaryTable(); } @Test public void testAuditedProperty() { - Assert.assertNotNull( mixedTable.getColumn( new Column( "number1" ) ) ); - Assert.assertNotNull( mixedTable.getColumn( new Column( "str2" ) ) ); + Assert.assertNotNull( mixedTable.locateColumn( "number1" ) ); + Assert.assertNotNull( mixedTable.locateColumn( "str2" ) ); } @Test public void testNotAuditedProperty() { - Assert.assertNull( mixedTable.getColumn( new Column( "str1" ) ) ); + Assert.assertNull( mixedTable.locateColumn( "str1" ) ); } @Test diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MultipleAuditParentsTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MultipleAuditParentsTest.java index 760190bd94a4..08a5400e3e5d 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MultipleAuditParentsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MultipleAuditParentsTest.java @@ -9,8 +9,8 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrIntTestEntity; import org.hibernate.envers.test.tools.TestTools; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Assert; import org.junit.Test; @@ -62,17 +62,17 @@ public void testCreatedAuditTable() { Set expectedColumns = TestTools.makeSet( "child", "parent", "relation_id", "grandparent", "id" ); Set unexpectedColumns = TestTools.makeSet( "notAudited" ); - Table table = getCfg().getClassMapping( + TableSpecification table = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditparents.ChildMultipleParentsEntity_AUD" - ).getTable(); + ).getPrimaryTable(); for ( String columnName : expectedColumns ) { // Check whether expected column exists. - Assert.assertNotNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNotNull( table.locateColumn( columnName ) ); } for ( String columnName : unexpectedColumns ) { // Check whether unexpected column does not exist. - Assert.assertNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNull( table.locateColumn( columnName ) ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/SingleAuditParentsTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/SingleAuditParentsTest.java index 57e7c38ba659..8733f85cd90e 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/SingleAuditParentsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/SingleAuditParentsTest.java @@ -9,8 +9,8 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrIntTestEntity; import org.hibernate.envers.test.tools.TestTools; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Assert; import org.junit.Test; @@ -63,17 +63,17 @@ public void testCreatedAuditTable() { Set expectedColumns = TestTools.makeSet( "child", "grandparent", "id" ); Set unexpectedColumns = TestTools.makeSet( "parent", "relation_id", "notAudited" ); - Table table = getCfg().getClassMapping( + TableSpecification table = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditparents.ChildSingleParentEntity_AUD" - ).getTable(); + ).getPrimaryTable(); for ( String columnName : expectedColumns ) { // Check whether expected column exists. - Assert.assertNotNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNotNull( table.locateColumn( columnName ) ); } for ( String columnName : unexpectedColumns ) { // Check whether unexpected column does not exist. - Assert.assertNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNull( table.locateColumn( columnName ) ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TotalAuditParentsTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TotalAuditParentsTest.java index 5c58a455bcd3..2d61a5b7cdf3 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TotalAuditParentsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TotalAuditParentsTest.java @@ -8,8 +8,8 @@ import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrIntTestEntity; import org.hibernate.envers.test.tools.TestTools; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Assert; import org.junit.Test; @@ -71,17 +71,17 @@ public void testCreatedAuditTable() { ); Set unexpectedColumns = TestTools.makeSet( "notAudited" ); - Table table = getCfg().getClassMapping( + TableSpecification table = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditparents.BabyCompleteEntity_AUD" - ).getTable(); + ).getPrimaryTable(); for ( String columnName : expectedColumns ) { // Check whether expected column exists. - Assert.assertNotNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNotNull( table.locateColumn( columnName ) ); } for ( String columnName : unexpectedColumns ) { // Check whether unexpected column does not exist. - Assert.assertNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNull( table.locateColumn(columnName ) ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveAuditParentsTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveAuditParentsTest.java index c6add0fe2d56..ca23562b0d43 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveAuditParentsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveAuditParentsTest.java @@ -7,8 +7,8 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.tools.TestTools; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Table; +import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.junit.Assert; import org.junit.Test; @@ -67,18 +67,18 @@ public void initData() { @Test public void testCreatedAuditTables() { - Table explicitTransChildTable = getCfg().getClassMapping( + TableSpecification explicitTransChildTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditparents.ExplicitTransitiveChildEntity_AUD" - ).getTable(); + ).getPrimaryTable(); checkTableColumns( TestTools.makeSet( "child", "parent", "grandparent", "id" ), TestTools.makeSet( "notAudited" ), explicitTransChildTable ); - Table implicitTransChildTable = getCfg().getClassMapping( + TableSpecification implicitTransChildTable = getMetadata().getEntityBinding( "org.hibernate.envers.test.integration.superclass.auditparents.ImplicitTransitiveChildEntity_AUD" - ).getTable(); + ).getPrimaryTable(); checkTableColumns( TestTools.makeSet( "child", "parent", "grandparent", "id" ), TestTools.makeSet( "notAudited" ), @@ -86,14 +86,14 @@ public void testCreatedAuditTables() { ); } - private void checkTableColumns(Set expectedColumns, Set unexpectedColumns, Table table) { + private void checkTableColumns(Set expectedColumns, Set unexpectedColumns, TableSpecification table) { for ( String columnName : expectedColumns ) { // Check whether expected column exists. - Assert.assertNotNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNotNull( table.locateColumn( columnName ) ); } for ( String columnName : unexpectedColumns ) { // Check whether unexpected column does not exist. - Assert.assertNull( table.getColumn( new Column( columnName ) ) ); + Assert.assertNull( table.locateColumn( columnName ) ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/tools/SchemaExportTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/tools/SchemaExportTest.java index 791ee9980185..8bb888098e19 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/tools/SchemaExportTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/tools/SchemaExportTest.java @@ -11,6 +11,7 @@ import org.junit.Assert; import org.junit.Test; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.TestForIssue; /** @@ -34,7 +35,7 @@ protected boolean createSchema() { @Priority(10) public void testSchemaCreation() { // Generate complete schema. - new EnversSchemaGenerator( configuration() ).export().create( true, true ); + new EnversSchemaGenerator( metadata() ).export().create( true, true ); // Populate database with test data. Session session = getSession(); @@ -56,6 +57,6 @@ public void testAuditDataRetrieval() { @Test @Priority(8) public void testSchemaDrop() { - new EnversSchemaGenerator( configuration() ).export().drop( true, true ); + new EnversSchemaGenerator( metadata() ).export().drop( true, true ); } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/TestTools.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/TestTools.java index 429df8c5f776..3e74f10baa27 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/TestTools.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/TestTools.java @@ -36,6 +36,8 @@ import org.hibernate.envers.enhanced.SequenceIdRevisionEntity; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; /** * @author Adam Warski (adam at warski dot org) @@ -84,16 +86,14 @@ public static List extractRevisionNumbers(List queryResults) { return result; } - public static Set extractModProperties(PersistentClass persistentClass) { - return extractModProperties( persistentClass, "_MOD" ); + public static Set extractModProperties(EntityBinding entityBinding) { + return extractModProperties( entityBinding, "_MOD" ); } - public static Set extractModProperties(PersistentClass persistentClass, String suffix) { + public static Set extractModProperties(EntityBinding entityBinding, String suffix) { final Set result = new HashSet(); - final Iterator iterator = persistentClass.getPropertyIterator(); - while ( iterator.hasNext() ) { - final Property property = (Property) iterator.next(); - final String propertyName = property.getName(); + for ( AttributeBinding property : entityBinding.attributeBindings() ) { + final String propertyName = property.getAttribute().getName(); if ( propertyName.endsWith( suffix ) ) { result.add( propertyName ); } diff --git a/hibernate-hikaricp/hibernate-hikaricp.gradle b/hibernate-hikaricp/hibernate-hikaricp.gradle new file mode 100644 index 000000000000..84090ce4a3e4 --- /dev/null +++ b/hibernate-hikaricp/hibernate-hikaricp.gradle @@ -0,0 +1,17 @@ +dependencies { + compile project( ':hibernate-core' ) + compile( libraries.hikaricp ) + testCompile project( ':hibernate-testing' ) +} + +def pomName() { + return 'Hibernate/HikariCP Integration' +} + +def pomDescription() { + return 'Integration for HikariCP into Hibernate O/RM' +} + +def osgiDescription() { + return pomDescription() +} diff --git a/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java new file mode 100644 index 000000000000..e3dd64220252 --- /dev/null +++ b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java @@ -0,0 +1,131 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +package org.hibernate.hikaricp.internal; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.service.UnknownUnwrapTypeException; +import org.hibernate.service.spi.Configurable; +import org.hibernate.service.spi.Stoppable; +import org.jboss.logging.Logger; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +/** + * HikariCP Connection provider for Hibernate. + * + * @author Brett Wooldridge + * @author Luca Burgazzoli + */ +public class HikariCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable { + + private static final long serialVersionUID = -9131625057941275711L; + + private static final Logger LOGGER = Logger.getLogger( HikariCPConnectionProvider.class ); + + /** + * HikariCP configuration. + */ + private HikariConfig hcfg = null; + + /** + * HikariCP data source. + */ + private HikariDataSource hds = null; + + // ************************************************************************* + // Configurable + // ************************************************************************* + + @SuppressWarnings("rawtypes") + @Override + public void configure(Map props) throws HibernateException { + try { + LOGGER.debug( "Configuring HikariCP" ); + + hcfg = HikariConfigurationUtil.loadConfiguration( props ); + hds = new HikariDataSource( hcfg ); + + } + catch (Exception e) { + throw new HibernateException( e ); + } + + LOGGER.debug( "HikariCP Configured" ); + } + + // ************************************************************************* + // ConnectionProvider + // ************************************************************************* + + @Override + public Connection getConnection() throws SQLException { + Connection conn = null; + if ( hds != null ) { + conn = hds.getConnection(); + } + + return conn; + } + + @Override + public void closeConnection(Connection conn) throws SQLException { + conn.close(); + } + + @Override + public boolean supportsAggressiveRelease() { + return false; + } + + @Override + @SuppressWarnings("rawtypes") + public boolean isUnwrappableAs(Class unwrapType) { + return ConnectionProvider.class.equals( unwrapType ) + || HikariCPConnectionProvider.class.isAssignableFrom( unwrapType ); + } + + @Override + @SuppressWarnings("unchecked") + public T unwrap(Class unwrapType) { + if ( isUnwrappableAs( unwrapType ) ) { + return (T) this; + } + else { + throw new UnknownUnwrapTypeException( unwrapType ); + } + } + + // ************************************************************************* + // Stoppable + // ************************************************************************* + + @Override + public void stop() { + hds.shutdown(); + } +} diff --git a/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariConfigurationUtil.java b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariConfigurationUtil.java new file mode 100644 index 000000000000..a145724a28fb --- /dev/null +++ b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariConfigurationUtil.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +package org.hibernate.hikaricp.internal; + +import java.util.Map; +import java.util.Properties; + +import org.hibernate.cfg.AvailableSettings; + +import com.zaxxer.hikari.HikariConfig; + +/** + * Utility class to map Hibernate properties to HikariCP configuration properties. + * + * @author Brett Wooldridge + * @author Luca Burgazzoli + * @author Brett Meyer + */ +public class HikariConfigurationUtil { + + public static final String CONFIG_PREFIX = "hibernate.hikari."; + + /** + * Create/load a HikariConfig from Hibernate properties. + * + * @param props a map of Hibernate properties + * @return a HikariConfig + */ + @SuppressWarnings("rawtypes") + public static HikariConfig loadConfiguration(Map props) { + Properties hikariProps = new Properties(); + copyProperty( AvailableSettings.ISOLATION, props, "transactionIsolation", hikariProps ); + copyProperty( AvailableSettings.AUTOCOMMIT, props, "autoCommit", hikariProps ); + + copyProperty(AvailableSettings.DRIVER, props, "driverClassName", hikariProps); + copyProperty(AvailableSettings.URL, props, "jdbcUrl", hikariProps); + copyProperty( AvailableSettings.USER, props, "username", hikariProps ); + copyProperty( AvailableSettings.PASS, props, "password", hikariProps ); + + for ( Object keyo : props.keySet() ) { + String key = (String) keyo; + if ( key.startsWith( CONFIG_PREFIX ) ) { + hikariProps.setProperty( key.substring( CONFIG_PREFIX.length() ), (String) props.get( key ) ); + } + } + + return new HikariConfig( hikariProps ); + } + + @SuppressWarnings("rawtypes") + private static void copyProperty(String srcKey, Map src, String dstKey, Properties dst) { + if ( src.containsKey( srcKey ) ) { + dst.setProperty( dstKey, (String) src.get( srcKey ) ); + } + } +} diff --git a/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/StrategyRegistrationProviderImpl.java b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/StrategyRegistrationProviderImpl.java new file mode 100644 index 000000000000..b9fbb9be050c --- /dev/null +++ b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/StrategyRegistrationProviderImpl.java @@ -0,0 +1,58 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.hikaricp.internal; + +import java.util.Collections; +import java.util.List; + +import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl; +import org.hibernate.boot.registry.selector.StrategyRegistration; +import org.hibernate.boot.registry.selector.StrategyRegistrationProvider; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; + +/** + * Provides the {@link HikariCPConnectionProvider} to the + * {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service. + * + * @author Brett Meyer + */ +public class StrategyRegistrationProviderImpl implements StrategyRegistrationProvider { + private static final List REGISTRATIONS = Collections.singletonList( + (StrategyRegistration) new SimpleStrategyRegistrationImpl( + ConnectionProvider.class, + HikariCPConnectionProvider.class, + "hikari", + "hikaricp", + HikariCPConnectionProvider.class.getSimpleName(), + // for consistency's sake + "org.hibernate.connection.HikariCPConnectionProvider" + ) + ); + + @Override + @SuppressWarnings("unchecked") + public Iterable getStrategyRegistrations() { + return REGISTRATIONS; + } +} diff --git a/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/package-info.java b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/package-info.java new file mode 100644 index 000000000000..ed2b12f239c4 --- /dev/null +++ b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/package-info.java @@ -0,0 +1,4 @@ +/** + * Implementation of ConnectionProvider using HikariCP. + */ +package org.hibernate.hikaricp.internal; diff --git a/hibernate-hikaricp/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider b/hibernate-hikaricp/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider new file mode 100644 index 000000000000..b4a1509a772a --- /dev/null +++ b/hibernate-hikaricp/src/main/resources/META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider @@ -0,0 +1 @@ +org.hibernate.hikaricp.internal.StrategyRegistrationProviderImpl diff --git a/hibernate-hikaricp/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/hibernate-hikaricp/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000000..163905773e31 --- /dev/null +++ b/hibernate-hikaricp/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPConnectionProviderTest.java b/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPConnectionProviderTest.java new file mode 100644 index 000000000000..22a2e56d1b4f --- /dev/null +++ b/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPConnectionProviderTest.java @@ -0,0 +1,90 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.hikaricp; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.hikaricp.internal.HikariCPConnectionProvider; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +/** + * @author Brett Meyer + */ +public class HikariCPConnectionProviderTest extends BaseCoreFunctionalTestCase { + + @Test + public void testHikariCPConnectionProvider() throws Exception { + JdbcServices jdbcServices = serviceRegistry().getService( JdbcServices.class ); + ConnectionProvider provider = jdbcServices.getConnectionProvider(); + assertTrue( provider instanceof HikariCPConnectionProvider ); + + HikariCPConnectionProvider hikariCP = (HikariCPConnectionProvider) provider; + // For simplicity's sake, using the following in hibernate.properties: + // hibernate.hikari.minimumPoolSize 2 + // hibernate.hikari.maximumPoolSize 2 + final List conns = new ArrayList(); + for ( int i = 0; i < 2; i++ ) { + Connection conn = hikariCP.getConnection(); + assertNotNull( conn ); + assertFalse( conn.isClosed() ); + conns.add( conn ); + } + + try { + hikariCP.getConnection(); + fail( "SQLException expected -- no more connections should have been available in the pool." ); + } + catch (SQLException e) { + // expected + assertTrue( e.getMessage().contains( "Timeout" ) ); + } + + for ( Connection conn : conns ) { + hikariCP.closeConnection( conn ); + assertTrue( conn.isClosed() ); + } + + releaseSessionFactory(); + + try { + hikariCP.getConnection(); + fail( "Exception expected -- the pool should have been shutdown." ); + } + catch (Exception e) { + // expected + assertTrue( e.getMessage().contains( "shutdown" ) ); + } + } +} diff --git a/hibernate-hikaricp/src/test/resources/hibernate.properties b/hibernate-hikaricp/src/test/resources/hibernate.properties new file mode 100644 index 000000000000..49c8ccfb37f3 --- /dev/null +++ b/hibernate-hikaricp/src/test/resources/hibernate.properties @@ -0,0 +1,35 @@ +# +# Hibernate, Relational Persistence for Idiomatic Java +# +# Copyright (c) 2010, Red Hat Inc. or third-party contributors as +# indicated by the @author tags or express copyright attribution +# statements applied by the authors. All third-party contributions are +# distributed under license by Red Hat Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# Lesser General Public License, as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this distribution; if not, write to: +# Free Software Foundation, Inc. +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301 USA +# +hibernate.dialect org.hibernate.dialect.H2Dialect +hibernate.connection.driver_class org.h2.Driver +hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE +hibernate.connection.username sa + +hibernate.jdbc.batch_size 10 +hibernate.connection.provider_class HikariCPConnectionProvider + +hibernate.hikari.poolName testPool +# Purposefully low and simplisitic. +hibernate.hikari.maximumPoolSize 2 +hibernate.hikari.idleTimeout 3000 \ No newline at end of file diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java index 2d2fe5666a92..f0115efb298c 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTestCase.java @@ -23,18 +23,19 @@ */ package org.hibernate.test.cache.infinispan.functional.cluster; -import org.infinispan.util.logging.Log; -import org.infinispan.util.logging.LogFactory; -import org.junit.After; -import org.junit.Before; - +import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; -import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; +import org.junit.After; +import org.junit.Before; /** * @author Galder Zamarreño @@ -149,12 +150,13 @@ public SecondNodeEnvironment() { configuration.setProperty( NODE_ID_PROP, REMOTE ); configuration.setProperty( NODE_ID_FIELD, REMOTE ); configureSecondNode( configuration ); - addMappings(configuration); - configuration.buildMappings(); - applyCacheSettings( configuration ); afterConfigurationBuilt( configuration ); serviceRegistry = buildServiceRegistry( buildBootstrapServiceRegistry(), configuration ); - sessionFactory = (SessionFactoryImplementor) configuration.buildSessionFactory( serviceRegistry ); + MetadataSources sources = new MetadataSources( serviceRegistry.getParentServiceRegistry() ); + addMappings( sources ); + MetadataImplementor metadata = (MetadataImplementor) sources.getMetadataBuilder( serviceRegistry ).build(); + applyCacheSettings( metadata ); + sessionFactory = (SessionFactoryImplementor) metadata.buildSessionFactory(); } public Configuration getConfiguration() { diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/PutFromLoadStressTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/PutFromLoadStressTestCase.java index 50b1c6be4168..7423d4d150e4 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/PutFromLoadStressTestCase.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/PutFromLoadStressTestCase.java @@ -1,13 +1,34 @@ package org.hibernate.test.cache.infinispan.stress; +import static org.infinispan.test.TestingUtil.withTx; +import static org.junit.Assert.assertFalse; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.transaction.TransactionManager; + import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.TruthValue; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; -import org.hibernate.cfg.Configuration; +import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.test.cache.infinispan.functional.Age; import org.hibernate.testing.ServiceRegistryBuilder; import org.infinispan.util.logging.Log; @@ -17,21 +38,6 @@ import org.junit.Ignore; import org.junit.Test; -import javax.transaction.TransactionManager; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.infinispan.test.TestingUtil.withTx; -import static org.junit.Assert.*; - /** * A stress test for putFromLoad operations * @@ -55,70 +61,68 @@ public class PutFromLoadStressTestCase { final AtomicBoolean run = new AtomicBoolean(true); - @BeforeClass - public static void beforeClass() { - Configuration cfg = new Configuration(); - cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); - cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); - // TODO: Tweak to have a fully local region factory (no transport, cache mode = local, no marshalling, ...etc) - cfg.setProperty(Environment.CACHE_REGION_FACTORY, - "org.hibernate.cache.infinispan.InfinispanRegionFactory"); - cfg.setProperty(Environment.JTA_PLATFORM, - "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"); - - // Force minimal puts off to simplify stressing putFromLoad logic - cfg.setProperty(Environment.USE_MINIMAL_PUTS, "false"); - - // Mappings - configureMappings(cfg); - -// // Database settings -// cfg.setProperty(Environment.DRIVER, "org.postgresql.Driver"); -// cfg.setProperty(Environment.URL, "jdbc:postgresql://localhost/hibernate"); -// cfg.setProperty(Environment.DIALECT, "org.hibernate.dialect.PostgreSQL82Dialect"); -// cfg.setProperty(Environment.USER, "hbadmin"); -// cfg.setProperty(Environment.PASS, "hbadmin"); - - // Create database schema in each run - cfg.setProperty(Environment.HBM2DDL_AUTO, "create-drop"); - - StandardServiceRegistryImpl registry = - ServiceRegistryBuilder.buildServiceRegistry(cfg.getProperties()); - sessionFactory = cfg.buildSessionFactory(registry); - - tm = com.arjuna.ats.jta.TransactionManager.transactionManager(); - } - - private static void configureMappings(Configuration cfg) { - String[] mappings = { - "cache/infinispan/functional/Item.hbm.xml", - "cache/infinispan/functional/Customer.hbm.xml", - "cache/infinispan/functional/Contact.hbm.xml"}; - for (String mapping : mappings) - cfg.addResource("org/hibernate/test/" + mapping); - - Class[] annotatedClasses = getAnnotatedClasses(); - if ( annotatedClasses != null ) { - for ( Class annotatedClass : annotatedClasses ) { - cfg.addAnnotatedClass( annotatedClass ); - } - } - - cfg.buildMappings(); - Iterator it = cfg.getClassMappings(); - String cacheStrategy = "transactional"; - while (it.hasNext()) { - PersistentClass clazz = (PersistentClass) it.next(); - if (!clazz.isInherited()) { - cfg.setCacheConcurrencyStrategy(clazz.getEntityName(), cacheStrategy); - } - } - it = cfg.getCollectionMappings(); - while (it.hasNext()) { - Collection coll = (Collection) it.next(); - cfg.setCollectionCacheConcurrencyStrategy( coll.getRole(), cacheStrategy); - } - } + @BeforeClass + public static void beforeClass() { + Properties envProps = Environment.getProperties(); + envProps.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" ); + envProps.setProperty( Environment.USE_QUERY_CACHE, "true" ); + // TODO: Tweak to have a fully local region factory (no transport, cache mode = local, no marshalling, ...etc) + envProps.setProperty( Environment.CACHE_REGION_FACTORY, "org.hibernate.cache.infinispan.InfinispanRegionFactory" ); + envProps.setProperty( Environment.JTA_PLATFORM, "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform" ); + + // Force minimal puts off to simplify stressing putFromLoad logic + envProps.setProperty( Environment.USE_MINIMAL_PUTS, "false" ); + + // Create database schema in each run + envProps.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); + + // // Database settings + // envProps.setProperty(Environment.DRIVER, "org.postgresql.Driver"); + // envProps.setProperty(Environment.URL, "jdbc:postgresql://localhost/hibernate"); + // envProps.setProperty(Environment.DIALECT, "org.hibernate.dialect.PostgreSQL82Dialect"); + // envProps.setProperty(Environment.USER, "hbadmin"); + // envProps.setProperty(Environment.PASS, "hbadmin"); + + StandardServiceRegistryImpl registry = ServiceRegistryBuilder.buildServiceRegistry(envProps); + MetadataSources sources = new MetadataSources( registry ); + + // Mappings + String[] mappings = { "cache/infinispan/functional/Item.hbm.xml", "cache/infinispan/functional/Customer.hbm.xml", + "cache/infinispan/functional/Contact.hbm.xml" }; + for ( String mapping : mappings ) + sources.addResource( "org/hibernate/test/" + mapping ); + + Class[] annotatedClasses = getAnnotatedClasses(); + if ( annotatedClasses != null ) { + for ( Class annotatedClass : annotatedClasses ) { + sources.addAnnotatedClass( annotatedClass ); + } + } + + Metadata metadata = sources.buildMetadata(); + + Iterator entityIter = metadata.getEntityBindings().iterator(); + while ( entityIter.hasNext() ) { + EntityBinding binding = entityIter.next(); + binding.getHierarchyDetails().getCaching().setAccessType( AccessType.TRANSACTIONAL ); + binding.getHierarchyDetails().getCaching().setRequested( TruthValue.TRUE ); + binding.getHierarchyDetails().getCaching().setRegion( binding.getEntityName() ); + binding.getHierarchyDetails().getCaching().setCacheLazyProperties( true ); + } + Iterator collectionIter = metadata.getCollectionBindings().iterator(); + while ( collectionIter.hasNext() ) { + PluralAttributeBinding binding = collectionIter.next(); + binding.getCaching().setAccessType( AccessType.TRANSACTIONAL ); + binding.getCaching().setRequested( TruthValue.TRUE ); + binding.getCaching() + .setRegion( StringHelper.qualify( binding.getContainer().seekEntityBinding().getEntityName(), binding.getAttribute().getName() ) ); + binding.getCaching().setCacheLazyProperties( true ); + } + + sessionFactory = metadata.buildSessionFactory(); + + tm = com.arjuna.ats.jta.TransactionManager.transactionManager(); + } @AfterClass public static void afterClass() { diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/SecondLevelCacheStressTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/SecondLevelCacheStressTestCase.java index caca545e0b19..915e758051af 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/SecondLevelCacheStressTestCase.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/stress/SecondLevelCacheStressTestCase.java @@ -23,15 +23,44 @@ package org.hibernate.test.cache.infinispan.stress; +import static org.infinispan.test.TestingUtil.withTx; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Queue; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +import javax.transaction.TransactionManager; + import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.TruthValue; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; import org.hibernate.cache.infinispan.InfinispanRegionFactory; -import org.hibernate.cfg.Configuration; +import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; import org.hibernate.test.cache.infinispan.stress.entities.Address; import org.hibernate.test.cache.infinispan.stress.entities.Family; import org.hibernate.test.cache.infinispan.stress.entities.Person; @@ -42,21 +71,6 @@ import org.junit.Ignore; import org.junit.Test; -import javax.transaction.TransactionManager; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Random; -import java.util.concurrent.*; - -import static org.infinispan.test.TestingUtil.withTx; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - /** * Stress test for second level cache. * @@ -94,27 +108,57 @@ public void beforeClass() { updatedIds = new ConcurrentHashSet(); removeIds = new ConcurrentLinkedQueue(); - Configuration cfg = new Configuration(); - cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); - cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); - configureCache(cfg); - - // Mappings - configureMappings(cfg); + Properties envProps = Environment.getProperties(); + envProps.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); + envProps.setProperty(Environment.USE_QUERY_CACHE, "true"); + envProps.setProperty(Environment.CACHE_REGION_FACTORY, + "org.hibernate.cache.infinispan.InfinispanRegionFactory"); + envProps.setProperty(Environment.JTA_PLATFORM, + "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"); + envProps.setProperty(InfinispanRegionFactory.INFINISPAN_CONFIG_RESOURCE_PROP, + "stress-local-infinispan.xml"); // Database settings - cfg.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver"); - cfg.setProperty(Environment.URL, "jdbc:mysql://localhost:3306/hibernate"); - cfg.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQL5InnoDBDialect"); - cfg.setProperty(Environment.USER, "root"); - cfg.setProperty(Environment.PASS, "password"); + envProps.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver"); + envProps.setProperty(Environment.URL, "jdbc:mysql://localhost:3306/hibernate"); + envProps.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQL5InnoDBDialect"); + envProps.setProperty(Environment.USER, "root"); + envProps.setProperty(Environment.PASS, "password"); // Create database schema in each run - cfg.setProperty(Environment.HBM2DDL_AUTO, "create-drop"); + envProps.setProperty(Environment.HBM2DDL_AUTO, "create-drop"); - StandardServiceRegistryImpl registry = - ServiceRegistryBuilder.buildServiceRegistry(cfg.getProperties()); - sessionFactory = cfg.buildSessionFactory(registry); + StandardServiceRegistryImpl registry = ServiceRegistryBuilder.buildServiceRegistry(envProps); + MetadataSources sources = new MetadataSources( registry ); + + Class[] annotatedClasses = getAnnotatedClasses(); + if ( annotatedClasses != null ) { + for ( Class annotatedClass : annotatedClasses ) { + sources.addAnnotatedClass( annotatedClass ); + } + } + + Metadata metadata = sources.buildMetadata(); + + Iterator entityIter = metadata.getEntityBindings().iterator(); + while (entityIter.hasNext()) { + EntityBinding binding = entityIter.next(); + binding.getHierarchyDetails().getCaching().setAccessType( AccessType.TRANSACTIONAL ); + binding.getHierarchyDetails().getCaching().setRequested( TruthValue.TRUE ); + binding.getHierarchyDetails().getCaching().setRegion( binding.getEntityName() ); + binding.getHierarchyDetails().getCaching().setCacheLazyProperties( true ); + } + Iterator collectionIter = metadata.getCollectionBindings().iterator(); + while (collectionIter.hasNext()) { + PluralAttributeBinding binding = collectionIter.next(); + binding.getCaching().setAccessType( AccessType.TRANSACTIONAL ); + binding.getCaching().setRequested( TruthValue.TRUE ); + binding.getCaching().setRegion( StringHelper.qualify( + binding.getContainer().seekEntityBinding().getEntityName(), binding.getAttribute().getName() ) ); + binding.getCaching().setCacheLazyProperties( true ); + } + + sessionFactory = metadata.buildSessionFactory(); tm = com.arjuna.ats.jta.TransactionManager.transactionManager(); } @@ -123,15 +167,6 @@ protected String getProvider() { return "infinispan"; } - protected void configureCache(Configuration cfg) { - cfg.setProperty(Environment.CACHE_REGION_FACTORY, - "org.hibernate.cache.infinispan.InfinispanRegionFactory"); - cfg.setProperty(Environment.JTA_PLATFORM, - "org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"); - cfg.setProperty(InfinispanRegionFactory.INFINISPAN_CONFIG_RESOURCE_PROP, - "stress-local-infinispan.xml"); - } - @After public void afterClass() { sessionFactory.close(); @@ -461,30 +496,6 @@ public static Class[] getAnnotatedClasses() { return new Class[] {Family.class, Person.class, Address.class}; } - private static void configureMappings(Configuration cfg) { - Class[] annotatedClasses = getAnnotatedClasses(); - if ( annotatedClasses != null ) { - for ( Class annotatedClass : annotatedClasses ) { - cfg.addAnnotatedClass( annotatedClass ); - } - } - - cfg.buildMappings(); - Iterator it = cfg.getClassMappings(); - String cacheStrategy = "transactional"; - while (it.hasNext()) { - PersistentClass clazz = (PersistentClass) it.next(); - if (!clazz.isInherited()) { - cfg.setCacheConcurrencyStrategy(clazz.getEntityName(), cacheStrategy); - } - } - it = cfg.getCollectionMappings(); - while (it.hasNext()) { - Collection coll = (Collection) it.next(); - cfg.setCollectionCacheConcurrencyStrategy(coll.getRole(), cacheStrategy); - } - } - private static abstract class Operation { final String name; diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java index e43b8cabe526..fb616c892caa 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java @@ -23,8 +23,12 @@ */ package org.hibernate.test.cache.infinispan.tm; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + import java.util.Iterator; import java.util.Properties; + import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; @@ -34,6 +38,23 @@ import javax.transaction.Status; import javax.transaction.UserTransaction; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.TruthValue; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Environment; +import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.metamodel.spi.binding.PluralAttributeBinding; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.stat.Statistics; +import org.hibernate.test.cache.infinispan.functional.Item; +import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.testing.jta.JtaAwareConnectionProviderImpl; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup; import org.infinispan.util.logging.Log; @@ -46,23 +67,6 @@ import org.junit.Before; import org.junit.Test; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform; -import org.hibernate.stat.Statistics; -import org.hibernate.test.cache.infinispan.functional.Item; -import org.hibernate.testing.ServiceRegistryBuilder; -import org.hibernate.testing.jta.JtaAwareConnectionProviderImpl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - /** * This is an example test based on http://community.jboss.org/docs/DOC-14617 that shows how to interact with * Hibernate configured with Infinispan second level cache provider using JTA transactions. @@ -241,39 +245,46 @@ private void unbind(String jndiName, Context ctx) throws Exception { } private SessionFactory buildSessionFactory() { - // Extra options located in src/test/resources/hibernate.properties - Configuration cfg = new Configuration(); - cfg.setProperty( Environment.DIALECT, "HSQL" ); - cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); - cfg.setProperty( Environment.CONNECTION_PROVIDER, JtaAwareConnectionProviderImpl.class.getName() ); - cfg.setProperty(Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory"); - cfg.setProperty(Environment.TRANSACTION_STRATEGY, "jta"); - cfg.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, "jta"); - cfg.setProperty(Environment.RELEASE_CONNECTIONS, "auto"); - cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); - cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); - - Properties envProps = Environment.getProperties(); + // Extra options located in src/test/resources/hibernate.properties + Properties envProps = Environment.getProperties(); + envProps.setProperty( Environment.DIALECT, "HSQL" ); + envProps.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); + envProps.setProperty( Environment.CONNECTION_PROVIDER, JtaAwareConnectionProviderImpl.class.getName() ); + envProps.setProperty(Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory"); + envProps.setProperty(Environment.TRANSACTION_STRATEGY, "jta"); + envProps.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, "jta"); + envProps.setProperty(Environment.RELEASE_CONNECTIONS, "auto"); + envProps.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); + envProps.setProperty(Environment.USE_QUERY_CACHE, "true"); envProps.put(AvailableSettings.JTA_PLATFORM, new JBossStandAloneJtaPlatform()); envProps.setProperty(Environment.CACHE_REGION_FACTORY, "org.hibernate.test.cache.infinispan.functional.SingleNodeTestCase$TestInfinispanRegionFactory"); serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry(envProps); + + MetadataSources sources = new MetadataSources( serviceRegistry ); String[] mappings = new String[]{"org/hibernate/test/cache/infinispan/functional/Item.hbm.xml"}; for (String mapping : mappings) { - cfg.addResource(mapping, Thread.currentThread().getContextClassLoader()); + sources.addResource(mapping); } - cfg.buildMappings(); - Iterator iter = cfg.getClassMappings(); - while (iter.hasNext()) { - PersistentClass clazz = (PersistentClass) iter.next(); - cfg.setCacheConcurrencyStrategy(clazz.getEntityName(), "transactional"); + Metadata metadata = sources.buildMetadata(); + Iterator entityIter = metadata.getEntityBindings().iterator(); + while (entityIter.hasNext()) { + EntityBinding binding = entityIter.next(); + binding.getHierarchyDetails().getCaching().setAccessType( AccessType.TRANSACTIONAL ); + binding.getHierarchyDetails().getCaching().setRequested( TruthValue.TRUE ); + binding.getHierarchyDetails().getCaching().setRegion( binding.getEntityName() ); + binding.getHierarchyDetails().getCaching().setCacheLazyProperties( true ); } - iter = cfg.getCollectionMappings(); - while (iter.hasNext()) { - Collection coll = (Collection) iter.next(); - cfg.setCollectionCacheConcurrencyStrategy(coll.getRole(), "transactional"); + Iterator collectionIter = metadata.getCollectionBindings().iterator(); + while (collectionIter.hasNext()) { + PluralAttributeBinding binding = collectionIter.next(); + binding.getCaching().setAccessType( AccessType.TRANSACTIONAL ); + binding.getCaching().setRequested( TruthValue.TRUE ); + binding.getCaching().setRegion( StringHelper.qualify( + binding.getContainer().seekEntityBinding().getEntityName(), binding.getAttribute().getName() ) ); + binding.getCaching().setCacheLazyProperties( true ); } - return cfg.buildSessionFactory( serviceRegistry ); + return metadata.buildSessionFactory(); } } diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java index 7803dbcec77a..fdc368935da4 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java @@ -30,6 +30,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Settings; +import org.hibernate.cfg.SettingsFactory; import org.hibernate.service.ServiceRegistry; import org.hibernate.test.cache.infinispan.functional.SingleNodeTestCase; @@ -64,8 +65,8 @@ public static Configuration buildCustomQueryCacheConfiguration(String regionPref public static InfinispanRegionFactory startRegionFactory(ServiceRegistry reg, Configuration cfg){ try { - Settings settings = cfg.buildSettings(reg); Properties properties = cfg.getProperties(); + Settings settings = new SettingsFactory().buildSettings( properties, reg ); String factoryType = cfg.getProperty(Environment.CACHE_REGION_FACTORY); Class clazz = Thread.currentThread() diff --git a/hibernate-osgi/hibernate-osgi.gradle b/hibernate-osgi/hibernate-osgi.gradle index 4854d7fad58c..62d066dee9d4 100644 --- a/hibernate-osgi/hibernate-osgi.gradle +++ b/hibernate-osgi/hibernate-osgi.gradle @@ -4,18 +4,12 @@ configurations { } sourceSets { - testResult testClientBundle } sourceSets.test { - compileClasspath += sourceSets.testResult.output - runtimeClasspath += sourceSets.testResult.output -} - -sourceSets.testClientBundle { - compileClasspath += sourceSets.testResult.output - runtimeClasspath += sourceSets.testResult.output + compileClasspath += sourceSets.testClientBundle.output + runtimeClasspath += sourceSets.testClientBundle.output } dependencies { @@ -133,7 +127,7 @@ task felixProperties << { } task testClientBundleJar(type: Jar) { - from sourceSets.testClientBundle.output, sourceSets.testResult.output + from sourceSets.testClientBundle.output destinationDir new File("$buildDir/osgi-lib") archiveName "testClientBundle.jar" diff --git a/hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiClassLoader.java b/hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiClassLoader.java index 5f0d6a2ff7b1..cc7a672b73f9 100644 --- a/hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiClassLoader.java +++ b/hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiClassLoader.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -46,8 +46,8 @@ public class OsgiClassLoader extends ClassLoader implements Stoppable { // Leave these as Sets -- addClassLoader or addBundle may be called more // than once if a SF or EMF is closed and re-created. - private Set classLoaders = new HashSet(); - private Set bundles = new HashSet(); + private Set classLoaders = new LinkedHashSet(); + private Set bundles = new LinkedHashSet(); private Map> classCache = new HashMap>(); private Map resourceCache = new HashMap(); diff --git a/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiTestCase.java b/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiTestCase.java index 5914be28fcc4..c97127c51d70 100644 --- a/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiTestCase.java +++ b/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiTestCase.java @@ -19,13 +19,18 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; +import static org.junit.Assert.assertTrue; import java.io.InputStream; +import org.hibernate.Hibernate; +import org.hibernate.boot.registry.selector.StrategyRegistrationProvider; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.spi.TypeContributor; import org.hibernate.osgi.OsgiPersistenceProviderService; import org.hibernate.osgi.OsgiSessionFactoryService; -import org.hibernate.osgi.test.result.OsgiTestResults; +import org.hibernate.osgi.test.client.DataPoint; +import org.hibernate.osgi.test.client.TestService; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.InSequence; @@ -41,21 +46,15 @@ import org.osgi.framework.ServiceReference; /** - * A separate sourceset, testClientBundle, contains a persistence unit and multiple uses of Native and JPA functionality. - * Any failures that occur are logged in the OsgiTestResult service, contained in another sourceset (testResult). - * - * The "unit tests" MUST reside in testClientBundle, rather than attempting to programmatically create a bundle and obtain an SF/EMF here. There are + * A separate sourceset, testClientBundle, contains a persistence unit and an OSGi service interface providing + * multiple uses of Native and JPA functionality. The use of a SF/EMF must occur in that separate bundle, rather than + * attempting to programmatically create a bundle and obtain/use an SF/EMF here. There are * MANY ClassLoader issues with that sort of setup. JPA annotations are "stripped", since one ClassLoader is used here * to create the entity's stream and another is used to parse it within core. Further, the entire Felix framework * is given to hibernate-osgi as the "requestingBundle" in that setup, regardless of Arquillian vs. Pax Exam. That * causes another slew of ClassLoader issues as well. * - * It is also important to keep OsgiTestResult in a third sourceset, rather than attempting to put it in test or - * testClientBundle. Adding testClientBundle to test's classpath causes more ClassLoader issues during runtime (and - * vice versa), similar to the above. - * - * The bottom line is that many, many alternatives were prototyped and all of them eventually hit brick walls. - * Regardless, this is the most "realistic" type of test anyway with a *real* client bundle. + * This is the most "realistic" type of test anyway with a *real* client bundle. * * IMPORTANT: There are a few maintenance points that need addressed for new versions of Hibernate and library upgrades: * 1.) Updated library versions in hibernate-osgi.gradle. libraries.gradle is used wherever possible. But, there @@ -71,8 +70,8 @@ * stripped of the javax.transaction nonsense. This may need to be repeated if Felix is ever updated in ORM * (should be rare). * - * This should largerly be considered an integration test, rather than a granular unit test. Depending on how you setup - * the source directories and classpaths, this may not work in your IDE. + * This should largerly be considered an integration test, rather than a granular unit test. Also, this is almost + * guaranteed to not work in your IDE. * * @author Brett Meyer */ @@ -97,8 +96,12 @@ public InputStream openStream() { final OSGiManifestBuilder builder = OSGiManifestBuilder.newInstance(); builder.addBundleSymbolicName( archive.getName() ); builder.addBundleManifestVersion( 2 ); - builder.addImportPackages( OsgiTestResults.class ); - // needed primarily to test service cleanup in #testStop + builder.addImportPackages( TestService.class ); + // ORM packages needed in the tests + builder.addImportPackages( Hibernate.class ); + builder.addImportPackages( Integrator.class ); + builder.addImportPackages( StrategyRegistrationProvider.class ); + builder.addImportPackages( TypeContributor.class ); builder.addImportPackages( OsgiSessionFactoryService.class ); return builder.openStream(); } @@ -121,13 +124,97 @@ public void testClientBundle() throws Exception { assertNotNull( "The test client bundle was not found!", testClientBundle ); testClientBundle.start(); assertEquals( "The test client bundle was not activated!", Bundle.ACTIVE, testClientBundle.getState() ); + } + + @Test + @InSequence(2) + public void testJpa() throws Exception { + commonTests(); - final ServiceReference serviceReference = context.getServiceReference( OsgiTestResults.class.getName() ); - final OsgiTestResults testResults = (OsgiTestResults) context.getService( serviceReference ); + final TestService testService = getTestService(); + + DataPoint dp = new DataPoint(); + dp.setName( "Brett" ); + testService.saveJpa( dp ); - if ( testResults.getFailures().size() > 0 ) { - fail( testResults.getFailures().get( 0 ).getFailure() ); - } + dp = testService.getJpa(dp.getId()); + assertNotNull( dp ); + assertEquals( "Brett", dp.getName() ); + + dp.setName( "Brett2" ); + testService.updateJpa( dp ); + + dp = testService.getJpa(dp.getId()); + assertNotNull( dp ); + assertEquals( "Brett2", dp.getName() ); + + testService.deleteJpa(); + + dp = testService.getJpa(dp.getId()); + assertNull( dp ); + } + + @Test + @InSequence(2) + public void testNative() throws Exception { + commonTests(); + + final TestService testService = getTestService(); + + DataPoint dp = new DataPoint(); + dp.setName( "Brett" ); + testService.saveNative( dp ); + + dp = testService.getNative(dp.getId()); + assertNotNull( dp ); + assertEquals( "Brett", dp.getName() ); + + dp.setName( "Brett2" ); + testService.updateNative( dp ); + + dp = testService.getNative(dp.getId()); + assertNotNull( dp ); + assertEquals( "Brett2", dp.getName() ); + + testService.deleteNative(); + + dp = testService.getNative(dp.getId()); + assertNull( dp ); + } + + @Test + @InSequence(2) + public void testLazyLoading() throws Exception { + commonTests(); + + final TestService testService = getTestService(); + + DataPoint dp = new DataPoint(); + dp.setName( "Brett" ); + testService.saveNative( dp ); + + // #lazyLoad will init dp on its own + dp = testService.lazyLoad( dp.getId() ); + assertNotNull( dp ); + assertTrue( Hibernate.isInitialized( dp ) ); + assertEquals( "Brett", dp.getName() ); + } + + @Test + @InSequence(2) + public void testExtensionPoints() throws Exception { + commonTests(); + + final TestService testService = getTestService(); + + assertNotNull( testService.getTestIntegrator() ); + assertTrue( testService.getTestIntegrator().passed() ); + + assertNotNull( testService.getTestStrategyRegistrationProvider() ); + assertTrue( testService.getTestStrategyRegistrationProvider().passed() ); + + assertNotNull( testService.getTestTypeContributor() ); + assertTrue( testService.getTestTypeContributor().passed() ); } /** @@ -140,7 +227,7 @@ public void testClientBundle() throws Exception { @Test // Arquillian does not restart the container between runs (afaik). Without the ordering, the tests will // intermittently fail since this method stops the bundle. - @InSequence(2) + @InSequence(3) public void testStop() throws Exception { commonTests(); @@ -175,4 +262,9 @@ private void testHibernateBundle(String symbolicName, int state) { assertNotNull( "Bundle " + symbolicName + " was not found!", bundle ); assertEquals( "Bundle " + symbolicName + " was not in the expected state!", state, bundle.getState() ); } + + private TestService getTestService() { + final ServiceReference serviceReference = context.getServiceReference( TestService.class.getName() ); + return (TestService) context.getService( serviceReference ); + } } diff --git a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/OsgiTestActivator.java b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/OsgiTestActivator.java index a02f35b290ac..98bc774ae8bf 100644 --- a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/OsgiTestActivator.java +++ b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/OsgiTestActivator.java @@ -21,54 +21,35 @@ package org.hibernate.osgi.test.client; import java.util.Hashtable; -import java.util.List; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.spi.PersistenceProvider; - -import org.hibernate.Session; -import org.hibernate.SessionFactory; import org.hibernate.boot.registry.selector.StrategyRegistrationProvider; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; import org.hibernate.metamodel.spi.TypeContributor; -import org.hibernate.osgi.test.result.OsgiTestResults; -import org.hibernate.osgi.test.result.OsgiTestResultsImpl; -import org.hibernate.service.ServiceRegistry; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; /** - * This is a BundleActivate for the testClientBundle, but realistically it's the actual unit test. See the note on - * OsgiTestCase. - * * @author Brett Meyer */ public class OsgiTestActivator implements BundleActivator { - private OsgiTestResults testResult = new OsgiTestResultsImpl(); - - private TestIntegrator integrator = new TestIntegrator(); - private TestStrategyRegistrationProvider strategyRegistrationProvider = new TestStrategyRegistrationProvider(); - private TestTypeContributor typeContributor = new TestTypeContributor(); + private TestService testService; @Override public void start(BundleContext context) throws Exception { - - // register the test result service - context.registerService( OsgiTestResults.class, testResult, new Hashtable() ); + + final TestIntegrator integrator = new TestIntegrator(); + final TestStrategyRegistrationProvider strategyRegistrationProvider = new TestStrategyRegistrationProvider(); + final TestTypeContributor typeContributor = new TestTypeContributor(); // register example extension point services context.registerService( Integrator.class, integrator, new Hashtable() ); context.registerService( StrategyRegistrationProvider.class, strategyRegistrationProvider, new Hashtable() ); context.registerService( TypeContributor.class, typeContributor, new Hashtable() ); - testUnmanagedJpa( context ); - testUnmanagedNative( context ); - testLazyLoading( context ); - testExtensionPoints( context ); + // register the test result service + testService = new TestServiceImpl(context, integrator, strategyRegistrationProvider, typeContributor); + context.registerService( TestService.class, testService, new Hashtable() ); } @Override @@ -76,156 +57,4 @@ public void stop(BundleContext context) throws Exception { } - private void testUnmanagedJpa(BundleContext context) { - try { - final ServiceReference serviceReference = context.getServiceReference( PersistenceProvider.class.getName() ); - final PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService( serviceReference ); - final EntityManagerFactory emf = persistenceProvider.createEntityManagerFactory( "hibernate-osgi-test", null ); - final EntityManager em = emf.createEntityManager(); - - DataPoint dp = new DataPoint(); - dp.setName( "Brett" ); - em.getTransaction().begin(); - em.persist( dp ); - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - List results = em.createQuery( "from DataPoint" ).getResultList(); - if ( results.size() == 0 || !results.get( 0 ).getName().equals( "Brett" ) ) { - testResult.addFailure( "Unmanaged JPA: Unexpected data returned!" ); - } - dp = results.get( 0 ); - dp.setName( "Brett2" ); - em.merge( dp ); - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - results = em.createQuery( "from DataPoint" ).getResultList(); - if ( results.size() == 0 || !results.get( 0 ).getName().equals( "Brett2" ) ) { - testResult.addFailure( "Unmanaged JPA: The update/merge failed!" ); - } - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - em.createQuery( "delete from DataPoint" ).executeUpdate(); - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - results = em.createQuery( "from DataPoint" ).getResultList(); - if ( results.size() > 0 ) { - testResult.addFailure( "Unmanaged JPA: The delete failed!" ); - } - em.getTransaction().commit(); - em.close(); - } - catch ( Exception e ) { - testResult.addFailure( "Exception: " + e.getMessage(), e ); - } - } - - private void testUnmanagedNative(BundleContext context) { - try { - final ServiceReference sr = context.getServiceReference( SessionFactory.class.getName() ); - final SessionFactory sf = (SessionFactory) context.getService( sr ); - final Session s = sf.openSession(); - - DataPoint dp = new DataPoint(); - dp.setName( "Brett" ); - s.getTransaction().begin(); - s.persist( dp ); - s.getTransaction().commit(); - s.clear(); - - s.getTransaction().begin(); - List results = s.createQuery( "from DataPoint" ).list(); - if ( results.size() == 0 || !results.get( 0 ).getName().equals( "Brett" ) ) { - testResult.addFailure( "Native Hibernate: Unexpected data returned!" ); - } - dp = results.get( 0 ); - dp.setName( "Brett2" ); - s.update( dp ); - s.getTransaction().commit(); - s.clear(); - - s.getTransaction().begin(); - results = s.createQuery( "from DataPoint" ).list(); - if ( results.size() == 0 || !results.get( 0 ).getName().equals( "Brett2" ) ) { - testResult.addFailure( "Native Hibernate: The update/merge failed!" ); - } - s.getTransaction().commit(); - s.clear(); - - s.getTransaction().begin(); - s.createQuery( "delete from DataPoint" ).executeUpdate(); - s.getTransaction().commit(); - s.clear(); - - s.getTransaction().begin(); - results = s.createQuery( "from DataPoint" ).list(); - if ( results.size() > 0 ) { - testResult.addFailure( "Native Hibernate: The delete failed!" ); - } - s.getTransaction().commit(); - s.close(); - } - catch ( Exception e ) { - testResult.addFailure( "Exception: " + e.getMessage(), e ); - } - } - - private void testLazyLoading(BundleContext context) { - try { - final ServiceReference sr = context.getServiceReference( SessionFactory.class.getName() ); - final SessionFactory sf = (SessionFactory) context.getService( sr ); - final Session s = sf.openSession(); - - DataPoint dp = new DataPoint(); - dp.setName( "Brett" ); - s.getTransaction().begin(); - s.persist( dp ); - s.getTransaction().commit(); - s.clear(); - - s.getTransaction().begin(); - // ensure the proxy comes through ok - dp = (DataPoint) s.load( DataPoint.class, new Long( dp.getId() ) ); - // initialize and test - if ( dp == null || !dp.getName().equals( "Brett" ) ) { - testResult.addFailure( "Native Hibernate: Lazy loading/proxy failed!" ); - } - s.getTransaction().commit(); - s.close(); - } - catch ( Exception e ) { - testResult.addFailure( "Exception: " + e.getMessage(), e ); - } - } - - private void testExtensionPoints(BundleContext context) { - try { - final ServiceReference serviceReference = context.getServiceReference( SessionFactory.class.getName() ); - final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) context.getService( - serviceReference ); - final ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry(); - - // test extension points in the client bundle - if (!integrator.passed) { - testResult.addFailure( "Could not discover " + integrator.getClass() ); - } - if (!strategyRegistrationProvider.passed) { - testResult.addFailure( "Could not discover " + strategyRegistrationProvider.getClass() ); - } - if (!typeContributor.passed) { - testResult.addFailure( "Could not discover " + typeContributor.getClass() ); - } - } - catch ( Exception e ) { - testResult.addFailure( "Exception: " + e.getMessage(), e ); - } - } - } diff --git a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestIntegrator.java b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestIntegrator.java index deadfca0fb05..6938690548ad 100644 --- a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestIntegrator.java +++ b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestIntegrator.java @@ -23,7 +23,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; @@ -32,7 +32,7 @@ */ public class TestIntegrator implements Integrator { - public boolean passed = false; + private boolean passed = false; public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { passed = true; @@ -45,5 +45,9 @@ public void integrate(MetadataImplementor metadata, SessionFactoryImplementor se public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { passed = true; } + + public boolean passed() { + return passed; + } } diff --git a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestService.java b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestService.java new file mode 100644 index 000000000000..3d430ca7c8a1 --- /dev/null +++ b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestService.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.osgi.test.client; + + + +/** + * OSGi service interface providing multiple uses of Native and JPA functionality. The use of a SF/EMF must occur in + * this separate bundle, rather than attempting to programmatically create a bundle and obtain/use an SF/EMF there. + * See comments on OsgiTestCase + * + * @author Brett Meyer + */ +public interface TestService { + public void saveJpa(DataPoint dp); + + public DataPoint getJpa(long id); + + public void updateJpa(DataPoint dp); + + public void deleteJpa(); + + public void saveNative(DataPoint dp); + + public DataPoint getNative(long id); + + public void updateNative(DataPoint dp); + + public void deleteNative(); + + public DataPoint lazyLoad(long id); + + public TestIntegrator getTestIntegrator(); + + public TestStrategyRegistrationProvider getTestStrategyRegistrationProvider(); + + public TestTypeContributor getTestTypeContributor(); +} diff --git a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestServiceImpl.java b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestServiceImpl.java new file mode 100644 index 000000000000..d10c29e0036a --- /dev/null +++ b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestServiceImpl.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.osgi.test.client; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.spi.PersistenceProvider; + +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + + +/** + * @author Brett Meyer + */ +public class TestServiceImpl implements TestService { + + private final EntityManagerFactory emf; + + private final SessionFactory sf; + + private final TestIntegrator testIntegrator; + + private final TestStrategyRegistrationProvider testStrategyRegistrationProvider; + + private final TestTypeContributor testTypeContributor; + + public TestServiceImpl(BundleContext context, TestIntegrator testIntegrator, + TestStrategyRegistrationProvider testStrategyRegistrationProvider, TestTypeContributor testTypeContributor) { + final ServiceReference serviceReference = context.getServiceReference( PersistenceProvider.class.getName() ); + final PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService( serviceReference ); + emf = persistenceProvider.createEntityManagerFactory( "hibernate-osgi-test", null ); + + final ServiceReference sr = context.getServiceReference( SessionFactory.class.getName() ); + sf = (SessionFactory) context.getService( sr ); + + this.testIntegrator = testIntegrator; + this.testStrategyRegistrationProvider = testStrategyRegistrationProvider; + this.testTypeContributor = testTypeContributor; + } + + public void saveJpa(DataPoint dp) { + final EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist( dp ); + em.getTransaction().commit(); + em.close(); + } + + public DataPoint getJpa(long id) { + final EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + DataPoint dp = em.find(DataPoint.class, id); + em.getTransaction().commit(); + em.close(); + return dp; + } + + public void updateJpa(DataPoint dp) { + final EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.merge( dp ); + em.getTransaction().commit(); + em.close(); + } + + public void deleteJpa() { + final EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete from DataPoint" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } + + public void saveNative(DataPoint dp) { + final Session s = sf.openSession(); + s.getTransaction().begin(); + s.persist( dp ); + s.getTransaction().commit(); + s.close(); + } + + public DataPoint getNative(long id) { + final Session s = sf.openSession(); + s.getTransaction().begin(); + DataPoint dp = (DataPoint) s.get( DataPoint.class, id ); + s.getTransaction().commit(); + s.close(); + return dp; + } + + public void updateNative(DataPoint dp) { + final Session s = sf.openSession(); + s.getTransaction().begin(); + s.update( dp ); + s.getTransaction().commit(); + s.close(); + } + + public void deleteNative() { + final Session s = sf.openSession(); + s.getTransaction().begin(); + s.createQuery( "delete from DataPoint" ).executeUpdate(); + s.getTransaction().commit(); + s.close(); + } + + public DataPoint lazyLoad(long id) { + final Session s = sf.openSession(); + s.getTransaction().begin(); + final DataPoint dp = (DataPoint) s.load( DataPoint.class, new Long( id ) ); + Hibernate.initialize( dp ); + s.getTransaction().commit(); + s.close(); + return dp; + } + + public TestIntegrator getTestIntegrator() { + return testIntegrator; + } + + public TestStrategyRegistrationProvider getTestStrategyRegistrationProvider() { + return testStrategyRegistrationProvider; + } + + public TestTypeContributor getTestTypeContributor() { + return testTypeContributor; + } +} diff --git a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestStrategyRegistrationProvider.java b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestStrategyRegistrationProvider.java index e59b5b198c3d..2b7c56caf7ae 100644 --- a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestStrategyRegistrationProvider.java +++ b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestStrategyRegistrationProvider.java @@ -30,10 +30,14 @@ */ public class TestStrategyRegistrationProvider implements StrategyRegistrationProvider { - public boolean passed = false; + private boolean passed = false; public Iterable getStrategyRegistrations() { passed = true; return Collections.EMPTY_LIST; } + + public boolean passed() { + return passed; + } } diff --git a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestTypeContributor.java b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestTypeContributor.java index a7999e60662b..8cf3e32894c3 100644 --- a/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestTypeContributor.java +++ b/hibernate-osgi/src/testClientBundle/java/org/hibernate/osgi/test/client/TestTypeContributor.java @@ -30,10 +30,14 @@ */ public class TestTypeContributor implements TypeContributor { - public boolean passed = false; + private boolean passed = false; public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { passed = true; } + + public boolean passed() { + return passed; + } } diff --git a/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestFailure.java b/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestFailure.java deleted file mode 100644 index 43a8da3fbe5e..000000000000 --- a/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestFailure.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.osgi.test.result; - -/** - * @author Brett Meyer - */ -public class OsgiTestFailure { - - private String failure; - - private Throwable cause; - - public OsgiTestFailure( String failure ) { - this.failure = failure; - } - - public OsgiTestFailure( String failure, Throwable cause ) { - this( failure ); - this.cause = cause; - } - - public String getFailure() { - return failure; - } - - public void setFailure(String failure) { - this.failure = failure; - } - - public Throwable getCause() { - return cause; - } - - public void setCause(Throwable cause) { - this.cause = cause; - } -} diff --git a/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestResults.java b/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestResults.java deleted file mode 100644 index bc464c9b08a7..000000000000 --- a/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestResults.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.osgi.test.result; - -import java.util.List; - - -/** - * Defines an OSGi service to provide test results to the main test class, without mucking up the classpath - * and causing ClassLoader issues. - * - * @author Brett Meyer - */ -public interface OsgiTestResults { - - public void addFailure(String failure); - - public void addFailure(String failure, Throwable cause); - - public List getFailures(); -} diff --git a/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestResultsImpl.java b/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestResultsImpl.java deleted file mode 100644 index 4cee397fbecc..000000000000 --- a/hibernate-osgi/src/testResult/java/org/hibernate/osgi/test/result/OsgiTestResultsImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * JBoss, Home of Professional Open Source - * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @authors tag. All rights reserved. - * See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU Lesser General Public License, v. 2.1. - * This program is distributed in the hope that it will be useful, but WITHOUT A - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License, - * v.2.1 along with this distribution; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -package org.hibernate.osgi.test.result; - -import java.util.ArrayList; -import java.util.List; - -/** - * Implementation of the OsgiTestResult OSGi service. - * - * @author Brett Meyer - */ -public class OsgiTestResultsImpl implements OsgiTestResults { - - private List failures = new ArrayList(); - - @Override - public void addFailure(String failure) { - failures.add( new OsgiTestFailure( failure ) ); - } - - @Override - public void addFailure(String failure, Throwable cause) { - failures.add( new OsgiTestFailure( failure, cause) ); - } - - @Override - public List getFailures() { - return failures; - } -} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java b/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java index 3616d96d187a..8a84aa4e8416 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java @@ -24,6 +24,7 @@ package org.hibernate.testing; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.spi.RowSelection; /** * Container class for different implementation of the {@link DialectCheck} interface. @@ -106,13 +107,15 @@ public boolean isMatch(Dialect dialect) { public static class SupportLimitCheck implements DialectCheck { public boolean isMatch(Dialect dialect) { - return dialect.supportsLimit(); + // TODO: Stupid -- better way? + return dialect.buildLimitHandler( "", new RowSelection() ).supportsLimit(); } } public static class SupportLimitAndOffsetCheck implements DialectCheck { public boolean isMatch(Dialect dialect) { - return dialect.supportsLimit() && dialect.supportsLimitOffset(); + // TODO: Stupid -- better way? + return dialect.buildLimitHandler( "", new RowSelection() ).supportsLimitOffset(); } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java b/hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java new file mode 100644 index 000000000000..7e2050d8875b --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/FailureExpectedWithNewMetamodel.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.testing; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to mark test classes or methods as expecting to fail when using the new metamodel introduced in 5.0. This annotation is + * only honored when the system property 'hibernate.test.new_metadata_mappings' is set to true. + */ +@Retention( RetentionPolicy.RUNTIME ) +@Target( { ElementType.METHOD, ElementType.TYPE } ) +public @interface FailureExpectedWithNewMetamodel { + + /** + * @return an optional JIRA issue key that covers the expected failure + */ + String jiraKey() default ""; + + /** + * @return an optional message related to the expected failure + */ + String message() default ""; +} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/PossibleLeaksLogger.java b/hibernate-testing/src/main/java/org/hibernate/testing/PossibleLeaksLogger.java new file mode 100644 index 000000000000..844497767174 --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/PossibleLeaksLogger.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.testing; + +import org.jboss.logging.Logger; + +/** + * Centralized logger (easier config) for logging possible test leaks + * + * @author Steve Ebersole + */ +public class PossibleLeaksLogger { + private static final Logger log = Logger.getLogger( PossibleLeaksLogger.class ); + + public static void logPossibleLeak(String message, String test) { + log.warn( "POSSIBLE LEAK [" + test + "] : " + message ); + } +} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/AfterClassCallbackHandler.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/AfterClassCallbackHandler.java index 5437a2a959c3..63cf9ab9f94f 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/AfterClassCallbackHandler.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/AfterClassCallbackHandler.java @@ -23,8 +23,13 @@ */ package org.hibernate.testing.junit4; +import org.hibernate.internal.SessionFactoryRegistry; + +import org.hibernate.testing.PossibleLeaksLogger; import org.junit.runners.model.Statement; +import org.jboss.logging.Logger; + /** * @author Steve Ebersole */ @@ -41,5 +46,12 @@ public AfterClassCallbackHandler(CustomRunner runner, Statement wrappedStatement public void evaluate() throws Throwable { wrappedStatement.evaluate(); runner.getTestClassMetadata().performAfterClassCallbacks( runner.getTestInstance() ); + if ( SessionFactoryRegistry.INSTANCE.hasRegistrations() ) { + PossibleLeaksLogger.logPossibleLeak( + "Possible SessionFactory leak", + runner.getTestClassMetadata().getTestClass().getName() + ); + SessionFactoryRegistry.INSTANCE.clearRegistrations(); + } } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseAnnotationBindingTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseAnnotationBindingTestCase.java new file mode 100644 index 000000000000..303346dd111b --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseAnnotationBindingTestCase.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.testing.junit4; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.metamodel.MetadataBuilder; +import org.hibernate.metamodel.MetadataSources; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import org.hibernate.metamodel.internal.MetadataImpl; +import org.hibernate.metamodel.spi.binding.EntityBinding; + +/** + * @author Hardy Ferentschik + */ +public abstract class BaseAnnotationBindingTestCase extends BaseUnitTestCase { + protected MetadataSources sources; + protected MetadataImpl meta; + protected List> annotatedClasses = new ArrayList>(); + + @Rule + public TestRule buildMetaData = new TestRule() { + @Override + public Statement apply(Statement base, Description description) { + return new KeepSetupFailureStatement( base, description ); + } + }; + + @After + public void tearDown() { + sources = null; + meta = null; + } + + public EntityBinding getEntityBinding(Class clazz) { + return meta.getEntityBinding( clazz.getName() ); + } + + public EntityBinding getRootEntityBinding(Class clazz) { + return meta.getRootEntityBinding( clazz.getName() ); + } + + public List> getAnnotatedClasses() { + return annotatedClasses; + } + + class KeepSetupFailureStatement extends Statement { + private final Statement origStatement; + private final Description description; + private Throwable setupError; + private boolean expectedException; + private StandardServiceRegistry serviceRegistry; + + KeepSetupFailureStatement(Statement statement, Description description) { + this.origStatement = statement; + this.description = description; + } + + @Override + public void evaluate() throws Throwable { + try { + createBindings(); + origStatement.evaluate(); + if ( setupError != null ) { + throw setupError; + } + } + catch ( Throwable t ) { + if ( setupError == null ) { + throw t; + } + else { + if ( !expectedException ) { + throw setupError; + } + } + } + finally { + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + serviceRegistry = null; + } + } + + private void createBindings() { + try { + serviceRegistry = new StandardServiceRegistryBuilder( ).build(); + sources = new MetadataSources( serviceRegistry ); + MetadataBuilder metadataBuilder = sources.getMetadataBuilder(); + Resources resourcesAnnotation = description.getAnnotation( Resources.class ); + if ( resourcesAnnotation != null ) { + metadataBuilder.with( resourcesAnnotation.cacheMode() ); + + for ( Class annotatedClass : resourcesAnnotation.annotatedClasses() ) { + annotatedClasses.add( annotatedClass ); + sources.addAnnotatedClass( annotatedClass ); + } + if ( !resourcesAnnotation.ormXmlPath().isEmpty() ) { + sources.addResource( resourcesAnnotation.ormXmlPath() ); + } + } + meta = ( MetadataImpl ) metadataBuilder.build(); + } + catch ( final Throwable t ) { + setupError = t; + Test testAnnotation = description.getAnnotation( Test.class ); + Class expected = testAnnotation.expected(); + if ( t.getClass().equals( expected ) ) { + expectedException = true; + } + } + } + } +} + + diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java index 8e2dc4d8c8be..fcef5b11e91b 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java @@ -23,13 +23,15 @@ */ package org.hibernate.testing.junit4; +import static org.junit.Assert.fail; + import java.io.InputStream; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; -import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; @@ -37,41 +39,43 @@ import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.Session; +import org.hibernate.TruthValue; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl; +import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Mappings; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.H2Dialect; +import org.hibernate.engine.config.internal.ConfigurationServiceImpl; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.jdbc.AbstractReturningWork; import org.hibernate.jdbc.Work; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.SimpleValue; import org.hibernate.metamodel.MetadataSources; -import org.hibernate.metamodel.source.MetadataImplementor; - +import org.hibernate.metamodel.SessionFactoryBuilder; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.testing.AfterClassOnce; import org.hibernate.testing.BeforeClassOnce; import org.hibernate.testing.OnExpectedFailure; import org.hibernate.testing.OnFailure; import org.hibernate.testing.SkipLog; import org.hibernate.testing.cache.CachingRegionFactory; +import org.hibernate.type.Type; import org.junit.After; import org.junit.Before; -import static org.junit.Assert.fail; - /** * Applies functional testing logic for core Hibernate testing on top of {@link BaseUnitTestCase} * @@ -80,26 +84,45 @@ @SuppressWarnings( {"deprecation"} ) public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { public static final String VALIDATE_DATA_CLEANUP = "hibernate.test.validateDataCleanup"; - public static final String USE_NEW_METADATA_MAPPINGS = "hibernate.test.new_metadata_mappings"; public static final Dialect DIALECT = Dialect.getDialect(); - private boolean isMetadataUsed; private Configuration configuration; private StandardServiceRegistryImpl serviceRegistry; private SessionFactoryImplementor sessionFactory; + private MetadataImplementor metadataImplementor; + private final boolean isMetadataUsed; protected Session session; + private List secondarySessions; protected static Dialect getDialect() { return DIALECT; } + protected BaseCoreFunctionalTestCase() { + // configure(Configuration) may add a setting for using the new metamodel, so, for now, + // build a dummy configuration to get all the property settings. + final Configuration dummyConfiguration = constructAndConfigureConfiguration(); + + // Can't build the ServiceRegistry until after the constructor executes + // (otherwise integrators don't get added). + // Create a dummy ConfigurationService just to find out if the new metamodel will be used. + final ConfigurationService dummyConfigurationService = new ConfigurationServiceImpl( + dummyConfiguration.getProperties() + ); + isMetadataUsed = true; + } + protected Configuration configuration() { return configuration; } - protected StandardServiceRegistryImpl serviceRegistry() { + protected MetadataImplementor metadata() { + return metadataImplementor; + } + + protected final StandardServiceRegistryImpl serviceRegistry() { return serviceRegistry; } @@ -108,54 +131,70 @@ protected SessionFactoryImplementor sessionFactory() { } protected Session openSession() throws HibernateException { + registerPreviousSessionIfNeeded( session ); session = sessionFactory().openSession(); return session; } + private void registerPreviousSessionIfNeeded(Session session) { + if ( session == null ) { + return; + } + + if ( !session.isOpen() ) { + return; + } + + registerSecondarySession( session ); + } + protected Session openSession(Interceptor interceptor) throws HibernateException { + registerPreviousSessionIfNeeded( session ); session = sessionFactory().withOptions().interceptor( interceptor ).openSession(); return session; } + protected Session openSecondarySession() throws HibernateException { + Session session = sessionFactory().openSession(); + registerSecondarySession( session ); + return session; + } + + protected void registerSecondarySession(Session session) { + if ( secondarySessions == null ) { + secondarySessions = new LinkedList(); + } + secondarySessions.add( session ); + } + // before/after test class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @BeforeClassOnce @SuppressWarnings( {"UnusedDeclaration"}) protected void buildSessionFactory() { - // for now, build the configuration to get all the property settings - configuration = constructAndConfigureConfiguration(); BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry(); + configuration = constructAndConfigureConfiguration(); serviceRegistry = buildServiceRegistry( bootRegistry, configuration ); - isMetadataUsed = serviceRegistry.getService( ConfigurationService.class ).getSetting( - USE_NEW_METADATA_MAPPINGS, - new ConfigurationService.Converter() { - @Override - public Boolean convert(Object value) { - return Boolean.parseBoolean( ( String ) value ); - } - }, - false - ); - if ( isMetadataUsed ) { - MetadataImplementor metadataImplementor = buildMetadata( bootRegistry, serviceRegistry ); - afterConstructAndConfigureMetadata( metadataImplementor ); - sessionFactory = ( SessionFactoryImplementor ) metadataImplementor.buildSessionFactory(); - } - else { - // this is done here because Configuration does not currently support 4.0 xsd - afterConstructAndConfigureConfiguration( configuration ); - sessionFactory = ( SessionFactoryImplementor ) configuration.buildSessionFactory( serviceRegistry ); + + metadataImplementor = buildMetadata(); + afterConstructAndConfigureMetadata( metadataImplementor ); + final SessionFactoryBuilder sessionFactoryBuilder = metadataImplementor.getSessionFactoryBuilder(); + if ( configuration.getInterceptor() != null ) { + sessionFactoryBuilder.with( configuration.getInterceptor() ); } + sessionFactory = (SessionFactoryImpl) sessionFactoryBuilder.build(); + afterSessionFactoryBuilt(); } + protected boolean isMetadataUsed() { + return isMetadataUsed; + } + protected void rebuildSessionFactory() { - if ( sessionFactory == null ) { - return; - } try { - sessionFactory.close(); + releaseSessionFactory(); } catch (Exception ignore) { } @@ -165,22 +204,73 @@ protected void rebuildSessionFactory() { protected void afterConstructAndConfigureMetadata(MetadataImplementor metadataImplementor) { + applyCacheSettings( metadataImplementor ); + } + public void applyCacheSettings(MetadataImplementor metadataImplementor) { + if ( !overrideCacheStrategy() || StringHelper.isEmpty( getCacheConcurrencyStrategy() ) ) { + return; + } + + for ( EntityBinding entityBinding : metadataImplementor.getEntityBindings() ) { + if ( entityBinding.getSuperEntityBinding() == null ) { + overrideEntityCache( entityBinding ); + } + overrideCollectionCachesForEntity( entityBinding ); + } } - private MetadataImplementor buildMetadata( - BootstrapServiceRegistry bootRegistry, - StandardServiceRegistryImpl serviceRegistry) { - MetadataSources sources = new MetadataSources( bootRegistry ); - addMappings( sources ); - return (MetadataImplementor) sources.getMetadataBuilder( serviceRegistry ).build(); + private void overrideEntityCache(EntityBinding entityBinding) { + boolean hasLob = false; + for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { + if ( attributeBinding.getAttribute().isSingular() ) { + Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping(); + String typeName = type.getName(); + if ( "blob".equals( typeName ) || "clob".equals( typeName ) ) { + hasLob = true; + break; + } + if ( Blob.class.getName().equals( typeName ) || Clob.class.getName().equals( typeName ) ) { + hasLob = true; + break; + } + } + } + if ( !hasLob && entityBinding.getSuperEntityBinding() == null ) { + entityBinding.getHierarchyDetails().getCaching().setRequested( TruthValue.TRUE ); + entityBinding.getHierarchyDetails().getCaching().setRegion( entityBinding.getEntityName() ); + entityBinding.getHierarchyDetails().getCaching().setCacheLazyProperties( true ); + entityBinding.getHierarchyDetails().getCaching().setAccessType( + AccessType.fromExternalName( + getCacheConcurrencyStrategy() + ) + ); + } } - // TODO: is this still needed? - protected Configuration buildConfiguration() { - Configuration cfg = constructAndConfigureConfiguration(); - afterConstructAndConfigureConfiguration( cfg ); - return cfg; + private void overrideCollectionCachesForEntity(EntityBinding entityBinding) { + for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { + if ( !attributeBinding.getAttribute().isSingular() ) { + AbstractPluralAttributeBinding binding = AbstractPluralAttributeBinding.class.cast( attributeBinding ); + + binding.getCaching().setRequested( TruthValue.TRUE ); + binding.getCaching().setRegion( + StringHelper.qualify( + entityBinding.getEntityName(), + attributeBinding.getAttribute().getName() + ) + ); + binding.getCaching().setCacheLazyProperties( true ); + binding.getCaching().setAccessType( AccessType.fromExternalName( getCacheConcurrencyStrategy() ) ); + } + } + } + + private MetadataImplementor buildMetadata() { + assert BootstrapServiceRegistry.class.isInstance( serviceRegistry.getParentServiceRegistry() ); + MetadataSources sources = new MetadataSources( serviceRegistry.getParentServiceRegistry() ); + addMappings( sources ); + return (MetadataImplementor) sources.getMetadataBuilder( serviceRegistry ).build(); } protected Configuration constructAndConfigureConfiguration() { @@ -189,13 +279,6 @@ protected Configuration constructAndConfigureConfiguration() { return cfg; } - private void afterConstructAndConfigureConfiguration(Configuration cfg) { - addMappings( cfg ); - cfg.buildMappings(); - applyCacheSettings( cfg ); - afterConfigurationBuilt( cfg ); - } - protected Configuration constructConfiguration() { Configuration configuration = new Configuration() .setProperty(Environment.CACHE_REGION_FACTORY, CachingRegionFactory.class.getName() ); @@ -217,37 +300,6 @@ protected Configuration constructConfiguration() { protected void configure(Configuration configuration) { } - protected void addMappings(Configuration configuration) { - String[] mappings = getMappings(); - if ( mappings != null ) { - for ( String mapping : mappings ) { - configuration.addResource( - getBaseForMappings() + mapping, - getClass().getClassLoader() - ); - } - } - Class[] annotatedClasses = getAnnotatedClasses(); - if ( annotatedClasses != null ) { - for ( Class annotatedClass : annotatedClasses ) { - configuration.addAnnotatedClass( annotatedClass ); - } - } - String[] annotatedPackages = getAnnotatedPackages(); - if ( annotatedPackages != null ) { - for ( String annotatedPackage : annotatedPackages ) { - configuration.addPackage( annotatedPackage ); - } - } - String[] xmlFiles = getXmlFiles(); - if ( xmlFiles != null ) { - for ( String xmlFile : xmlFiles ) { - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( xmlFile ); - configuration.addInputStream( is ); - } - } - } - protected void addMappings(MetadataSources sources) { String[] mappings = getMappings(); if ( mappings != null ) { @@ -303,36 +355,6 @@ protected String[] getXmlFiles() { return NO_MAPPINGS; } - protected void applyCacheSettings(Configuration configuration) { - if ( getCacheConcurrencyStrategy() != null ) { - Iterator itr = configuration.getClassMappings(); - while ( itr.hasNext() ) { - PersistentClass clazz = (PersistentClass) itr.next(); - Iterator props = clazz.getPropertyClosureIterator(); - boolean hasLob = false; - while ( props.hasNext() ) { - Property prop = (Property) props.next(); - if ( prop.getValue().isSimpleValue() ) { - String type = ( (SimpleValue) prop.getValue() ).getTypeName(); - if ( "blob".equals(type) || "clob".equals(type) ) { - hasLob = true; - } - if ( Blob.class.getName().equals(type) || Clob.class.getName().equals(type) ) { - hasLob = true; - } - } - } - if ( !hasLob && !clazz.isInherited() && overrideCacheStrategy() ) { - configuration.setCacheConcurrencyStrategy( clazz.getEntityName(), getCacheConcurrencyStrategy() ); - } - } - itr = configuration.getCollectionMappings(); - while ( itr.hasNext() ) { - Collection coll = (Collection) itr.next(); - configuration.setCollectionCacheConcurrencyStrategy( coll.getRole(), getCacheConcurrencyStrategy() ); - } - } - } protected boolean overrideCacheStrategy() { return true; @@ -343,7 +365,7 @@ protected String getCacheConcurrencyStrategy() { } protected void afterConfigurationBuilt(Configuration configuration) { - afterConfigurationBuilt( configuration.createMappings(), getDialect() ); +// afterConfigurationBuilt( configuration.createMappings(), getDialect() ); } protected void afterConfigurationBuilt(Mappings mappings, Dialect dialect) { @@ -400,10 +422,16 @@ protected void releaseSessionFactory() { sessionFactory.close(); sessionFactory = null; configuration = null; - if(serviceRegistry == null){ - return; - } - serviceRegistry.destroy(); + if ( serviceRegistry != null ) { + if ( serviceRegistry.isActive() ) { + try { + serviceRegistry.destroy(); + } + catch (Exception ignore) { + } + fail( "StandardServiceRegistry was not closed down as expected" ); + } + } serviceRegistry=null; } @@ -434,7 +462,12 @@ public final void afterTest() throws Exception { } cleanupTest(); - cleanupSession(); + cleanupSession( session ); + if ( secondarySessions != null ) { + for ( Session session: secondarySessions ) { + cleanupSession( session ); + } + } assertAllDataRemoved(); @@ -449,22 +482,33 @@ protected void cleanupCache() { protected boolean isCleanupTestDataRequired() { return false; } protected void cleanupTestData() throws Exception { - Session s = openSession(); - s.beginTransaction(); - s.createQuery( "delete from java.lang.Object" ).executeUpdate(); - s.getTransaction().commit(); - s.close(); + Session s = sessionFactory.openSession(); + try { + s.beginTransaction(); + try { + s.createQuery( "delete from java.lang.Object" ).executeUpdate(); + s.getTransaction().commit(); + } + catch (Exception e) { + try { + s.doWork( new RollbackWork() ); + } + catch (Exception ignore) { + } + } + } + finally { + s.close(); + } } - - private void cleanupSession() { + private void cleanupSession(Session session) { if ( session != null && ! ( (SessionImplementor) session ).isClosed() ) { if ( session.isConnected() ) { session.doWork( new RollbackWork() ); } session.close(); } - session = null; } public class RollbackWork implements Work { diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java index 4959fdc89f71..ebd86d87a6ec 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseUnitTestCase.java @@ -26,16 +26,15 @@ import javax.transaction.SystemException; import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper; - +import org.hibernate.metamodel.MetadataSources; import org.hibernate.testing.jta.TestingJtaPlatformImpl; +import org.jboss.logging.Logger; import org.junit.After; import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.junit.runner.RunWith; -import org.jboss.logging.Logger; - /** * The base unit test adapter. * diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java index d24466d62b12..d33dd0614756 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BeforeClassCallbackHandler.java @@ -25,6 +25,9 @@ import org.junit.runners.model.Statement; +import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; + /** * @author Steve Ebersole */ @@ -39,7 +42,16 @@ public BeforeClassCallbackHandler(CustomRunner runner, Statement wrappedStatemen @Override public void evaluate() throws Throwable { - runner.getTestClassMetadata().performBeforeClassCallbacks( runner.getTestInstance() ); - wrappedStatement.evaluate(); + try { + runner.getTestClassMetadata().performBeforeClassCallbacks( runner.getTestInstance() ); + wrappedStatement.evaluate(); + } + catch ( Throwable error ) { + runner.setBeforeClassMethodFailed(); + if ( runner.getTestClass().getJavaClass().getAnnotation( FailureExpected.class ) == null + && runner.getTestClass().getJavaClass().getAnnotation( FailureExpectedWithNewMetamodel.class ) == null ) { + throw error; + } + } } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java index fb286422cc4a..ff43366e98e2 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java @@ -35,6 +35,7 @@ import org.hibernate.testing.DialectCheck; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.RequiresDialects; @@ -64,6 +65,7 @@ public class CustomRunner extends BlockJUnit4ClassRunner { private static final Logger log = Logger.getLogger( CustomRunner.class ); private TestClassMetadata testClassMetadata; + private boolean beforeClassMethodFailed; public CustomRunner(Class clazz) throws InitializationError, NoTestsRemainException { super( clazz ); @@ -76,6 +78,14 @@ protected void collectInitializationErrors(List errors) { testClassMetadata.validate( errors ); } + boolean beforeClassMethodFailed() { + return beforeClassMethodFailed; + } + + void setBeforeClassMethodFailed() { + beforeClassMethodFailed = true; + } + public TestClassMetadata getTestClassMetadata() { return testClassMetadata; } @@ -123,15 +133,15 @@ protected Statement withAfterClasses(Statement statement) { ); } - /** - * {@inheritDoc} - * - * @see org.junit.runners.ParentRunner#classBlock(org.junit.runner.notification.RunNotifier) - */ @Override protected Statement classBlock( RunNotifier notifier ) { log.info( BeforeClass.class.getSimpleName() + ": " + getName() ); + if ( getTestClass().getJavaClass().getAnnotation( FailureExpected.class ) != null + || getTestClass().getJavaClass().getAnnotation( FailureExpectedWithNewMetamodel.class ) != null ) { + log.info( FailureExpected.class.getSimpleName() ); + } + return super.classBlock( notifier ); } @@ -139,9 +149,15 @@ protected Statement classBlock( RunNotifier notifier ) { protected Statement methodBlock(FrameworkMethod method) { log.info( Test.class.getSimpleName() + ": " + method.getName() ); + if ( method.getAnnotation( FailureExpected.class ) != null + || method.getAnnotation( FailureExpectedWithNewMetamodel.class ) != null ) { + log.info( FailureExpected.class.getSimpleName() ); + } + + final Statement originalMethodBlock = super.methodBlock( method ); final ExtendedFrameworkMethod extendedFrameworkMethod = (ExtendedFrameworkMethod) method; - return new FailureExpectedHandler( originalMethodBlock, testClassMetadata, extendedFrameworkMethod, testInstance ); + return new FailureExpectedHandler( this, originalMethodBlock, testClassMetadata, extendedFrameworkMethod, testInstance ); } private Object testInstance; @@ -193,8 +209,16 @@ protected List doComputation() { Ignore virtualIgnore; for ( FrameworkMethod frameworkMethod : methods ) { + FailureExpected failureExpected = Helper.locateAnnotation( FailureExpected.class, frameworkMethod, getTestClass() ); + if ( failureExpected == null ) { + // see if there is a FailureExpectedWithNewMetamodel, and if so treat it like FailureExpected + final FailureExpectedWithNewMetamodel failureExpectedWithNewMetamodel + = Helper.locateAnnotation( FailureExpectedWithNewMetamodel.class, frameworkMethod, getTestClass() ); + if ( failureExpectedWithNewMetamodel != null ) { + failureExpected = new FailureExpectedWithNewMetamodelAdapter( failureExpectedWithNewMetamodel ); + } + } // potentially ignore based on expected failure - final FailureExpected failureExpected = Helper.locateAnnotation( FailureExpected.class, frameworkMethod, getTestClass() ); if ( failureExpected != null && !doValidation ) { virtualIgnore = new IgnoreImpl( Helper.extractIgnoreMessage( failureExpected, frameworkMethod ) ); } @@ -209,25 +233,6 @@ protected List doComputation() { return result; } - @SuppressWarnings( {"ClassExplicitlyAnnotation"}) - public static class IgnoreImpl implements Ignore { - private final String value; - - public IgnoreImpl(String value) { - this.value = value; - } - - @Override - public String value() { - return value; - } - - @Override - public Class annotationType() { - return Ignore.class; - } - } - private static Dialect dialect = determineDialect(); private static Dialect determineDialect() { @@ -353,4 +358,45 @@ private MatcherInstantiationException(Class matcherClass } } + @SuppressWarnings( {"ClassExplicitlyAnnotation"}) + public static class IgnoreImpl implements Ignore { + private final String value; + + public IgnoreImpl(String value) { + this.value = value; + } + + @Override + public String value() { + return value; + } + + @Override + public Class annotationType() { + return Ignore.class; + } + } + + @SuppressWarnings("ClassExplicitlyAnnotation") + private class FailureExpectedWithNewMetamodelAdapter implements FailureExpected { + private final FailureExpectedWithNewMetamodel failureExpectedWithNewMetamodel; + + public FailureExpectedWithNewMetamodelAdapter(FailureExpectedWithNewMetamodel failureExpectedWithNewMetamodel) { + this.failureExpectedWithNewMetamodel = failureExpectedWithNewMetamodel; + } + @Override + public Class< ? extends Annotation > annotationType() { + return FailureExpected.class; + } + + @Override + public String message() { + return failureExpectedWithNewMetamodel.message(); + } + + @Override + public String jiraKey() { + return failureExpectedWithNewMetamodel.jiraKey(); + } + } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java index 9e0a75a9412a..1040bcc23fe2 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/FailureExpectedHandler.java @@ -35,16 +35,19 @@ class FailureExpectedHandler extends Statement { private static final Logger log = Logger.getLogger( FailureExpectedHandler.class ); + private final CustomRunner runner; private final TestClassMetadata testClassMetadata; private final ExtendedFrameworkMethod extendedFrameworkMethod; private final Statement realInvoker; private final Object testInstance; public FailureExpectedHandler( + CustomRunner runner, Statement realInvoker, TestClassMetadata testClassMetadata, ExtendedFrameworkMethod extendedFrameworkMethod, Object testInstance) { + this.runner = runner; this.realInvoker = realInvoker; this.testClassMetadata = testClassMetadata; this.extendedFrameworkMethod = extendedFrameworkMethod; @@ -53,6 +56,9 @@ public FailureExpectedHandler( @Override public void evaluate() throws Throwable { + if ( runner.beforeClassMethodFailed() ) { + return; + } final FailureExpected failureExpected = extendedFrameworkMethod.getFailureExpectedAnnotation(); try { realInvoker.evaluate(); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/Resources.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/Resources.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/Resources.java rename to hibernate-testing/src/main/java/org/hibernate/testing/junit4/Resources.java index f5f0fd3b9b22..8c68b9285724 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/Resources.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/Resources.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.metamodel.source.annotations.entity; +package org.hibernate.testing.junit4; import java.lang.annotation.Retention; import java.lang.annotation.Target; diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/TestClassMetadata.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/TestClassMetadata.java index aea68ca3f764..b1a6da8c4bb1 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/TestClassMetadata.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/TestClassMetadata.java @@ -42,12 +42,15 @@ public class TestClassMetadata { private static final Object[] NO_ARGS = new Object[0]; + private Class testClass; + private LinkedHashSet beforeClassOnceMethods; private LinkedHashSet afterClassOnceMethods; private LinkedHashSet onFailureCallbacks; private LinkedHashSet onExpectedFailureCallbacks; public TestClassMetadata(Class testClass) { + this.testClass = testClass; processClassHierarchy( testClass ); } @@ -74,6 +77,10 @@ private void processClassHierarchy(Class testClass) { } } + public Class getTestClass() { + return testClass; + } + private void addBeforeClassOnceCallback(Method method) { if ( beforeClassOnceMethods == null ) { beforeClassOnceMethods = new LinkedHashSet(); @@ -83,13 +90,11 @@ private void addBeforeClassOnceCallback(Method method) { } private void ensureAccessibility(Method method) { - if ( !method.isAccessible() ) { - try { - method.setAccessible( true ); - } - catch (Exception ignored) { - // ignore for now - } + try { + method.setAccessible( true ); + } + catch (Exception ignored) { + // ignore for now } } @@ -141,17 +146,15 @@ private void validateCallbackMethod(Method method, CallbackType type, List project.buildFileName = "${project.name}.gradle" diff --git a/tooling/hibernate-enhance-maven-plugin/hibernate-enhance-maven-plugin.gradle b/tooling/hibernate-enhance-maven-plugin/hibernate-enhance-maven-plugin.gradle new file mode 100644 index 000000000000..6c8b0568d78b --- /dev/null +++ b/tooling/hibernate-enhance-maven-plugin/hibernate-enhance-maven-plugin.gradle @@ -0,0 +1,112 @@ +apply plugin: 'java' +apply plugin: 'maven' + +import org.apache.tools.ant.filters.ReplaceTokens + +group = 'org.hibernate.orm.tooling' + +repositories { + mavenCentral() +} + +processResources.doLast { + project.build.outputDirectory = '${project.build.outputDirectory}' + copy { + from 'src/main/resources' + into processResources.destinationDir + expand ([ version: version, project: project, dir: '${dir}' ]) + } +} + +dependencies { + compile( libraries.maven_plugin ) { transitive = false } + compile( libraries.maven_plugin_tools ) { transitive = false } + compile( project(':hibernate-core') ) { transitive = false } + compile( libraries.jpa ) { transitive = false } + compile( libraries.javassist ) { transitive = false } + compile 'org.codehaus.plexus:plexus-utils:3.0.1' + runtime( libraries.maven_plugin ) + runtime( libraries.maven_plugin_tools ) + runtime( project(':hibernate-core') ) + runtime( libraries.jpa ) + runtime( libraries.javassist ) + runtime 'org.codehaus.plexus:plexus-utils:3.0.1' +} + +// Inject dependencies into plugin.xml +// Note: injecting the full dependency, rather than just the version, +// removing the need to maintain artifact names that might change with upgrades (JPA/JTA API version, etc.) +task processPluginXml(type: Copy) { + // force out-of-date if version changes + inputs.property("version", project.version) + + from "src/main/resources/META-INF/maven/plugin.xml.original" + into "src/main/resources/META-INF/maven" + rename ("plugin.xml.original", "plugin.xml") + filter(ReplaceTokens, tokens: ['generated-dependencies' :\ + generateMavenDependency(libraries.jpa)\ + + generateMavenDependency(libraries.antlr)\ + + generateMavenDependency(libraries.dom4j)\ + + generateMavenDependency(libraries.jta)\ + + generateMavenDependency(libraries.commons_annotations)\ + + generateMavenDependency(libraries.javassist)\ + + generateMavenDependency(libraries.logging)\ + + generateMavenDependency("org.hibernate:hibernate-core:" + project.version)]) +} + +// TODO: There may be a way to do this directly with Gradle's Maven plugin, but it's still incubating +// and I'd rather not rely on it yet. +def generateMavenDependency(String gradleDependency) { + String[] split = gradleDependency.split(":") + return \ + ""\ + + "" + split[0] + ""\ + + "" + split[1] + ""\ + + "jar"\ + + "" + split[2] + ""\ + + "\n" +} + +task writeNewPom(type:Task, description: 'Writes pom.xml using merged Gradle dependency and MavenPom configuration.') { + ext.pomDefinition = pom { + configurations { + // avoiding test dependencies in generated pom + compile + runtime + } + + project { + groupId project.group + packaging 'maven-plugin' + name 'Enhance Plugin of the Hibernate project for use with Maven build system.' + build { + plugins { + plugin { + groupId 'org.apache.maven.plugins' + artifactId 'maven-plugin-plugin' + version '3.2' + configuration { + skipErrorNoDescriptorsFound 'true' + } + executions { + execution { + id 'mojo-descriptor' + goals { + goal 'descriptor' + } + } + } + } + } + } + properties { + 'project.build.sourceEncoding' 'UTF-8' + } + } + } + ext.pomDefinition.writeTo("$projectDir/src/main/resources/pom.xml") +} + +writeNewPom.dependsOn processPluginXml +processResources.dependsOn writeNewPom + diff --git a/tooling/hibernate-enhance-maven-plugin/src/main/java/org/hibernate/bytecode/enhance/plugins/MavenEnhancePlugin.java b/tooling/hibernate-enhance-maven-plugin/src/main/java/org/hibernate/bytecode/enhance/plugins/MavenEnhancePlugin.java new file mode 100644 index 000000000000..ae72e39422b8 --- /dev/null +++ b/tooling/hibernate-enhance-maven-plugin/src/main/java/org/hibernate/bytecode/enhance/plugins/MavenEnhancePlugin.java @@ -0,0 +1,270 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.bytecode.enhance.plugins; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtField; + +import javax.persistence.ElementCollection; +import javax.persistence.Embeddable; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import javax.persistence.Transient; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.hibernate.bytecode.enhance.spi.EnhancementContext; +import org.hibernate.bytecode.enhance.spi.Enhancer; + +/** + * This plugin will enhance Entity objects. + * + * @author Jeremy Whiting + * @phase "compile" + */ +@Mojo ( name="enhance", defaultPhase = LifecyclePhase.COMPILE ) +@Execute ( goal ="enhance" , phase = LifecyclePhase.COMPILE ) +public class MavenEnhancePlugin extends AbstractMojo implements EnhancementContext { + + /** + * The contexts to use during enhancement. + */ + private List classes = new ArrayList(); + private ClassPool pool = new ClassPool( false ); + private final Enhancer enhancer = new Enhancer( this); + + private static final String CLASS_EXTENSION = ".class"; + + @Parameter(property="dir", defaultValue="${project.build.outputDirectory}") + private String dir = null; + + public void execute() throws MojoExecutionException, MojoFailureException { + getLog().info( "Started enhance plugin....." ); + /** Perform a depth first search for files. */ + File root = new File( this.dir ); + walkDir( root ); + + if ( 0 < classes.size() ) { + for ( File file : classes ) { + processClassFile(file); + } + } + + getLog().info( "Enhance plugin completed." ); + } + + /** + * Expects a directory. + */ + private void walkDir(File dir) { + + walkDir( dir, new FileFilter() { + + @Override + public boolean accept(File pathname) { + return ( pathname.isFile() && pathname.getName().endsWith( CLASS_EXTENSION ) ); + } + }, new FileFilter() { + + @Override + public boolean accept(File pathname) { + return ( pathname.isDirectory() ); + } + } ); + } + + private void walkDir(File dir, FileFilter classesFilter, FileFilter dirFilter) { + + File[] dirs = dir.listFiles( dirFilter ); + for ( int i = 0; i < dirs.length; i++ ) { + walkDir( dirs[i], classesFilter, dirFilter ); + } + dirs = null; + File[] files = dir.listFiles( classesFilter ); + for ( int i = 0; i < files.length; i++ ) { + this.classes.add( files[i] ); + } + } + + + /** + * Atm only process files annotated with either @Entity or @Embeddable + * @param javaClassFile + */ + private void processClassFile(File javaClassFile) + throws MojoExecutionException { + try { + final CtClass ctClass = getClassPool().makeClass( new FileInputStream( javaClassFile ) ); + if(this.isEntityClass(ctClass)) + processEntityClassFile(javaClassFile, ctClass); + else if(this.isCompositeClass(ctClass)) + processCompositeClassFile(javaClassFile, ctClass); + + } + catch (IOException e) { + throw new MojoExecutionException( + String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ), e ); + } + } + + private void processEntityClassFile(File javaClassFile, CtClass ctClass ) { + try { + getLog().info( String.format("Processing Entity class file [%1$s].", ctClass.getName()) ); + byte[] result = enhancer.enhance( ctClass.getName(), ctClass.toBytecode() ); + if(result != null) + writeEnhancedClass(javaClassFile, result); + } + catch (Exception e) { + getLog().error( "Unable to enhance class [" + ctClass.getName() + "]", e); + return; + } + } + + private void processCompositeClassFile(File javaClassFile, CtClass ctClass) { + try { + getLog().info( String.format("Processing Composite class file [%1$s].", ctClass.getName()) ); + byte[] result = enhancer.enhanceComposite(ctClass.getName(), ctClass.toBytecode()); + if(result != null) + writeEnhancedClass(javaClassFile, result); + } + catch (Exception e) { + getLog().error( "Unable to enhance class [" + ctClass.getName() + "]", e); + return; + } + } + + private void writeEnhancedClass(File javaClassFile, byte[] result) + throws MojoExecutionException { + try { + if ( javaClassFile.delete() ) { + if ( ! javaClassFile.createNewFile() ) { + getLog().error( "Unable to recreate class file [" + javaClassFile.getName() + "]"); + } + } + else { + getLog().error( "Unable to delete class file [" + javaClassFile.getName() + "]"); + } + + FileOutputStream outputStream = new FileOutputStream( javaClassFile, false ); + try { + outputStream.write( result); + outputStream.flush(); + } + finally { + try { + outputStream.close(); + } + catch ( IOException ignore) { + } + } + } + catch (FileNotFoundException ignore) { + // should not ever happen because of explicit checks + } + catch (IOException e) { + throw new MojoExecutionException( + String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ), e ); + } + } + + private ClassPool getClassPool() { + return this.pool; + } + + private boolean shouldInclude(CtClass ctClass) { + // we currently only handle entity enhancement + return ctClass.hasAnnotation( Entity.class ); + } + + @Override + public ClassLoader getLoadingClassLoader() { + return getClass().getClassLoader(); + } + + @Override + public boolean isEntityClass(CtClass classDescriptor) { + return classDescriptor.hasAnnotation(Entity.class); + } + + @Override + public boolean isCompositeClass(CtClass classDescriptor) { + return classDescriptor.hasAnnotation(Embeddable.class); + } + + @Override + public boolean doDirtyCheckingInline(CtClass classDescriptor) { + return true; + } + + @Override + public boolean hasLazyLoadableAttributes(CtClass classDescriptor) { + return true; + } + + @Override + public boolean isLazyLoadable(CtField field) { + return true; + } + + @Override + public boolean isPersistentField(CtField ctField) { + // current check is to look for @Transient + return ! ctField.hasAnnotation( Transient.class ); + } + + @Override + public boolean isMappedCollection(CtField field) { + try { + return (field.getAnnotation(OneToMany.class) != null || + field.getAnnotation(ManyToMany.class) != null || + field.getAnnotation(ElementCollection.class) != null); + } + catch (ClassNotFoundException e) { + return false; + } + } + + @Override + public CtField[] order(CtField[] persistentFields) { + // for now... + return persistentFields; + // eventually needs to consult the Hibernate metamodel for proper ordering + } +} diff --git a/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/org.hibernate.orm.tooling/hibernate-enhance-maven-plugin/plugin-help.xml b/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/org.hibernate.orm.tooling/hibernate-enhance-maven-plugin/plugin-help.xml new file mode 100644 index 000000000000..d9e84b3ceafa --- /dev/null +++ b/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/org.hibernate.orm.tooling/hibernate-enhance-maven-plugin/plugin-help.xml @@ -0,0 +1,44 @@ + + + + + + Enhance Plugin of the Hibernate project for use with Maven build system. + + org.hibernate.orm.tooling + hibernate-enhance-maven-plugin + ${version} + hibernate-enhance + + + enhance + This plugin will enhance Entity objects. + false + true + false + false + false + true + compile + compile + enhance + org.hibernate.bytecode.enhance.plugins.MavenEnhancePlugin + java + per-lookup + once-per-session + false + + + dir + java.lang.String + false + true + + + + + ${dir} + + + + \ No newline at end of file diff --git a/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/org.hibernate.orm.tooling/plugin-help.xml b/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/org.hibernate.orm.tooling/plugin-help.xml new file mode 100644 index 000000000000..00fc267a80e4 --- /dev/null +++ b/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/org.hibernate.orm.tooling/plugin-help.xml @@ -0,0 +1,13 @@ + + + + + + Enhance Plugin of the Hibernate project for use with Maven build system. + + org.hibernate.orm.tooling + hibernate-enhance-maven-plugin + ${version} + hibernate-enhance + + \ No newline at end of file diff --git a/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/plugin.xml.original b/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/plugin.xml.original new file mode 100644 index 000000000000..08aea627582d --- /dev/null +++ b/tooling/hibernate-enhance-maven-plugin/src/main/resources/META-INF/maven/plugin.xml.original @@ -0,0 +1,117 @@ + + + + + + Enhance Plugin of the Hibernate project for use with Maven build system. + + org.hibernate.orm.tooling + hibernate-enhance-maven-plugin + ${version} + hibernate-enhance + false + true + + + enhance + This plugin will enhance Entity objects. + false + true + false + false + false + true + compile + compile + enhance + org.hibernate.bytecode.enhance.plugins.MavenEnhancePlugin + java + per-lookup + once-per-session + false + + + dir + java.lang.String + false + true + + + + + ${dir} + + + + + + @generated-dependencies@ + + + org.codehaus.plexus + plexus-utils + jar + 3.0.1 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + jar + 3.2 + + + org.apache.maven + maven-artifact + jar + 3.0 + + + org.apache.maven + maven-plugin-api + jar + 3.0.5 + + + org.apache.maven + maven-model + jar + 3.0.5 + + + org.sonatype.sisu + sisu-inject-plexus + jar + 2.3.0 + + + org.codehaus.plexus + plexus-component-annotations + jar + 1.5.5 + + + org.codehaus.plexus + plexus-classworlds + jar + 2.4 + + + org.sonatype.sisu + sisu-inject-bean + jar + 2.3.0 + + + org.sonatype.sisu + sisu-guice + jar + 3.1.0 + + + org.sonatype.sisu + sisu-guava + jar + 0.9.9 + + + diff --git a/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle b/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle deleted file mode 100644 index 0dbbc2742cab..000000000000 --- a/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'java' -apply plugin: 'maven' - -repositories { - mavenCentral() -} - -dependencies { - compile( libraries.maven_plugin ) - compile( libraries.maven_plugin_tools ) - compile( project(':hibernate-core') ) - compile( libraries.jpa ) - compile( libraries.javassist ) -} diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/bytecode/enhance/plugins/HibernateEnhancementMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/bytecode/enhance/plugins/HibernateEnhancementMojo.java deleted file mode 100644 index e7cb21a044a5..000000000000 --- a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/bytecode/enhance/plugins/HibernateEnhancementMojo.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2013, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.bytecode.enhance.plugins; - -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.persistence.ElementCollection; -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.ManyToMany; -import javax.persistence.OneToMany; -import javax.persistence.Transient; - -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtField; - -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; - -import org.hibernate.bytecode.enhance.spi.EnhancementContext; -import org.hibernate.bytecode.enhance.spi.Enhancer; - -/** - * This plugin will enhance Entity objects. - * - * @author Jeremy Whiting - */ -@Mojo(name = "enhance") -public class HibernateEnhancementMojo extends AbstractMojo implements EnhancementContext { - - /** - * The contexts to use during enhancement. - */ - private List classes = new ArrayList(); - private ClassPool pool = new ClassPool( false ); - private final Enhancer enhancer = new Enhancer( this); - - private static final String CLASS_EXTENSION = ".class"; - - @Parameter(property="dir", defaultValue="${project.build.outputDirectory}") - private String dir; - - public void execute() throws MojoExecutionException, MojoFailureException { - getLog().info( "Started enhance plugin....." ); - /** Perform a depth first search for files. */ - File root = new File( this.dir ); - walkDir( root ); - - if ( 0 < classes.size() ) { - for ( File file : classes ) { - processClassFile(file); - } - } - - getLog().info( "Enhance plugin completed." ); - } - - /** - * Expects a directory. - */ - private void walkDir(File dir) { - - walkDir( dir, new FileFilter() { - - @Override - public boolean accept(File pathname) { - return ( pathname.isFile() && pathname.getName().endsWith( CLASS_EXTENSION ) ); - } - }, new FileFilter() { - - @Override - public boolean accept(File pathname) { - return ( pathname.isDirectory() ); - } - } ); - } - - private void walkDir(File dir, FileFilter classesFilter, FileFilter dirFilter) { - - File[] dirs = dir.listFiles( dirFilter ); - for ( int i = 0; i < dirs.length; i++ ) { - walkDir( dirs[i], classesFilter, dirFilter ); - } - dirs = null; - File[] files = dir.listFiles( classesFilter ); - for ( int i = 0; i < files.length; i++ ) { - this.classes.add( files[i] ); - } - } - - - /** - * Atm only process files annotated with either @Entity or @Embeddable - * @param javaClassFile - */ - private void processClassFile(File javaClassFile) - throws MojoExecutionException { - try { - final CtClass ctClass = getClassPool().makeClass( new FileInputStream( javaClassFile ) ); - if(this.isEntityClass(ctClass)) - processEntityClassFile(javaClassFile, ctClass); - else if(this.isCompositeClass(ctClass)) - processCompositeClassFile(javaClassFile, ctClass); - - } - catch (IOException e) { - throw new MojoExecutionException( - String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ), e ); - } - } - - private void processEntityClassFile(File javaClassFile, CtClass ctClass ) { - try { - byte[] result = enhancer.enhance( ctClass.getName(), ctClass.toBytecode() ); - if(result != null) - writeEnhancedClass(javaClassFile, result); - } - catch (Exception e) { - getLog().error( "Unable to enhance class [" + ctClass.getName() + "]", e); - return; - } - } - - private void processCompositeClassFile(File javaClassFile, CtClass ctClass) { - try { - byte[] result = enhancer.enhanceComposite(ctClass.getName(), ctClass.toBytecode()); - if(result != null) - writeEnhancedClass(javaClassFile, result); - } - catch (Exception e) { - getLog().error( "Unable to enhance class [" + ctClass.getName() + "]", e); - return; - } - } - - private void writeEnhancedClass(File javaClassFile, byte[] result) - throws MojoExecutionException { - try { - if ( javaClassFile.delete() ) { - if ( ! javaClassFile.createNewFile() ) { - getLog().error( "Unable to recreate class file [" + javaClassFile.getName() + "]"); - } - } - else { - getLog().error( "Unable to delete class file [" + javaClassFile.getName() + "]"); - } - - FileOutputStream outputStream = new FileOutputStream( javaClassFile, false ); - try { - outputStream.write( result); - outputStream.flush(); - } - finally { - try { - outputStream.close(); - } - catch ( IOException ignore) { - } - } - } - catch (FileNotFoundException ignore) { - // should not ever happen because of explicit checks - } - catch (IOException e) { - throw new MojoExecutionException( - String.format( "Error processing included file [%s]", javaClassFile.getAbsolutePath() ), e ); - } - } - - private ClassPool getClassPool() { - return this.pool; - } - - private boolean shouldInclude(CtClass ctClass) { - // we currently only handle entity enhancement - return ctClass.hasAnnotation( Entity.class ); - } - - @Override - public ClassLoader getLoadingClassLoader() { - return getClass().getClassLoader(); - } - - @Override - public boolean isEntityClass(CtClass classDescriptor) { - return classDescriptor.hasAnnotation(Entity.class); - } - - @Override - public boolean isCompositeClass(CtClass classDescriptor) { - return classDescriptor.hasAnnotation(Embeddable.class); - } - - @Override - public boolean doDirtyCheckingInline(CtClass classDescriptor) { - return true; - } - - @Override - public boolean hasLazyLoadableAttributes(CtClass classDescriptor) { - return true; - } - - @Override - public boolean isLazyLoadable(CtField field) { - return true; - } - - @Override - public boolean isPersistentField(CtField ctField) { - // current check is to look for @Transient - return ! ctField.hasAnnotation( Transient.class ); - } - - @Override - public boolean isMappedCollection(CtField field) { - try { - return (field.getAnnotation(OneToMany.class) != null || - field.getAnnotation(ManyToMany.class) != null || - field.getAnnotation(ElementCollection.class) != null); - } - catch (ClassNotFoundException e) { - return false; - } - } - - @Override - public CtField[] order(CtField[] persistentFields) { - // for now... - return persistentFields; - // eventually needs to consult the Hibernate metamodel for proper ordering - } -} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/sortedcollection/Printer.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/sortedcollection/Printer.java index dd0218f2d786..e1a918547eaf 100644 --- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/sortedcollection/Printer.java +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/sortedcollection/Printer.java @@ -30,7 +30,7 @@ import javax.persistence.Id; import javax.persistence.OneToMany; -import org.hibernate.annotations.Sort; +import org.hibernate.annotations.SortNatural; /** * @author Hardy Ferentschik @@ -42,11 +42,11 @@ public class Printer { private long id; @OneToMany - @Sort + @SortNatural private SortedSet printQueue; @OneToMany - @Sort + @SortNatural private SortedMap printedJobs; }